Browse Source

Merge pull request #2 from bsmg/master

Merge upstream into fork
pull/50/head
Eris 3 years ago
committed by GitHub
parent
commit
540b3a379a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 934 additions and 1454 deletions
  1. +19
    -0
      .github/release_draft.yml
  2. +44
    -0
      .github/workflows/build.yml
  3. +1
    -1
      .github/workflows/docs.yml
  4. +48
    -78
      BSIPA-Meta/BSIPA-Meta.csproj
  5. +132
    -239
      BSIPA.sln
  6. +106
    -155
      IPA.Injector/IPA.Injector.csproj
  7. +1
    -1
      IPA.Loader/Config/SelfConfig.cs
  8. +27
    -172
      IPA.Loader/IPA.Loader.csproj
  9. +31
    -0
      IPA.Loader/JsonConverters/FeaturesFieldConverter.cs
  10. +20
    -9
      IPA.Loader/Loader/Features/ConfigProviderFeature.cs
  11. +49
    -21
      IPA.Loader/Loader/Features/DefineFeature.cs
  12. +97
    -50
      IPA.Loader/Loader/Features/Feature.cs
  13. +0
    -105
      IPA.Loader/Loader/Features/InitInjectorFeature.cs
  14. +0
    -12
      IPA.Loader/Loader/Features/NoUpdateFeature.cs
  15. +0
    -32
      IPA.Loader/Loader/Features/PrintFeature.cs
  16. +78
    -77
      IPA.Loader/Loader/PluginLoader.cs
  17. +23
    -5
      IPA.Loader/Loader/PluginManager.cs
  18. +3
    -2
      IPA.Loader/Loader/PluginManifest.cs
  19. +4
    -0
      IPA.Loader/Loader/PluginMetadata.cs
  20. +10
    -12
      IPA.Loader/Loader/manifest.json
  21. BIN
      IPA.Loader/Thumbs.db
  22. +0
    -15
      IPA.Loader/Updating/BeatMods/Updater.cs
  23. +8
    -2
      IPA.Loader/Utilities/Async/Coroutines.cs
  24. +180
    -180
      IPA.Loader/Utilities/CriticalSection.cs
  25. +1
    -1
      IPA/Program.cs
  26. +41
    -41
      Net3-Proxy/CompilerServices.cs
  27. +9
    -60
      Net3-Proxy/Net3-Proxy.csproj
  28. +2
    -2
      README.md
  29. +0
    -182
      appveyor.yml

+ 19
- 0
.github/release_draft.yml View File

@ -0,0 +1,19 @@
name-template: 'BSIPA $RESOLVED_VERSION'
tag-template: '$RESOLVED_VERSION'
categories:
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
version-resolver:
major:
labels:
- 'major'
minor:
labels:
- 'minor'
patch:
labels:
- 'patch'
default: patch
template: |
[*All Changes*](https://github.com/bsmg/BeatSaber-IPA-Reloaded/compare/$PREVIOUS_TAG...$RESOLVED_VERSION)
[*Documentation Permalink*](https://bsmg.github.io/BeatSaber-IPA-Reloaded/tags/$RESOLVED_VERSION/index.html)

+ 44
- 0
.github/workflows/build.yml View File

@ -0,0 +1,44 @@
name: Build
on:
push:
branches-ignore:
- gh-pages
pull_request:
branches:
- master
defaults:
run:
shell: pwsh
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
platform: ["x86", "x64"]
env:
Configuration: Release
Platform: ${{ matrix.platform }}
steps:
- name: Checkout branch
uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Locate MSBuild
uses: warrenbuckley/Setup-MSBuild@v1
- name: Restore
run: msbuild -t:Restore -m
- name: Build
run: msbuild -t:Build -m
- name: Upload net461
uses: actions/upload-artifact@v2
with:
name: BSIPA-net461-${{ env.Platform }}
path: BSIPA-Meta/bin/${{ env.Platform }}/${{ env.Configuration }}/net461/
- name: Upload net35
uses: actions/upload-artifact@v2
with:
name: BSIPA-net35-${{ env.Platform }}
path: BSIPA-Meta/bin/${{ env.Platform }}/${{ env.Configuration }}/net35/

+ 1
- 1
.github/workflows/docs.yml View File

@ -33,7 +33,7 @@ jobs:
- name: Install DocFX
uses: crazy-max/ghaction-chocolatey@v1
with:
args: install docfx --version 2.48 -y
args: install docfx -y
- name: Checkout current pages
uses: actions/checkout@v2
with:


+ 48
- 78
BSIPA-Meta/BSIPA-Meta.csproj View File

@ -1,99 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Assemble" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk" DefaultTargets="Build">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x64-Net4</Platform>
<ProjectGuid>{880A3560-82CD-4836-996B-11BEFE6B44DB}</ProjectGuid>
<OutputType>Library</OutputType>
<TargetFrameworks>net35;net461</TargetFrameworks>
<Platforms>x86;x64</Platforms>
<Configurations>Debug;Release;Verbose;Verbose_Release</Configurations>
<RootNamespace>BSIPA_Meta</RootNamespace>
<AssemblyName>Meta Project</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86-Net4' Or '$(Platform)' == 'x86-Net3' ">
<ProxyPlatform>Win32</ProxyPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x64-Net4' Or '$(Platform)' == 'x64-Net3' ">
<ProxyPlatform>x64</ProxyPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86-Net4' Or '$(Platform)' == 'x64-Net4' ">
<NetPlatform>Net4</NetPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86-Net3' Or '$(Platform)' == 'x64-Net3' ">
<NetPlatform>Net3</NetPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoVerboseConfig>Debug</NoVerboseConfig>
<OtherConfig>Debug</OtherConfig>
<ProxyConfig>Release</ProxyConfig>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
<PackageAction>Assemble</PackageAction>
<InnerTargets>Assemble</InnerTargets>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoVerboseConfig>Release</NoVerboseConfig>
<OtherConfig>Release</OtherConfig>
<PropertyGroup>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<IsVerbose>false</IsVerbose>
<IsVerbose Condition="'$(Configuration)' == 'Verbose' Or '$(Configuration)' == 'Verbose_Release'">true</IsVerbose>
<NoVerboseConfig>$(Configuration)</NoVerboseConfig>
<NoVerboseConfig Condition="'$(IsVerbose)' == 'true' And '$(Configuration)' == 'Verbose'">Debug</NoVerboseConfig>
<NoVerboseConfig Condition="'$(IsVerbose)' == 'true' And '$(Configuration)' == 'Verbose_Release'">Release</NoVerboseConfig>
<ProxyConfig>Release</ProxyConfig>
<ProxyConfig Condition="'$(IsVerbose)' == 'true'">Verbose_Release</ProxyConfig>
<ProxyPlatform>Win32</ProxyPlatform>
<ProxyPlatform Condition="'$(Platform)' == 'x64'">x64</ProxyPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Verbose' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoVerboseConfig>Debug</NoVerboseConfig>
<OtherConfig>Verbose</OtherConfig>
<ProxyConfig>Verbose_Release</ProxyConfig>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Verbose_Release' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoVerboseConfig>Release</NoVerboseConfig>
<OtherConfig>Verbose_Release</OtherConfig>
<ProxyConfig>Verbose_Release</ProxyConfig>
</PropertyGroup>
<Target Name="Restore" />
<ItemGroup>
<ProjectReference Include="..\IPA\IPA.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\IPA.Injector\IPA.Injector.csproj">
<SetConfiguration>Configuration=$(NoVerboseConfig)</SetConfiguration>
<SetPlatform>Platform=AnyCPU</SetPlatform>
</ProjectReference>
<ProjectReference Include="..\IPA.Loader\IPA.Loader.csproj">
<SetConfiguration>Configuration=$(NoVerboseConfig)</SetConfiguration>
<SetPlatform>Platform=AnyCPU</SetPlatform>
</ProjectReference>
<ProjectReference Include="..\Doorstop\Proxy\Proxy.vcxproj" ReferenceOutputAssembly="false">
<SetConfiguration>Configuration=$(ProxyConfig)</SetConfiguration>
<SetPlatform>Platform=$(ProxyPlatform)</SetPlatform>
</ProjectReference>
</ItemGroup>
<Target Name="Clean">
<ItemGroup>
<Files Include="$(OutputPath)**\*" />
</ItemGroup>
<Delete Files="@(Files)" />
</Target>
<Target Name="Rebuild">
<CallTarget Targets="Assemble" />
</Target>
<Target Name="Build">
<Target Name="CoreCompile">
<CallTarget Targets="Assemble" />
</Target>
<Target Name="Assemble" Returns="$(OutputPath)">
<Message Text="Packing..." Importance="High" />
<Message Text="Results will be put in $(OutputPath)" Importance="High" />
<ItemGroup>
<InputDlls Include="$(SolutionDir)IPA.Injector\bin\$(NetPlatform)\$(NoVerboseConfig)\**\*" Exclude="$(SolutionDir)IPA.Injector\bin\$(NetPlatform)\$(NoVerboseConfig)\Libraries\**\*" />
<InputDlls Include="$(SolutionDir)IPA.Injector\bin\$(NoVerboseConfig)\$(TargetFramework)\**\*" Exclude="$(SolutionDir)IPA.Injector\bin\$(NoVerboseConfig)\$(TargetFramework)\Libraries\**\*" />
<InputDlls Include="$(SolutionDir)Doorstop\Proxy\bin\$(ProxyPlatform)\$(ProxyConfig)\**\*.dll" />
<InputDlls Include="$(SolutionDir)Doorstop\Proxy\bin\$(ProxyPlatform)\$(ProxyConfig)\**\*.pdb" />
<InputIPAFiles Include="$(SolutionDir)IPA\bin\$(OtherConfig)\**\*" />
<InputIPAFiles Include="$(SolutionDir)IPA\bin\$(Configuration)\**\*" />
</ItemGroup>
<Copy SourceFiles="@(InputDlls)" DestinationFolder="$(OutputPath)IPA\%(RecursiveDir)" />
<Move SourceFiles="$(OutputPath)IPA\proxy.dll" DestinationFiles="$(OutputPath)IPA\winhttp.dll" />
@ -107,4 +76,5 @@
<Delete Files="@(BadFiles)" />
<RemoveDir Directories="$(OutputPath)Libraries\" />
</Target>
</Project>
</Project>

+ 132
- 239
BSIPA.sln View File

@ -6,17 +6,7 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPA", "IPA\IPA.csproj", "{14092533-98BB-40A4-9AFC-27BB75672A70}"
ProjectSection(ProjectDependencies) = postProject
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F} = {5F33B310-DC8D-4C0D-877E-BAC3908DE10F}
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7} = {2A1AF16B-27F1-46E0-9A95-181516BC1CB7}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IPA.Loader", "IPA.Loader\IPA.Loader.csproj", "{5AD344F0-01A0-4CA8-92E5-9D095737744D}"
ProjectSection(ProjectDependencies) = postProject
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F} = {5F33B310-DC8D-4C0D-877E-BAC3908DE10F}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IPA.Injector", "IPA.Injector\IPA.Injector.csproj", "{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}"
ProjectSection(ProjectDependencies) = postProject
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F} = {5F33B310-DC8D-4C0D-877E-BAC3908DE10F}
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C} = {10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "proxy", "Doorstop\Proxy\Proxy.vcxproj", "{88609E16-731F-46C9-8139-6B1A7A83240D}"
@ -28,7 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{C79C2C3A
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4D6639A2-BD39-4F9B-AF7F-8E5F3B88243D}"
ProjectSection(SolutionItems) = preProject
appveyor.yml = appveyor.yml
.github\release_draft.yml = .github\release_draft.yml
.github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\docs.yml = .github\workflows\docs.yml
README.md = README.md
.github\workflows\tag_docs.yml = .github\workflows\tag_docs.yml
@ -36,243 +27,145 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollectDependencies", "BuildTools\CollectDependencies\CollectDependencies.csproj", "{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BSIPA-Meta", "BSIPA-Meta\BSIPA-Meta.csproj", "{880A3560-82CD-4836-996B-11BEFE6B44DB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BSIPA-Meta", "BSIPA-Meta\BSIPA-Meta.csproj", "{880A3560-82CD-4836-996B-11BEFE6B44DB}"
ProjectSection(ProjectDependencies) = postProject
{88609E16-731F-46C9-8139-6B1A7A83240D} = {88609E16-731F-46C9-8139-6B1A7A83240D}
{14092533-98BB-40A4-9AFC-27BB75672A70} = {14092533-98BB-40A4-9AFC-27BB75672A70}
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7} = {2A1AF16B-27F1-46E0-9A95-181516BC1CB7}
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C} = {10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IPA.Injector", "IPA.Injector\IPA.Injector.csproj", "{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}"
ProjectSection(ProjectDependencies) = postProject
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F} = {5F33B310-DC8D-4C0D-877E-BAC3908DE10F}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IPA.Loader", "IPA.Loader\IPA.Loader.csproj", "{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}"
ProjectSection(ProjectDependencies) = postProject
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F} = {5F33B310-DC8D-4C0D-877E-BAC3908DE10F}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Net3-Proxy", "Net3-Proxy\Net3-Proxy.csproj", "{642F52DA-90F9-40E3-8784-6964F36752FB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net3-Proxy", "Net3-Proxy\Net3-Proxy.csproj", "{0DEDB099-9A26-4069-A4C1-A76CEB16283B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64-Net3 = Debug|x64-Net3
Debug|x64-Net4 = Debug|x64-Net4
Debug|x86-Net3 = Debug|x86-Net3
Debug|x86-Net4 = Debug|x86-Net4
Release|x64-Net3 = Release|x64-Net3
Release|x64-Net4 = Release|x64-Net4
Release|x86-Net3 = Release|x86-Net3
Release|x86-Net4 = Release|x86-Net4
Verbose_Release|x64-Net3 = Verbose_Release|x64-Net3
Verbose_Release|x64-Net4 = Verbose_Release|x64-Net4
Verbose_Release|x86-Net3 = Verbose_Release|x86-Net3
Verbose_Release|x86-Net4 = Verbose_Release|x86-Net4
Verbose|x64-Net3 = Verbose|x64-Net3
Verbose|x64-Net4 = Verbose|x64-Net4
Verbose|x86-Net3 = Verbose|x86-Net3
Verbose|x86-Net4 = Verbose|x86-Net4
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
Verbose_Release|x64 = Verbose_Release|x64
Verbose_Release|x86 = Verbose_Release|x86
Verbose|x64 = Verbose|x64
Verbose|x86 = Verbose|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x64-Net3.ActiveCfg = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x64-Net3.Build.0 = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x64-Net4.ActiveCfg = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x64-Net4.Build.0 = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x86-Net3.ActiveCfg = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x86-Net3.Build.0 = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x86-Net4.ActiveCfg = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x86-Net4.Build.0 = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x64-Net3.ActiveCfg = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x64-Net3.Build.0 = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x64-Net4.ActiveCfg = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x64-Net4.Build.0 = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x86-Net3.ActiveCfg = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x86-Net3.Build.0 = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x86-Net4.ActiveCfg = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x86-Net4.Build.0 = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x64-Net3.ActiveCfg = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x64-Net3.Build.0 = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x64-Net4.ActiveCfg = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x64-Net4.Build.0 = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x86-Net3.ActiveCfg = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x86-Net3.Build.0 = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x86-Net4.ActiveCfg = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x86-Net4.Build.0 = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x64-Net3.ActiveCfg = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x64-Net3.Build.0 = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x64-Net4.ActiveCfg = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x64-Net4.Build.0 = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x86-Net3.ActiveCfg = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x86-Net3.Build.0 = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x86-Net4.ActiveCfg = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x86-Net4.Build.0 = Verbose|Any CPU
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x64-Net3.ActiveCfg = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x64-Net3.Build.0 = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x64-Net4.ActiveCfg = Debug|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x64-Net4.Build.0 = Debug|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x86-Net3.ActiveCfg = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x86-Net3.Build.0 = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x86-Net4.ActiveCfg = Debug|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Debug|x86-Net4.Build.0 = Debug|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x64-Net3.ActiveCfg = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x64-Net3.Build.0 = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x64-Net4.ActiveCfg = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x64-Net4.Build.0 = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x86-Net3.ActiveCfg = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x86-Net3.Build.0 = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x86-Net4.ActiveCfg = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Release|x86-Net4.Build.0 = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x64-Net3.ActiveCfg = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x64-Net3.Build.0 = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x64-Net4.ActiveCfg = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x64-Net4.Build.0 = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x86-Net3.ActiveCfg = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x86-Net3.Build.0 = Release|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x86-Net4.ActiveCfg = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose_Release|x86-Net4.Build.0 = Release|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x64-Net3.ActiveCfg = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x64-Net3.Build.0 = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x64-Net4.ActiveCfg = Debug|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x64-Net4.Build.0 = Debug|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x86-Net3.ActiveCfg = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x86-Net3.Build.0 = Debug|Net3
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x86-Net4.ActiveCfg = Debug|Net4
{5AD344F0-01A0-4CA8-92E5-9D095737744D}.Verbose|x86-Net4.Build.0 = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x64-Net3.ActiveCfg = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x64-Net3.Build.0 = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x64-Net4.ActiveCfg = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x64-Net4.Build.0 = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x86-Net3.ActiveCfg = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x86-Net3.Build.0 = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x86-Net4.ActiveCfg = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Debug|x86-Net4.Build.0 = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x64-Net3.ActiveCfg = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x64-Net3.Build.0 = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x64-Net4.ActiveCfg = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x64-Net4.Build.0 = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x86-Net3.ActiveCfg = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x86-Net3.Build.0 = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x86-Net4.ActiveCfg = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Release|x86-Net4.Build.0 = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x64-Net3.ActiveCfg = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x64-Net3.Build.0 = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x64-Net4.ActiveCfg = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x64-Net4.Build.0 = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x86-Net3.ActiveCfg = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x86-Net3.Build.0 = Release|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x86-Net4.ActiveCfg = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose_Release|x86-Net4.Build.0 = Release|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x64-Net3.ActiveCfg = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x64-Net3.Build.0 = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x64-Net4.ActiveCfg = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x64-Net4.Build.0 = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x86-Net3.ActiveCfg = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x86-Net3.Build.0 = Debug|Net3
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x86-Net4.ActiveCfg = Debug|Net4
{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}.Verbose|x86-Net4.Build.0 = Debug|Net4
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64-Net3.ActiveCfg = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64-Net3.Build.0 = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64-Net4.ActiveCfg = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64-Net4.Build.0 = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86-Net3.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86-Net3.Build.0 = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86-Net4.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86-Net4.Build.0 = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64-Net3.ActiveCfg = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64-Net3.Build.0 = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64-Net4.ActiveCfg = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64-Net4.Build.0 = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86-Net3.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86-Net3.Build.0 = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86-Net4.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86-Net4.Build.0 = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64-Net3.ActiveCfg = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64-Net3.Build.0 = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64-Net4.ActiveCfg = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64-Net4.Build.0 = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86-Net3.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86-Net3.Build.0 = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86-Net4.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86-Net4.Build.0 = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64-Net3.ActiveCfg = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64-Net3.Build.0 = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64-Net4.ActiveCfg = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64-Net4.Build.0 = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86-Net3.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86-Net3.Build.0 = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86-Net4.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86-Net4.Build.0 = Verbose_Release|Win32
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x64-Net3.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x64-Net3.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x64-Net4.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x64-Net4.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x86-Net3.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x86-Net3.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x86-Net4.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x86-Net4.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Release|x64-Net3.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Release|x64-Net4.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Release|x86-Net3.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Release|x86-Net4.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose_Release|x64-Net3.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose_Release|x64-Net4.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose_Release|x86-Net3.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose_Release|x86-Net4.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x64-Net3.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x64-Net3.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x64-Net4.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x64-Net4.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x86-Net3.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x86-Net3.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x86-Net4.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x86-Net4.Build.0 = Debug|Any CPU
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x64-Net3.ActiveCfg = Debug|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x64-Net3.Build.0 = Debug|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x64-Net4.ActiveCfg = Debug|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x64-Net4.Build.0 = Debug|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x86-Net3.ActiveCfg = Debug|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x86-Net3.Build.0 = Debug|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x86-Net4.ActiveCfg = Debug|x86-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x86-Net4.Build.0 = Debug|x86-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x64-Net3.ActiveCfg = Release|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x64-Net3.Build.0 = Release|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x64-Net4.ActiveCfg = Release|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x64-Net4.Build.0 = Release|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x86-Net3.ActiveCfg = Release|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x86-Net3.Build.0 = Release|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x86-Net4.ActiveCfg = Release|x86-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x86-Net4.Build.0 = Release|x86-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x64-Net3.ActiveCfg = Verbose_Release|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x64-Net3.Build.0 = Verbose_Release|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x64-Net4.ActiveCfg = Verbose_Release|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x64-Net4.Build.0 = Verbose_Release|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x86-Net3.ActiveCfg = Verbose_Release|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x86-Net3.Build.0 = Verbose_Release|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x86-Net4.ActiveCfg = Verbose_Release|x86-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x86-Net4.Build.0 = Verbose_Release|x86-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x64-Net3.ActiveCfg = Verbose|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x64-Net3.Build.0 = Verbose|x64-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x64-Net4.ActiveCfg = Verbose|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x64-Net4.Build.0 = Verbose|x64-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x86-Net3.ActiveCfg = Verbose|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x86-Net3.Build.0 = Verbose|x86-Net3
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x86-Net4.ActiveCfg = Verbose|x86-Net4
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x86-Net4.Build.0 = Verbose|x86-Net4
{642F52DA-90F9-40E3-8784-6964F36752FB}.Debug|x64-Net3.ActiveCfg = Debug|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Debug|x64-Net3.Build.0 = Debug|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Debug|x64-Net4.ActiveCfg = Debug|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Debug|x86-Net3.ActiveCfg = Debug|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Debug|x86-Net3.Build.0 = Debug|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Debug|x86-Net4.ActiveCfg = Debug|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Release|x64-Net3.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Release|x64-Net3.Build.0 = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Release|x64-Net4.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Release|x86-Net3.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Release|x86-Net3.Build.0 = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Release|x86-Net4.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose_Release|x64-Net3.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose_Release|x64-Net3.Build.0 = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose_Release|x64-Net4.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose_Release|x86-Net3.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose_Release|x86-Net3.Build.0 = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose_Release|x86-Net4.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose|x64-Net3.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose|x64-Net3.Build.0 = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose|x64-Net4.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose|x86-Net3.ActiveCfg = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose|x86-Net3.Build.0 = Release|Any CPU
{642F52DA-90F9-40E3-8784-6964F36752FB}.Verbose|x86-Net4.ActiveCfg = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x64.ActiveCfg = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x64.Build.0 = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x86.ActiveCfg = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Debug|x86.Build.0 = Debug|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x64.ActiveCfg = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x64.Build.0 = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x86.ActiveCfg = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Release|x86.Build.0 = Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x64.ActiveCfg = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x64.Build.0 = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x86.ActiveCfg = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose_Release|x86.Build.0 = Verbose_Release|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x64.ActiveCfg = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x64.Build.0 = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x86.ActiveCfg = Verbose|Any CPU
{14092533-98BB-40A4-9AFC-27BB75672A70}.Verbose|x86.Build.0 = Verbose|Any CPU
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64.ActiveCfg = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64.Build.0 = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86.Build.0 = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64.ActiveCfg = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64.Build.0 = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86.Build.0 = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64.ActiveCfg = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64.Build.0 = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86.Build.0 = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64.ActiveCfg = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64.Build.0 = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86.Build.0 = Verbose_Release|Win32
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x64.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x64.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x86.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Debug|x86.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Release|x64.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Release|x86.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose_Release|x64.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose_Release|x86.ActiveCfg = Release|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x64.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x64.Build.0 = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x86.ActiveCfg = Debug|Any CPU
{5F33B310-DC8D-4C0D-877E-BAC3908DE10F}.Verbose|x86.Build.0 = Debug|Any CPU
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x64.ActiveCfg = Debug|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x64.Build.0 = Debug|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x86.ActiveCfg = Debug|x86
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Debug|x86.Build.0 = Debug|x86
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x64.ActiveCfg = Release|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x64.Build.0 = Release|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x86.ActiveCfg = Release|x86
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Release|x86.Build.0 = Release|x86
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x64.ActiveCfg = Verbose_Release|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x64.Build.0 = Verbose_Release|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x86.ActiveCfg = Verbose_Release|x86
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose_Release|x86.Build.0 = Verbose_Release|x86
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x64.ActiveCfg = Verbose|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x64.Build.0 = Verbose|x64
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x86.ActiveCfg = Verbose|x86
{880A3560-82CD-4836-996B-11BEFE6B44DB}.Verbose|x86.Build.0 = Verbose|x86
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Debug|x64.ActiveCfg = Debug|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Debug|x64.Build.0 = Debug|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Debug|x86.ActiveCfg = Debug|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Debug|x86.Build.0 = Debug|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Release|x64.ActiveCfg = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Release|x64.Build.0 = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Release|x86.ActiveCfg = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Release|x86.Build.0 = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose_Release|x64.ActiveCfg = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose_Release|x64.Build.0 = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose_Release|x86.ActiveCfg = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose_Release|x86.Build.0 = Release|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose|x64.ActiveCfg = Debug|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose|x64.Build.0 = Debug|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose|x86.ActiveCfg = Debug|Any CPU
{10F0057C-6C1E-41AA-A4DE-2F9D2EABE55C}.Verbose|x86.Build.0 = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Debug|x64.ActiveCfg = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Debug|x64.Build.0 = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Debug|x86.ActiveCfg = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Debug|x86.Build.0 = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Release|x64.ActiveCfg = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Release|x64.Build.0 = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Release|x86.ActiveCfg = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Release|x86.Build.0 = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose_Release|x64.ActiveCfg = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose_Release|x64.Build.0 = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose_Release|x86.ActiveCfg = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose_Release|x86.Build.0 = Release|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose|x64.ActiveCfg = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose|x64.Build.0 = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose|x86.ActiveCfg = Debug|Any CPU
{BBBA5CAD-B40E-4565-AE96-E8EC468DB54B}.Verbose|x86.Build.0 = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Debug|x64.ActiveCfg = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Debug|x64.Build.0 = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Debug|x86.ActiveCfg = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Debug|x86.Build.0 = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Release|x64.ActiveCfg = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Release|x64.Build.0 = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Release|x86.ActiveCfg = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Release|x86.Build.0 = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose_Release|x64.ActiveCfg = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose_Release|x64.Build.0 = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose_Release|x86.ActiveCfg = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose_Release|x86.Build.0 = Release|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose|x64.ActiveCfg = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose|x64.Build.0 = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose|x86.ActiveCfg = Debug|Any CPU
{0DEDB099-9A26-4069-A4C1-A76CEB16283B}.Verbose|x86.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


+ 106
- 155
IPA.Injector/IPA.Injector.csproj View File

@ -1,155 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">Net4</Platform>
<BuildForBeatSaber Condition=" '$(BuildForBeatSaber)' == '' And '$(Platform)' == 'Net4' ">true</BuildForBeatSaber>
<ProjectGuid>{2A1AF16B-27F1-46E0-9A95-181516BC1CB7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>IPA.Injector</RootNamespace>
<AssemblyName>IPA.Injector</AssemblyName>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<PathMap>$(SolutionDir)=C:\</PathMap>
<DebugType>portable</DebugType>
<ShowTargetFrameworks>false</ShowTargetFrameworks>
<ShowTargetFrameworks Condition=" '$(BuildingInsideVisualStudio)' != 'true' Or '$(CI)' == 'True' ">true</ShowTargetFrameworks>
<TargetFrameworks Condition=" '$(ShowTargetFrameworks)' == 'true' ">net461;net35</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<Optimize>false</Optimize>
<OutputPath>bin\$(Platform)\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<Optimize>true</Optimize>
<OutputPath>bin\$(Platform)\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'Net4' ">
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<DefineConstants>$(DefineConstants);NET4</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'Net3' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<DefineConstants>$(DefineConstants);NET3</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(BuildForBeatSaber)' == 'true' ">
<DefineConstants>$(DefineConstants);BeatSaber</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="UnityEngine.CoreModule" Condition=" '$(Platform)' == 'Net4' ">
<HintPath>..\Refs\UnityEngine.CoreModule.Net4.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule" Condition=" '$(Platform)' == 'Net3' ">
<HintPath>..\Refs\UnityEngine.CoreModule.Net3.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AntiPiracy.cs" />
<Compile Include="Backups\BackupManager.cs" />
<Compile Include="Backups\BackupUnit.cs" />
<Compile Include="Bootstrapper.cs" />
<Compile Include="GameVersionEarly.cs" />
<Compile Include="Injector.cs" />
<Compile Include="PermissionFix.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Updates.cs" />
<Compile Include="Virtualizer.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IPA.Loader\IPA.Loader.csproj">
<Project>{5ad344f0-01a0-4ca8-92e5-9d095737744d}</Project>
<Name>IPA.Loader</Name>
</ProjectReference>
<ProjectReference Include="..\Net3-Proxy\Net3-Proxy.csproj" Condition=" '$(Platform)' == 'Net3' ">
<Project>{642F52DA-90F9-40E3-8784-6964F36752FB}</Project>
<Name>Net3-Proxy</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'Net4' ">
<Content Include="..\Libs\I18N.Net4.dll">
<Link>Libraries\Mono\I18N.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\I18N.West.Net4.dll">
<Link>Libraries\Mono\I18N.West.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\Microsoft.CSharp.dll">
<Link>Libraries\Mono\Microsoft.CSharp.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\System.Runtime.Serialization.Net4.dll">
<Link>Libraries\Mono\System.Runtime.Serialization.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'Net3' ">
<Content Include="..\Libs\I18N.Net3.dll">
<Link>Libraries\Mono\I18N.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\I18N.West.Net3.dll">
<Link>Libraries\Mono\I18N.West.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\System.Runtime.Serialization.Net3.dll">
<Link>Libraries\Mono\System.Runtime.Serialization.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Mono.Cecil">
<Version>0.10.4</Version>
</PackageReference>
<PackageReference Include="SemanticVersioning">
<Version>1.2.2</Version>
</PackageReference>
<PackageReference Include="AsyncBridge">
<Version>0.3.1</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">
<Message Text="Relocating" Importance="normal" />
<ItemGroup>
<SystemFiles Include="$(OutputPath)IPA.Injector.*" />
<SystemFiles Include="$(OutputPath)IPA.Loader.*" />
<SystemFiles Include="$(OutputPath)AsyncBridge.*" />
<SystemFiles Include="$(OutputPath)System.*" />
<SystemFiles Include="$(OutputPath)Portable.System.*" />
<SystemFiles Include="$(OutputPath)Net3-Proxy.*" />
<SystemFiles Include="$(OutputPath)Libraries\Mono\**\*" />
<OldLibFiles Include="$(OutputPath)Libs\**\*" />
</ItemGroup>
<Move SourceFiles="@(SystemFiles)" DestinationFolder="$(OutputPath)Data\Managed" />
<RemoveDir Directories="$(OutputPath)Libraries\Mono" />
<Delete Files="@(OldLibFiles)" />
<RemoveDir Directories="$(OutputPath)Libs" />
<ItemGroup>
<LibFiles Include="$(OutputPath)**\*" Exclude="$(OutputPath)Data\**\*;$(OutputPath)Libs\**\*" />
</ItemGroup>
<Move SourceFiles="@(LibFiles)" DestinationFolder="$(OutputPath)Libs\" />
<RemoveDir Directories="$(OutputPath)Libraries\Included" />
<RemoveDir Directories="$(OutputPath)Libraries" />
</Target>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461;net35</TargetFrameworks>
<RootNamespace>IPA.Injector</RootNamespace>
<!--<PathMap>$(SolutionDir)=C:\</PathMap>-->
<DebugType>portable</DebugType>
<LangVersion>8.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>CA1031</NoWarn>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<BuildForBeatSaber Condition=" '$(BuildForBeatSaber)' == '' And '$(TargetFramework)' == 'net461' ">true</BuildForBeatSaber>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
<DefineConstants>$(DefineConstants);NET4</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net35'">
<DefineConstants>$(DefineConstants);NET3</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BuildForBeatSaber)' == 'true'">
<DefineConstants>$(DefineConstants);BeatSaber</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\IPA.Loader\IPA.Loader.csproj" />
<ProjectReference Include="..\Net3-Proxy\Net3-Proxy.csproj" Condition=" '$(TargetFramework)' == 'net35' " />
</ItemGroup>
<ItemGroup>
<Reference Include="UnityEngine.CoreModule" Condition=" '$(TargetFramework)' == 'net461' ">
<HintPath>..\Refs\UnityEngine.CoreModule.Net4.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule" Condition=" '$(TargetFramework)' == 'net35' ">
<HintPath>..\Refs\UnityEngine.CoreModule.Net3.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Content Include="..\Libs\I18N.Net4.dll">
<Link>Libraries\Mono\I18N.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\I18N.West.Net4.dll">
<Link>Libraries\Mono\I18N.West.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\Microsoft.CSharp.dll">
<Link>Libraries\Mono\Microsoft.CSharp.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\System.Runtime.Serialization.Net4.dll">
<Link>Libraries\Mono\System.Runtime.Serialization.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' ">
<Content Include="..\Libs\I18N.Net3.dll">
<Link>Libraries\Mono\I18N.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\I18N.West.Net3.dll">
<Link>Libraries\Mono\I18N.West.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Libs\System.Runtime.Serialization.Net3.dll">
<Link>Libraries\Mono\System.Runtime.Serialization.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Mono.Cecil" Version="0.10.4" />
<PackageReference Include="SemanticVersioning" Version="1.2.2" />
<PackageReference Include="AsyncBridge" Version="0.3.1" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Message Text="Relocating" Importance="normal" />
<ItemGroup>
<SystemFiles Include="$(OutputPath)IPA.Injector.*" />
<SystemFiles Include="$(OutputPath)IPA.Loader.*" />
<SystemFiles Include="$(OutputPath)AsyncBridge.*" />
<SystemFiles Include="$(OutputPath)System.*" />
<SystemFiles Include="$(OutputPath)Portable.System.*" />
<SystemFiles Include="$(OutputPath)Net3-Proxy.*" />
<SystemFiles Include="$(OutputPath)Libraries\Mono\**\*" />
<OldLibFiles Include="$(OutputPath)Libs\**\*" />
</ItemGroup>
<Move SourceFiles="@(SystemFiles)" DestinationFolder="$(OutputPath)Data\Managed" />
<RemoveDir Directories="$(OutputPath)Libraries\Mono" />
<Delete Files="@(OldLibFiles)" />
<RemoveDir Directories="$(OutputPath)Libs" />
<ItemGroup>
<LibFiles Include="$(OutputPath)**\*" Exclude="$(OutputPath)Data\**\*;$(OutputPath)Libs\**\*" />
</ItemGroup>
<Move SourceFiles="@(LibFiles)" DestinationFolder="$(OutputPath)Libs\" />
<RemoveDir Directories="$(OutputPath)Libraries\Included" />
<RemoveDir Directories="$(OutputPath)Libraries" />
</Target>
</Project>

+ 1
- 1
IPA.Loader/Config/SelfConfig.cs View File

@ -68,7 +68,7 @@ namespace IPA.Config
}
internal const string IPAName = "Beat Saber IPA";
internal const string IPAVersion = "4.0.6.0";
internal const string IPAVersion = "4.1.0.0";
// uses Updates.AutoUpdate, Updates.AutoCheckUpdates, YeetMods, Debug.ShowCallSource, Debug.ShowDebug,
// Debug.CondenseModLogs


+ 27
- 172
IPA.Loader/IPA.Loader.csproj View File

@ -1,68 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">Net4</Platform>
<BuildForBeatSaber Condition=" '$(BuildForBeatSaber)' == '' And '$(Platform)' == 'Net4' ">true</BuildForBeatSaber>
<ProjectGuid>{5AD344F0-01A0-4CA8-92E5-9D095737744D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworks>net461;net35</TargetFrameworks>
<RootNamespace>IPA</RootNamespace>
<AssemblyName>IPA.Loader</AssemblyName>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<PathMap>$(SolutionDir)=C:\</PathMap>
<!--<PathMap>$(SolutionDir)=C:\</PathMap>-->
<DebugType>portable</DebugType>
<ShowTargetFrameworks>false</ShowTargetFrameworks>
<ShowTargetFrameworks Condition=" '$(BuildingInsideVisualStudio)' != 'true' Or '$(CI)' == 'True' ">true</ShowTargetFrameworks>
<TargetFrameworks Condition=" '$(ShowTargetFrameworks)' == 'true' ">net461;net35</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>CA1031</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<BuildForBeatSaber Condition=" '$(BuildForBeatSaber)' == '' And '$(TargetFramework)' == 'net461' ">true</BuildForBeatSaber>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<Optimize>false</Optimize>
<OutputPath>bin\$(Platform)\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RegisterForComInterop>false</RegisterForComInterop>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<Optimize>true</Optimize>
<OutputPath>bin\$(Platform)\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RegisterForComInterop>false</RegisterForComInterop>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'Net4' ">
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
<DefineConstants>$(DefineConstants);NET4</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'Net3' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<PropertyGroup Condition="'$(TargetFramework)' == 'net35'">
<DefineConstants>$(DefineConstants);NET3</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(BuildForBeatSaber)' == 'true' ">
<PropertyGroup Condition="'$(BuildForBeatSaber)' == 'true'">
<DefineConstants>$(DefineConstants);BeatSaber</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<DocumentationFile>$(OutputPath)IPA.Loader.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" Condition=" '$(Platform)' == 'Net4' " />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" Condition=" '$(Platform)' == 'Net4' " />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'Net4' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\Refs\UnityEngine.CoreModule.Net4.dll</HintPath>
<Private>False</Private>
@ -72,7 +33,7 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'Net3' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' ">
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\Refs\UnityEngine.CoreModule.Net3.dll</HintPath>
<Private>False</Private>
@ -82,131 +43,25 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Net3-Proxy\Net3-Proxy.csproj" Condition=" '$(Platform)' == 'Net3' ">
<Project>{642F52DA-90F9-40E3-8784-6964F36752FB}</Project>
<Name>Net3-Proxy</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Config\Config.cs" />
<Compile Include="Config\ConfigRuntime.cs" />
<Compile Include="Config\Providers\JsonConfigProvider.cs" />
<Compile Include="Config\Data\List.cs" />
<Compile Include="Config\Data\Map.cs" />
<Compile Include="Config\Data\Primitives.cs" />
<Compile Include="Config\Data\Value.cs" />
<Compile Include="Config\IConfigProvider.cs" />
<Compile Include="Config\IConfigStore.cs" />
<Compile Include="Config\SelfConfig.cs" />
<Compile Include="Config\Stores\Attributes.cs" />
<Compile Include="Config\Stores\Converters.cs" />
<Compile Include="Config\Stores\CustomObjectConverter.cs" />
<Compile Include="Config\Stores\CollectionConverter.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\ConversionDelegates.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\Correction.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\Deserialization.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\GeneratedStoreImpl.cs" />
<Compile Include="Config\Stores\GeneratedStoreCollections.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\IGeneratedStore.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\MakeCreator.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\ObjectStructure.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\Serialization.cs" />
<Compile Include="Config\Stores\GeneratedStoreImpl\Utility.cs" />
<Compile Include="Config\Stores\GeneratedStorePublicInterface.cs" />
<Compile Include="Config\Stores\ValueConverter.cs" />
<Compile Include="JsonConverters\AlmostVersionConverter.cs" />
<Compile Include="JsonConverters\MultilineStringConverter.cs" />
<Compile Include="Loader\CannotRuntimeDisableException.cs" />
<Compile Include="Loader\Composite\CompositeBSPlugin.cs" />
<Compile Include="Loader\DisabledConfig.cs" />
<Compile Include="Loader\Features\ConfigProviderFeature.cs" />
<Compile Include="Loader\Features\DefineFeature.cs" />
<Compile Include="Loader\Features\InitInjectorFeature.cs" />
<Compile Include="Loader\Features\NoUpdateFeature.cs" />
<Compile Include="Loader\Features\PrintFeature.cs" />
<Compile Include="Loader\HarmonyProtector.cs" />
<Compile Include="Loader\PluginExecutor.cs" />
<Compile Include="Loader\PluginInitInjector.cs" />
<Compile Include="Loader\LibLoader.cs" />
<Compile Include="Loader\Features\Feature.cs" />
<Compile Include="Loader\PluginLoader.cs" />
<Compile Include="Loader\PluginManifest.cs" />
<Compile Include="Loader\PluginMetadata.cs" />
<Compile Include="Loader\StateTransitionTransaction.cs" />
<Compile Include="Logging\ConsoleWindow.cs" />
<Compile Include="Logging\Printers\ColorlessConsolePrinter.cs" />
<Compile Include="Logging\Printers\PluginSubLogPrinter.cs" />
<Compile Include="Logging\StdoutInterceptor.cs" />
<Compile Include="PluginInterfaces\Attributes\LifecycleAttributes.cs" />
<Compile Include="PluginInterfaces\Attributes\PluginAttribute.cs" />
<Compile Include="Config\IniFile.cs" />
<Compile Include="PluginInterfaces\IPA\IEnhancedPlugin.cs" />
<Compile Include="PluginInterfaces\IPA\IPlugin.cs" />
<Compile Include="Logging\Logger.cs" />
<Compile Include="Logging\LogPrinter.cs" />
<Compile Include="Config\ModPrefs.cs" />
<Compile Include="JsonConverters\SemverRangeConverter.cs" />
<Compile Include="JsonConverters\SemverVersionConverter.cs" />
<Compile Include="Utilities\Async\Coroutines.cs" />
<Compile Include="Utilities\Async\SingleCreationValueCache.cs" />
<Compile Include="Utilities\Async\SingleThreadTaskScheduler.cs" />
<Compile Include="Utilities\Accessor.cs" />
<Compile Include="Utilities\Async\UnityMainThreadTaskScheduler.cs" />
<Compile Include="Utilities\UnityGame.cs" />
<Compile Include="Utilities\AlmostVersion.cs" />
<Compile Include="Utilities\CriticalSection.cs" />
<Compile Include="Utilities\EnumerableExtensions.cs" />
<Compile Include="Utilities\Ref.cs" />
<Compile Include="Utilities\ReflectionUtil.cs" />
<Compile Include="Loader\Composite\CompositeIPAPlugin.cs" />
<Compile Include="Logging\Printers\ColoredConsolePrinter.cs" />
<Compile Include="Logging\Printers\GlobalLogFilePrinter.cs" />
<Compile Include="Logging\Printers\GZFilePrinter.cs" />
<Compile Include="Logging\Printers\PluginLogFilePrinter.cs" />
<Compile Include="Logging\StandardLogger.cs" />
<Compile Include="Logging\UnityLogProvider.cs" />
<Compile Include="Loader\PluginComponent.cs" />
<Compile Include="Loader\PluginManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Updating\BeatMods\ApiEndpoint.cs" />
<Compile Include="Updating\BeatMods\Updater.cs" />
<Compile Include="Utilities\Extensions.cs" />
<Compile Include="Utilities\Async\Synchronization.cs" />
<Compile Include="Utilities\Utils.cs" />
<Compile Include="Utilities\Win32.cs" />
<ProjectReference Include="..\Net3-Proxy\Net3-Proxy.csproj" Condition=" '$(TargetFramework)' == 'net35' " />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Ionic.Zip">
<Version>1.9.1.8</Version>
</PackageReference>
<PackageReference Include="Lib.Harmony">
<Version>2.0.0.7</Version>
</PackageReference>
<PackageReference Include="Mono.Cecil">
<Version>0.10.4</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.3</Version>
</PackageReference>
<PackageReference Include="Portable.System.ValueTuple">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="SemanticVersioning">
<Version>1.2.2</Version>
</PackageReference>
<PackageReference Include="AsyncBridge">
<Version>0.3.1</Version>
</PackageReference>
<PackageReference Include="Ionic.Zip" Version="1.9.1.8" />
<PackageReference Include="Lib.Harmony" Version="2.0.0.7" />
<PackageReference Include="Mono.Cecil" Version="0.10.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Portable.System.ValueTuple" Version="1.0.1" />
<PackageReference Include="SemanticVersioning" Version="1.2.2" />
<PackageReference Include="AsyncBridge" Version="0.3.1" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Loader\manifest.json" />
<EmbeddedResource Include="icon_white.png" />
<EmbeddedResource Include="Loader\description.md" />
</ItemGroup>
<ItemGroup>
<None Include="icon_black.png" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>

+ 31
- 0
IPA.Loader/JsonConverters/FeaturesFieldConverter.cs View File

@ -0,0 +1,31 @@
using IPA.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IPA.JsonConverters
{
internal class FeaturesFieldConverter : JsonConverter<Dictionary<string, JObject>>
{
public override Dictionary<string, JObject> ReadJson(JsonReader reader, Type objectType, Dictionary<string, JObject> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
_ = serializer.Deserialize<string[]>(reader);
Logger.features.Warn("Encountered old features used. They no longer do anything, please move to the new format.");
return existingValue;
}
return serializer.Deserialize<Dictionary<string, JObject>>(reader);
}
public override void WriteJson(JsonWriter writer, Dictionary<string, JObject> value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
}

+ 20
- 9
IPA.Loader/Loader/Features/ConfigProviderFeature.cs View File

@ -1,28 +1,39 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
namespace IPA.Loader.Features
{
internal class ConfigProviderFeature : Feature
{
public override bool Initialize(PluginMetadata meta, string[] parameters)
{// parameters should be (fully qualified name of provider type)
if (parameters.Length != 1)
private class DataModel
{
[JsonProperty("type", Required = Required.Always)]
public string TypeName = "";
}
protected override bool Initialize(PluginMetadata meta, JObject featureData)
{
DataModel data;
try
{
InvalidMessage = "Incorrect number of parameters";
data = featureData.ToObject<DataModel>();
}
catch (Exception e)
{
InvalidMessage = $"Invalid data: {e}";
return false;
}
RequireLoaded(meta);
Type getType;
try
{
getType = meta.Assembly.GetType(parameters[0]);
getType = meta.Assembly.GetType(data.TypeName);
}
catch (ArgumentException)
{
InvalidMessage = $"Invalid type name {parameters[0]}";
InvalidMessage = $"Invalid type name {data.TypeName}";
return false;
}
catch (Exception e) when (e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException)


+ 49
- 21
IPA.Loader/Loader/Features/DefineFeature.cs View File

@ -1,4 +1,7 @@
using System;
using IPA.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
namespace IPA.Loader.Features
@ -7,27 +10,49 @@ namespace IPA.Loader.Features
{
public static bool NewFeature = true;
protected internal override bool StoreOnPlugin => false;
private class DataModel
{
[JsonProperty("type", Required = Required.Always)]
public string TypeName = "";
[JsonProperty("name", Required = Required.DisallowNull)]
public string ActualName = null;
public override bool Initialize(PluginMetadata meta, string[] parameters)
{ // parameters should be (name, fully qualified type)
if (parameters.Length != 2)
public string Name => ActualName ?? TypeName;
}
private DataModel data;
protected override bool Initialize(PluginMetadata meta, JObject featureData)
{
Logger.features.Debug("Executing DefineFeature Init");
try
{
InvalidMessage = "Incorrect number of parameters";
data = featureData.ToObject<DataModel>();
}
catch (Exception e)
{
InvalidMessage = $"Invalid data: {e}";
return false;
}
RequireLoaded(meta);
InvalidMessage = $"Feature {data.Name} already exists";
return PreregisterFeature(meta, data.Name);
}
public override void BeforeInit(PluginMetadata meta)
{
Logger.features.Debug("Executing DefineFeature AfterInit");
Type type;
try
{
type = meta.Assembly.GetType(parameters[1]);
type = meta.Assembly.GetType(data.TypeName);
}
catch (ArgumentException)
{
InvalidMessage = $"Invalid type name {parameters[1]}";
return false;
Logger.features.Error($"Invalid type name {data.TypeName}");
return;
}
catch (Exception e) when (e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException)
{
@ -46,28 +71,31 @@ namespace IPA.Loader.Features
break;
}
InvalidMessage = $"Could not find {filename} while loading type";
return false;
Logger.features.Error($"Could not find {filename} while loading type");
return;
}
if (type == null)
{
InvalidMessage = $"Invalid type name {parameters[1]}";
return false;
Logger.features.Error($"Invalid type name {data.TypeName}");
return;
}
try
{
if (RegisterFeature(parameters[0], type)) return NewFeature = true;
InvalidMessage = $"Feature with name {parameters[0]} already exists";
return false;
if (RegisterFeature(meta, data.Name, type))
{
NewFeature = true;
return;
}
Logger.features.Error($"Feature with name {data.Name} already exists");
return;
}
catch (ArgumentException)
{
InvalidMessage = $"{type.FullName} not a subclass of {nameof(Feature)}";
return false;
Logger.features.Error($"{type.FullName} not a subclass of {nameof(Feature)}");
return;
}
}
}


+ 97
- 50
IPA.Loader/Loader/Features/Feature.cs View File

@ -1,5 +1,8 @@
using System;
using Mono.Cecil;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
#if NET3
using Net3_Proxy;
@ -16,52 +19,30 @@ namespace IPA.Loader.Features
public abstract class Feature
{
/// <summary>
/// Initializes the feature with the parameters provided in the definition.
///
/// Note: When no parenthesis are provided, <paramref name="parameters"/> is an empty array.
/// Initializes the feature with the data provided in the definition.
/// </summary>
/// <remarks>
/// This gets called BEFORE *your* `Init` method.
///
/// Returning <see langword="false" /> does *not* prevent the plugin from being loaded. It simply prevents the feature from being used.
/// <para>This gets called AFTER your <c>Init</c> method, but BEFORE the target's <c>Init</c> method. If it is applied to the defining plugin, <c>BeforeInit</c> is not called.</para>
/// <para>Returning <see langword="false" /> does <i>not</i> prevent the plugin from being loaded. It simply prevents the feature from being used.</para>
/// </remarks>
/// <param name="meta">the metadata of the plugin that is being prepared</param>
/// <param name="parameters">the parameters passed to the feature definition, or null</param>
/// <param name="featureData">the data provided with the feature</param>
/// <returns><see langword="true"/> if the feature is valid for the plugin, <see langword="false"/> otherwise</returns>
public abstract bool Initialize(PluginMetadata meta, string[] parameters);
/// <summary>
/// Evaluates the Feature for use in conditional meta-Features. This should be re-calculated on every call, unless it can be proven to not change.
///
/// This will be called on every feature that returns <see langword="true" /> from <see cref="Initialize"/>
/// </summary>
/// <returns>the truthiness of the Feature.</returns>
public virtual bool Evaluate() => true;
protected abstract bool Initialize(PluginMetadata meta, JObject featureData);
/// <summary>
/// The message to be logged when the feature is not valid for a plugin.
/// This should also be set whenever either <see cref="BeforeLoad"/> or <see cref="BeforeInit"/> returns false.
/// This should also be set whenever either <see cref="BeforeInit"/> returns false.
/// </summary>
/// <value>the message to show when the feature is marked invalid</value>
public virtual string InvalidMessage { get; protected set; }
/// <summary>
/// Called before a plugin is loaded. This should never throw an exception. An exception will abort the loading of the plugin with an error.
/// </summary>
/// <remarks>
/// The assembly will still be loaded, but the plugin will not be constructed if this returns <see langword="false" />.
/// Any features it defines, for example, will still be loaded.
/// </remarks>
/// <param name="plugin">the plugin about to be loaded</param>
/// <returns>whether or not the plugin should be loaded</returns>
public virtual bool BeforeLoad(PluginMetadata plugin) => true;
/// <summary>
/// Called before a plugin's `Init` method is called. This will not be called if there is no `Init` method. This should never throw an exception. An exception will abort the loading of the plugin with an error.
/// </summary>
/// <param name="plugin">the plugin to be initialized</param>
/// <returns>whether or not to call the Init method</returns>
public virtual bool BeforeInit(PluginMetadata plugin) => true;
public virtual void BeforeInit(PluginMetadata plugin) { }
/// <summary>
/// Called after a plugin has been fully initialized, whether or not there is an `Init` method. This should never throw an exception.
@ -77,16 +58,10 @@ namespace IPA.Loader.Features
public virtual void AfterInit(PluginMetadata plugin) { }
/// <summary>
/// Ensures a plugin's assembly is loaded. Do not use unless you need to.
/// </summary>
/// <param name="plugin">the plugin to ensure is loaded.</param>
protected void RequireLoaded(PluginMetadata plugin) => PluginLoader.Load(plugin);
/// <summary>
/// Defines whether or not this feature will be accessible from the plugin metadata once loaded.
/// Called after a plugin with this feature appplied is disabled.
/// </summary>
/// <value><see langword="true"/> if this <see cref="Feature"/> will be stored on the plugin metadata, <see langword="false"/> otherwise</value>
protected internal virtual bool StoreOnPlugin => true;
/// <param name="plugin">the plugin that was disabled</param>
public virtual void AfterDisable(PluginMetadata plugin) { }
// TODO: rework features to take arguments as JSON objects
@ -99,39 +74,111 @@ namespace IPA.Loader.Features
{
featureTypes = new Dictionary<string, Type>
{
{ "define-feature", typeof(DefineFeature) }
{ "IPA.DefineFeature", typeof(DefineFeature) }
};
featureDelcarers = new Dictionary<string, PluginMetadata>
{
{ "IPA.DefineFeature", null }
};
}
private static Dictionary<string, Type> featureTypes;
private static Dictionary<string, PluginMetadata> featureDelcarers;
internal static bool HasFeature(string name) => featureTypes.ContainsKey(name);
internal static bool RegisterFeature(string name, Type type)
internal static bool PreregisterFeature(PluginMetadata defining, string name)
{
if (featureDelcarers.ContainsKey(name)) return false;
featureDelcarers.Add(name, defining);
return true;
}
internal static bool RegisterFeature(PluginMetadata definingPlugin, string name, Type type)
{
if (!typeof(Feature).IsAssignableFrom(type))
throw new ArgumentException($"Feature type not subclass of {nameof(Feature)}", nameof(type));
if (featureTypes.ContainsKey(name)) return false;
if (featureDelcarers.TryGetValue(name, out var declarer))
{
if (definingPlugin != declarer)
return false;
}
else
{
featureDelcarers.Add(name, definingPlugin);
}
featureTypes.Add(name, type);
return true;
}
internal struct FeatureParse
private class EmptyFeature : Feature
{
protected override bool Initialize(PluginMetadata meta, JObject featureData)
{
throw new NotImplementedException();
}
}
internal string FeatureName;
internal class Instance
{
public readonly PluginMetadata AppliedTo;
public readonly string Name;
public readonly string[] Parameters;
public readonly JObject Data;
public FeatureParse(string name, string[] parameters)
public Instance(PluginMetadata appliedTo, string name, JObject data)
{
AppliedTo = appliedTo;
Name = name;
Parameters = parameters;
Data = data;
type = null;
}
private Type type;
public bool TryGetDefiningPlugin(out PluginMetadata plugin)
{
return featureDelcarers.TryGetValue(Name, out plugin);
}
// returns whether or not Initialize returned true, feature is always set when the thing exists
public bool TryCreate(out Feature feature)
{
if (type == null)
{
if (!featureTypes.TryGetValue(Name, out type))
{
feature = new EmptyFeature() { InvalidMessage = "No such feature type found", FeatureName = Name };
return false;
}
}
bool result;
try
{
feature = (Feature)Activator.CreateInstance(type);
feature.FeatureName = Name;
result = feature.Initialize(AppliedTo, Data);
}
catch (Exception e)
{
result = false;
feature = new EmptyFeature() { InvalidMessage = e.ToString(), FeatureName = Name };
}
return result;
}
}
/*
// returns false with both outs null for no such feature
internal static bool TryParseFeature(string featureString, PluginMetadata plugin,
out Feature feature, out Exception failException, out bool featureValid, out FeatureParse parsed,
FeatureParse? preParsed = null)
out Feature feature, out Exception failException, out bool featureValid, out Instance parsed,
Instance? preParsed = null)
{
failException = null;
feature = null;
@ -190,7 +237,7 @@ namespace IPA.Loader.Features
if (name == null)
name = builder.ToString();
parsed = new FeatureParse(name, parameters.ToArray());
parsed = new Instance(name, parameters.ToArray());
if (parens != 0)
{
@ -212,7 +259,7 @@ namespace IPA.Loader.Features
return false;
}
featureValid = aFeature.Initialize(plugin, parsed.Parameters);
featureValid = aFeature.Initialize(plugin, TODO);
feature = aFeature;
return true;
}
@ -221,6 +268,6 @@ namespace IPA.Loader.Features
failException = e;
return false;
}
}
}*/
}
}

+ 0
- 105
IPA.Loader/Loader/Features/InitInjectorFeature.cs View File

@ -1,105 +0,0 @@
using System;
using System.IO;
using System.Reflection;
#if NET3
using Array = Net3_Proxy.Array;
#endif
namespace IPA.Loader.Features
{
internal class InitInjectorFeature : Feature
{
protected internal override bool StoreOnPlugin => false;
public override bool Initialize(PluginMetadata meta, string[] parameters)
{ // parameters should be (assembly qualified lookup type, [fully qualified type]:[method name])
// method should be static
if (parameters.Length != 2)
{
InvalidMessage = "Incorrect number of parameters";
return false;
}
RequireLoaded(meta);
var methodParts = parameters[1].Split(':');
var type = Type.GetType(parameters[0], false);
if (type == null)
{
InvalidMessage = $"Could not find type {parameters[0]}";
return false;
}
Type getType;
try
{
getType = meta.Assembly.GetType(methodParts[0]);
}
catch (ArgumentException)
{
InvalidMessage = $"Invalid type name {methodParts[0]}";
return false;
}
catch (Exception e) when (e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException)
{
string filename;
switch (e)
{
case FileNotFoundException fn:
filename = fn.FileName;
goto hasFilename;
case FileLoadException fl:
filename = fl.FileName;
goto hasFilename;
case BadImageFormatException bi:
filename = bi.FileName;
hasFilename:
InvalidMessage = $"Could not find {filename} while loading type";
break;
default:
InvalidMessage = $"Error while loading type: {e}";
break;
}
return false;
}
MethodInfo method;
try
{
method = getType.GetMethod(methodParts[1], BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
null, new[]
{
typeof(object),
typeof(ParameterInfo),
typeof(PluginMetadata)
}, Array.Empty<ParameterModifier>());
}
catch (Exception e)
{
InvalidMessage = $"Error while loading type: {e}";
return false;
}
if (method == null)
{
InvalidMessage = $"Could not find method {methodParts[1]} in type {methodParts[0]}";
return false;
}
try
{
var del = (PluginInitInjector.InjectParameter)Delegate.CreateDelegate(typeof(PluginInitInjector.InjectParameter), null, method);
PluginInitInjector.AddInjector(type, del);
return true;
}
catch (Exception e)
{
InvalidMessage = $"Error generated while creating delegate: {e}";
return false;
}
}
}
}

+ 0
- 12
IPA.Loader/Loader/Features/NoUpdateFeature.cs View File

@ -1,12 +0,0 @@
namespace IPA.Loader.Features
{
internal class NoUpdateFeature : Feature
{
public override bool Initialize(PluginMetadata meta, string[] parameters)
{
return meta.Id != null;
}
public override string InvalidMessage { get; protected set; } = "No ID specified; cannot update anyway";
}
}

+ 0
- 32
IPA.Loader/Loader/Features/PrintFeature.cs View File

@ -1,32 +0,0 @@

using IPA.Logging;
namespace IPA.Loader.Features
{
internal class PrintFeature : Feature
{
public override bool Initialize(PluginMetadata meta, string[] parameters)
{
Logger.features.Info($"{meta.Name}: {string.Join(" ", parameters)}");
return true;
}
}
internal class DebugFeature : Feature
{
public override bool Initialize(PluginMetadata meta, string[] parameters)
{
Logger.features.Debug($"{meta.Name}: {string.Join(" ", parameters)}");
return true;
}
}
internal class WarnFeature : Feature
{
public override bool Initialize(PluginMetadata meta, string[] parameters)
{
Logger.features.Warn($"{meta.Name}: {string.Join(" ", parameters)}");
return true;
}
}
}

+ 78
- 77
IPA.Loader/Loader/PluginLoader.cs View File

@ -39,6 +39,7 @@ namespace IPA.Loader
LoadMetadata();
Resolve();
InitFeatures();
ComputeLoadOrder();
FilterDisabled();
FilterWithoutFiles();
@ -100,7 +101,9 @@ namespace IPA.Loader
Logger.loader.Critical("Error loading own manifest");
Logger.loader.Critical(e);
}
var resolver = new CecilLibLoader();
resolver.AddSearchDirectory(UnityGame.LibraryPath);
resolver.AddSearchDirectory(UnityGame.PluginsPath);
foreach (var plugin in plugins)
{
var metadata = new PluginMetadata
@ -115,7 +118,7 @@ namespace IPA.Loader
{
ReadingMode = ReadingMode.Immediate,
ReadWrite = false,
AssemblyResolver = new CecilLibLoader()
AssemblyResolver = resolver
}).MainModule;
string pluginNs = "";
@ -303,7 +306,7 @@ namespace IPA.Loader
/// When this is the set <see cref="Reason"/> in an <see cref="IgnoreReason"/> structure, the member
/// <see cref="IgnoreReason.Error"/> will contain the thrown exception.
/// </remarks>
Error,
Error,
/// <summary>
/// The plugin this reason is associated with has the same ID as another plugin whose information was
/// already loaded.
@ -333,12 +336,12 @@ namespace IPA.Loader
/// The plugin this reason is associated with was released for a game update, but is still considered
/// present for the purposes of updating.
/// </summary>
Released,
Released,
/// <summary>
/// The plugin this reason is associated with was denied from loading by a <see cref="Features.Feature"/>
/// that it marks.
/// </summary>
Feature,
Feature,
/// <summary>
/// The plugin this reason is assoicated with is unsupported.
/// </summary>
@ -431,8 +434,8 @@ namespace IPA.Loader
=> !(left == right);
}
internal partial class PluginLoader
{
internal partial class PluginLoader
{
// keep track of these for the updater; it should still be able to update mods not loaded
// the thing -> the reason
internal static Dictionary<PluginMetadata, IgnoreReason> ignoredPlugins = new Dictionary<PluginMetadata, IgnoreReason>();
@ -440,7 +443,7 @@ namespace IPA.Loader
internal static void Resolve()
{ // resolves duplicates and conflicts, etc
PluginsMetadata.Sort((a, b) => b.Version.CompareTo(a.Version));
var ids = new HashSet<string>();
var ignore = new Dictionary<PluginMetadata, IgnoreReason>();
var resolved = new List<PluginMetadata>(PluginsMetadata.Count);
@ -685,57 +688,47 @@ namespace IPA.Loader
internal static void InitFeatures()
{
var parsedFeatures = PluginsMetadata.Select(m =>
(metadata: m,
features: m.Manifest.Features.Select(feature =>
(feature, parsed: Ref.Create<Feature.FeatureParse?>(null))
).ToList()
)
).ToList();
while (DefineFeature.NewFeature)
foreach (var meta in PluginsMetadata)
{
DefineFeature.NewFeature = false;
foreach (var (metadata, features) in parsedFeatures)
for (var i = 0; i < features.Count; i++)
{
var feature = features[i];
var success = Feature.TryParseFeature(feature.feature, metadata, out var featureObj,
out var exception, out var valid, out var parsed, feature.parsed.Value);
if (!success && !valid && featureObj == null && exception == null) // no feature of type found
feature.parsed.Value = parsed;
else if (success)
foreach (var feature in meta.Manifest.Features.Select(f => new Feature.Instance(meta, f.Key, f.Value)))
{
if (feature.TryGetDefiningPlugin(out var plugin) && plugin == null)
{ // this is a DefineFeature, so we want to initialize it early
if (!feature.TryCreate(out var inst))
{
if (valid && featureObj.StoreOnPlugin)
metadata.InternalFeatures.Add(featureObj);
else if (!valid)
Logger.features.Warn(
$"Feature not valid on {metadata.Name}: {featureObj.InvalidMessage}");
features.RemoveAt(i--);
Logger.features.Error($"Error evaluating {feature.Name}: {inst.InvalidMessage}");
}
else
{
Logger.features.Error($"Error parsing feature definition on {metadata.Name}");
Logger.features.Error(exception);
features.RemoveAt(i--);
meta.InternalFeatures.Add(inst);
}
}
foreach (var plugin in PluginsMetadata)
foreach (var feature in plugin.Features)
feature.Evaluate();
else
{ // this is literally any other feature, so we want to delay its initialization
meta.UnloadedFeatures.Add(feature);
}
}
}
foreach (var plugin in parsedFeatures)
// at this point we have pre-initialized all features, so we can go ahead and use them to add stuff to the dep resolver
foreach (var meta in PluginsMetadata)
{
if (plugin.features.Count <= 0) continue;
foreach (var feature in meta.UnloadedFeatures)
{
if (feature.TryGetDefiningPlugin(out var plugin))
{
if (plugin != meta)
{ // if the feature is not applied to the defining feature
meta.LoadsAfter.Add(plugin);
}
Logger.features.Warn($"On plugin {plugin.metadata.Name}:");
foreach (var feature in plugin.features)
Logger.features.Warn($" Feature not found with name {feature.feature}");
plugin.CreateFeaturesWhenLoaded.Add(feature);
}
else
{
Logger.features.Warn($"No such feature {feature.Name}");
}
}
}
}
@ -805,20 +798,6 @@ namespace IPA.Loader
Load(meta);
foreach (var feature in meta.Features)
{
if (!feature.BeforeLoad(meta))
{
Logger.loader.Warn(
$"Feature {feature?.GetType()} denied plugin {meta.Name} from loading! {feature?.InvalidMessage}");
ignoredPlugins.Add(meta, new IgnoreReason(Reason.Feature)
{
ReasonText = $"Denied in {nameof(Feature.BeforeLoad)} of feature {feature?.GetType()}:\n\t{feature?.InvalidMessage}"
});
return null;
}
}
PluginExecutor exec;
try
{
@ -833,18 +812,17 @@ namespace IPA.Loader
foreach (var feature in meta.Features)
{
if (!feature.BeforeInit(meta))
try
{
Logger.loader.Warn(
$"Feature {feature?.GetType()} denied plugin {meta.Name} from initializing! {feature?.InvalidMessage}");
ignoredPlugins.Add(meta, new IgnoreReason(Reason.Feature)
{
ReasonText = $"Denied in {nameof(Feature.BeforeInit)} of feature {feature?.GetType()}:\n\t{feature?.InvalidMessage}"
});
return null;
feature.BeforeInit(meta);
}
catch (Exception e)
{
Logger.loader.Critical($"Feature errored in {nameof(Feature.BeforeInit)}:");
Logger.loader.Critical(e);
}
}
try
{
exec.Create();
@ -861,6 +839,21 @@ namespace IPA.Loader
return null;
}
// TODO: make this new features system behave better wrt DynamicInit plugins
foreach (var feature in meta.CreateFeaturesWhenLoaded)
{
if (!feature.TryCreate(out var inst))
{
Logger.features.Warn($"Could not create instance of feature {feature.Name}: {inst.InvalidMessage}");
}
else
{
feature.AppliedTo.InternalFeatures.Add(inst);
feature.AppliedTo.UnloadedFeatures.Remove(feature);
}
}
meta.CreateFeaturesWhenLoaded.Clear(); // if a plugin is loaded twice, for the moment, we don't want to create the feature twice
foreach (var feature in meta.Features)
try
{
@ -868,7 +861,8 @@ namespace IPA.Loader
}
catch (Exception e)
{
Logger.loader.Critical($"Feature errored in {nameof(Feature.AfterInit)}: {e}");
Logger.loader.Critical($"Feature errored in {nameof(Feature.AfterInit)}:");
Logger.loader.Critical(e);
}
return exec;
@ -878,18 +872,25 @@ namespace IPA.Loader
internal static List<PluginExecutor> LoadPlugins()
{
InitFeatures();
DisabledPlugins.ForEach(Load); // make sure they get loaded into memory so their metadata and stuff can be read more easily
var list = new List<PluginExecutor>();
var loaded = new HashSet<PluginMetadata>();
foreach (var meta in PluginsMetadata)
{
var exec = InitPlugin(meta, loaded);
if (exec != null)
try
{
var exec = InitPlugin(meta, loaded);
if (exec != null)
{
list.Add(exec);
loaded.Add(meta);
}
}
catch (Exception e)
{
list.Add(exec);
loaded.Add(meta);
Logger.log.Critical($"Uncaught exception while loading pluign {meta.Name}:");
Logger.log.Critical(e);
}
}


+ 23
- 5
IPA.Loader/Loader/PluginManager.cs View File

@ -14,6 +14,7 @@ using UnityEngine;
using Logger = IPA.Logging.Logger;
using System.Threading.Tasks;
using IPA.Utilities.Async;
using IPA.Loader.Features;
#if NET4
using TaskEx = System.Threading.Tasks.Task;
using TaskEx6 = System.Threading.Tasks.Task;
@ -189,16 +190,33 @@ namespace IPA.Loader
{
if (alreadyDisabled.TryGetValue(exec.Executor, out var task))
return task;
else
else
{
if (exec.Executor.Metadata.RuntimeOptions != RuntimeOptions.DynamicInit)
return TaskEx6.FromException(new CannotRuntimeDisableException(exec.Executor.Metadata));
var res = TaskEx.WhenAll(exec.Dependents.Select(d => Disable(d, alreadyDisabled)))
.ContinueWith(t => t.IsFaulted
? TaskEx.WhenAll(t, TaskEx6.FromException(
new CannotRuntimeDisableException(exec.Executor.Metadata, "Dependents cannot be disabled for plugin")))
: exec.Executor.Disable(), UnityMainThreadTaskScheduler.Default).Unwrap();
.ContinueWith(t =>
{
if (t.IsFaulted) {
return TaskEx.WhenAll(t, TaskEx6.FromException(
new CannotRuntimeDisableException(exec.Executor.Metadata, "Dependents cannot be disabled for plugin")));
}
return exec.Executor.Disable()
.ContinueWith(t =>
{
foreach (var feature in exec.Executor.Metadata.Features)
{
try {
feature.AfterDisable(exec.Executor.Metadata);
}
catch (Exception e)
{
Logger.loader.Critical($"Feature errored in {nameof(Feature.AfterDisable)}: {e}");
}
}
}, UnityMainThreadTaskScheduler.Default);
}, UnityMainThreadTaskScheduler.Default).Unwrap();
// We do not want to call the disable method if a dependent couldn't be disabled
// By scheduling on a UnityMainThreadScheduler, we ensure that Disable() is always called on the Unity main thread
alreadyDisabled.Add(exec.Executor, res);


+ 3
- 2
IPA.Loader/Loader/PluginManifest.cs View File

@ -1,6 +1,7 @@
using IPA.JsonConverters;
using IPA.Utilities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SemVer;
using System;
using System.Collections.Generic;
@ -39,8 +40,8 @@ namespace IPA.Loader
[JsonProperty("conflictsWith", Required = Required.DisallowNull, ItemConverterType = typeof(SemverRangeConverter))]
public Dictionary<string, Range> Conflicts = new Dictionary<string, Range>();
[JsonProperty("features", Required = Required.DisallowNull)]
public string[] Features = Array.Empty<string>();
[JsonProperty("features", Required = Required.DisallowNull), JsonConverter(typeof(FeaturesFieldConverter))]
public Dictionary<string, JObject> Features = new Dictionary<string, JObject>();
[JsonProperty("loadBefore", Required = Required.DisallowNull)]
public string[] LoadBefore = Array.Empty<string>();


+ 4
- 0
IPA.Loader/Loader/PluginMetadata.cs View File

@ -76,6 +76,10 @@ namespace IPA.Loader
internal readonly List<Feature> InternalFeatures = new List<Feature>();
internal readonly HashSet<Feature.Instance> UnloadedFeatures = new HashSet<Feature.Instance>();
internal readonly List<Feature.Instance> CreateFeaturesWhenLoaded = new List<Feature.Instance>();
/// <summary>
/// A list of files (that aren't <see cref="File"/>) that are associated with this plugin.
/// </summary>


+ 10
- 12
IPA.Loader/Loader/manifest.json View File

@ -5,22 +5,20 @@
"#![IPA.Loader.description.md]",
"A mod loader specifically for Beat Saber."
],
"gameVersion": "1.8.0",
"gameVersion": "1.11.0",
"id": "BSIPA",
"name": "Beat Saber IPA",
"version": "4.0.6",
"version": "4.1.0",
"icon": "IPA.icon_white.png",
"features": [
"define-feature(print, IPA.Loader.Features.PrintFeature)",
"define-feature(debug, IPA.Loader.Features.DebugFeature)",
"define-feature(warn, IPA.Loader.Features.WarnFeature)",
"define-feature(no-update, IPA.Loader.Features.NoUpdateFeature)",
"define-feature(init-injector, IPA.Loader.Features.InitInjectorFeature)",
"define-feature(config-provider, IPA.Loader.Features.ConfigProviderFeature)"
],
"features": {
"IPA.DefineFeature": {
"type": "IPA.Loader.Features.ConfigProviderFeature",
"name": "IPA.ConfigProvider"
}
},
"links": {
"project-home": "https://beat-saber-modding-group.github.io/BeatSaber-IPA-Reloaded/index.html",
"project-source": "https://github.com/beat-saber-modding-group/BeatSaber-IPA-Reloaded",
"project-home": "https://bsmg.github.io/BeatSaber-IPA-Reloaded/index.html",
"project-source": "https://github.com/bsmg/BeatSaber-IPA-Reloaded",
"donate": "https://ko-fi.com/danike"
},
"files": [


BIN
IPA.Loader/Thumbs.db View File


+ 0
- 15
IPA.Loader/Updating/BeatMods/Updater.cs View File

@ -204,11 +204,6 @@ namespace IPA.Updating.BeatMods
LocalPluginMeta = msinfo
};
if (msinfo.Features.FirstOrDefault(f => f is NoUpdateFeature) != null)
{ // disable updating, by only matching self, so that dependencies can still be resolved
dep.Requirement = new Range(msinfo.Version.ToString());
}
depList.Value.Add(dep);
}
}
@ -225,11 +220,6 @@ namespace IPA.Updating.BeatMods
LocalPluginMeta = meta
};
if (meta.Features.FirstOrDefault(f => f is NoUpdateFeature) != null)
{ // disable updating, by only matching self
dep.Requirement = new Range(meta.Version.ToString());
}
depList.Value.Add(dep);
}
}
@ -246,11 +236,6 @@ namespace IPA.Updating.BeatMods
LocalPluginMeta = meta
};
if (meta.Features.FirstOrDefault(f => f is NoUpdateFeature) != null)
{ // disable updating, by only matching self
dep.Requirement = new Range(meta.Version.ToString());
}
depList.Value.Add(dep);
}
}


+ 8
- 2
IPA.Loader/Utilities/Async/Coroutines.cs View File

@ -56,16 +56,22 @@ namespace IPA.Utilities.Async
if (!UnityGame.OnMainThread)
return UnityMainThreadTaskScheduler.Factory.StartNew(() => AsTask(coroutine)).Unwrap();
var tcs = new TaskCompletionSource<VoidStruct>(coroutine, TaskCreationOptions.RunContinuationsAsynchronously);
var tcs = new TaskCompletionSource<VoidStruct>(coroutine, AsTaskSourceOptions);
PluginComponent.Instance.StartCoroutine(new AsTaskCoroutineExecutor(coroutine, tcs));
return tcs.Task;
}
#if NET4
private static readonly TaskCreationOptions AsTaskSourceOptions = TaskCreationOptions.RunContinuationsAsynchronously;
#else
private static readonly TaskCreationOptions AsTaskSourceOptions = TaskCreationOptions.None;
#endif
private struct VoidStruct { }
private class ExceptionLocation : Exception
{
public ExceptionLocation(IEnumerable<string> locations)
: base(string.Join("\n", locations.Select(s => "in " + s)))
: base(string.Join("\n", Utils.StrJP(locations.Select(s => "in " + s))))
{
}
}


+ 180
- 180
IPA.Loader/Utilities/CriticalSection.cs View File

@ -1,185 +1,185 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using IPA.Logging;
namespace IPA.Utilities
{
/// <summary>
/// Provides utilities for managing various critical sections.
/// </summary>
public static class CriticalSection
{
internal static void Configure()
{
Logger.log.Debug("Configuring exit handlers");
ResetExitHandlers();
}
private static void Reset(object sender, EventArgs e)
{
Win32.SetConsoleCtrlHandler(registeredHandler, false);
WinHttp.SetPeekMessageHook(null);
}
#region Execute section
private static readonly Win32.ConsoleCtrlDelegate registeredHandler = HandleExit;
internal static void ResetExitHandlers()
{
Win32.SetConsoleCtrlHandler(registeredHandler, false);
Win32.SetConsoleCtrlHandler(registeredHandler, true);
WinHttp.SetPeekMessageHook(PeekMessageHook);
AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using IPA.Logging;
namespace IPA.Utilities
{
/// <summary>
/// Provides utilities for managing various critical sections.
/// </summary>
public static class CriticalSection
{
internal static void Configure()
{
Logger.log.Debug("Configuring exit handlers");
ResetExitHandlers();
}
private static void Reset(object sender, EventArgs e)
{
Win32.SetConsoleCtrlHandler(registeredHandler, false);
WinHttp.SetPeekMessageHook(null);
}
#region Execute section
private static readonly Win32.ConsoleCtrlDelegate registeredHandler = HandleExit;
internal static void ResetExitHandlers()
{
Win32.SetConsoleCtrlHandler(registeredHandler, false);
Win32.SetConsoleCtrlHandler(registeredHandler, true);
WinHttp.SetPeekMessageHook(PeekMessageHook);
AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
}
private static void OnProcessExit(object sender, EventArgs args)
{
WinHttp.SetIgnoreUnhandledExceptions(true);
}
private static class WinHttp
{
public delegate bool PeekMessageHook(
bool isW,
uint result,
[MarshalAs(UnmanagedType.LPStruct)]
in Win32.MSG message,
IntPtr hwnd,
uint filterMin,
uint filterMax,
ref Win32.PeekMessageParams removeMsg);
[DllImport("bsipa-doorstop")]
public static extern void SetPeekMessageHook(
[MarshalAs(UnmanagedType.FunctionPtr)]
}
private static class WinHttp
{
public delegate bool PeekMessageHook(
bool isW,
uint result,
[MarshalAs(UnmanagedType.LPStruct)]
in Win32.MSG message,
IntPtr hwnd,
uint filterMin,
uint filterMax,
ref Win32.PeekMessageParams removeMsg);
[DllImport("bsipa-doorstop")]
public static extern void SetPeekMessageHook(
[MarshalAs(UnmanagedType.FunctionPtr)]
PeekMessageHook hook);
[DllImport("bsipa-doorstop")]
public static extern void SetIgnoreUnhandledExceptions(
[MarshalAs(UnmanagedType.Bool)] bool ignore);
}
private static Win32.ConsoleCtrlDelegate _handler = null;
private static volatile bool isInExecuteSection = false;
// returns true to continue looping and calling PeekMessage
private static bool PeekMessageHook(
bool isW,
uint result,
[MarshalAs(UnmanagedType.LPStruct)]
in Win32.MSG message,
IntPtr hwnd,
uint filterMin,
uint filterMax,
ref Win32.PeekMessageParams removeMsg)
{
if (isInExecuteSection)
{
if (result == 0) return false;
switch (message.message)
{
case Win32.WM.CLOSE:
if (removeMsg != Win32.PeekMessageParams.PM_REMOVE)
{
removeMsg = Win32.PeekMessageParams.PM_REMOVE;
exitRecieved = true;
return true;
}
else
{
removeMsg = Win32.PeekMessageParams.PM_NOREMOVE;
return true;
}
default:
return false;
}
}
return false;
}
private static bool HandleExit(Win32.CtrlTypes type)
{
if (_handler != null)
return _handler(type);
return false;
}
private static volatile bool exitRecieved = false;
/// <summary>
/// A struct that allows <c>using</c> blocks to manage an execute section.
/// </summary>
public struct AutoExecuteSection : IDisposable
{
private readonly bool constructed;
internal AutoExecuteSection(bool val)
{
constructed = val && !isInExecuteSection;
if (constructed)
EnterExecuteSection();
}
void IDisposable.Dispose()
{
if (constructed)
ExitExecuteSection();
}
}
/// <summary>
/// Creates an <see cref="AutoExecuteSection"/> for automated management of an execute section.
/// </summary>
/// <returns>the new <see cref="AutoExecuteSection"/> that manages the section</returns>
public static AutoExecuteSection ExecuteSection() => new AutoExecuteSection(true);
/// <summary>
/// Enters a critical execution section. Does not nest.
/// </summary>
/// <note>
/// During a critical execution section, the program must execute until the end of the section before
/// exiting. If an exit signal is recieved during the section, it will be canceled, and the process
/// will terminate at the end of the section.
/// </note>
public static void EnterExecuteSection()
{
ResetExitHandlers();
exitRecieved = false;
_handler = sig => exitRecieved = true;
isInExecuteSection = true;
}
/// <summary>
/// Exits a critical execution section. Does not nest.
/// </summary>
/// <note>
/// During a critical execution section, the program must execute until the end of the section before
/// exiting. If an exit signal is recieved during the section, it will be canceled, and the process
/// will terminate at the end of the section.
/// </note>
public static void ExitExecuteSection()
{
_handler = null;
isInExecuteSection = false;
Reset(null, null);
if (exitRecieved)
Environment.Exit(1);
}
#endregion
}
}
[DllImport("bsipa-doorstop")]
public static extern void SetIgnoreUnhandledExceptions(
[MarshalAs(UnmanagedType.Bool)] bool ignore);
}
private static Win32.ConsoleCtrlDelegate _handler = null;
private static volatile bool isInExecuteSection = false;
// returns true to continue looping and calling PeekMessage
private static bool PeekMessageHook(
bool isW,
uint result,
[MarshalAs(UnmanagedType.LPStruct)]
in Win32.MSG message,
IntPtr hwnd,
uint filterMin,
uint filterMax,
ref Win32.PeekMessageParams removeMsg)
{
if (isInExecuteSection)
{
if (result == 0) return false;
switch (message.message)
{
case Win32.WM.CLOSE:
if (removeMsg != Win32.PeekMessageParams.PM_REMOVE)
{
removeMsg = Win32.PeekMessageParams.PM_REMOVE;
exitRecieved = true;
return true;
}
else
{
removeMsg = Win32.PeekMessageParams.PM_NOREMOVE;
return true;
}
default:
return false;
}
}
return false;
}
private static bool HandleExit(Win32.CtrlTypes type)
{
if (_handler != null)
return _handler(type);
return false;
}
private static volatile bool exitRecieved = false;
/// <summary>
/// A struct that allows <c>using</c> blocks to manage an execute section.
/// </summary>
public struct AutoExecuteSection : IDisposable
{
private readonly bool constructed;
internal AutoExecuteSection(bool val)
{
constructed = val && !isInExecuteSection;
if (constructed)
EnterExecuteSection();
}
void IDisposable.Dispose()
{
if (constructed)
ExitExecuteSection();
}
}
/// <summary>
/// Creates an <see cref="AutoExecuteSection"/> for automated management of an execute section.
/// </summary>
/// <returns>the new <see cref="AutoExecuteSection"/> that manages the section</returns>
public static AutoExecuteSection ExecuteSection() => new AutoExecuteSection(true);
/// <summary>
/// Enters a critical execution section. Does not nest.
/// </summary>
/// <note>
/// During a critical execution section, the program must execute until the end of the section before
/// exiting. If an exit signal is recieved during the section, it will be canceled, and the process
/// will terminate at the end of the section.
/// </note>
public static void EnterExecuteSection()
{
ResetExitHandlers();
exitRecieved = false;
_handler = sig => exitRecieved = true;
isInExecuteSection = true;
}
/// <summary>
/// Exits a critical execution section. Does not nest.
/// </summary>
/// <note>
/// During a critical execution section, the program must execute until the end of the section before
/// exiting. If an exit signal is recieved during the section, it will be canceled, and the process
/// will terminate at the end of the section.
/// </note>
public static void ExitExecuteSection()
{
_handler = null;
isInExecuteSection = false;
Reset(null, null);
if (exitRecieved)
Environment.Exit(1);
}
#endregion
}
}

+ 1
- 1
IPA/Program.cs View File

@ -23,7 +23,7 @@ namespace IPA
Unknown
}
public const string FileVersion = "4.0.6.0";
public const string FileVersion = "4.1.0.0";
public static Version Version => Assembly.GetEntryAssembly().GetName().Version;


+ 41
- 41
Net3-Proxy/CompilerServices.cs View File

@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace System.Runtime.CompilerServices
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace System.Runtime.CompilerServices
{
public sealed class ConditionalWeakTable<TKey, TValue> where TKey : class where TValue : class
{
private readonly Dictionary<WeakReference<TKey>, TValue> items = new Dictionary<WeakReference<TKey>, TValue>();
private readonly object _lock = new object();
{
private readonly Dictionary<WeakReference<TKey>, TValue> items = new Dictionary<WeakReference<TKey>, TValue>();
private readonly object _lock = new object();
private sealed class KeyComparer : IEqualityComparer<WeakReference<TKey>>
{
public bool Equals(WeakReference<TKey> x, WeakReference<TKey> y)
@ -17,11 +17,11 @@ namespace System.Runtime.CompilerServices
public int GetHashCode(WeakReference<TKey> obj)
=> obj.TryGetTarget(out var key) ? key.GetHashCode() : 0;
}
private static WeakReference<TKey> WeakRef(TKey key)
=> new WeakReference<TKey>(key);
}
private static WeakReference<TKey> WeakRef(TKey key)
=> new WeakReference<TKey>(key);
private sealed class GCTracker
{
public static event Action OnGC;
@ -32,11 +32,11 @@ namespace System.Runtime.CompilerServices
if (!AppDomain.CurrentDomain.IsFinalizingForUnload() && !Environment.HasShutdownStarted)
tracker.SetTarget(new GCTracker());
}
}
}
public void Add(TKey key, TValue value)
{
if (key == null)
{
if (key == null)
throw new ArgumentException("Null key", nameof(key));
lock (_lock)
items.Add(WeakRef(key), value);
@ -52,8 +52,8 @@ namespace System.Runtime.CompilerServices
return items.TryGetValue(WeakRef(key), out value);
}
public delegate TValue CreateValueCallback(TKey key);
public delegate TValue CreateValueCallback(TKey key);
public TValue GetValue(TKey key, CreateValueCallback createValueCallback)
{
if (createValueCallback == null)
@ -70,29 +70,29 @@ namespace System.Runtime.CompilerServices
return value;
}
}
}
public TValue GetOrCreateValue(TKey key)
=> GetValue(key, k => Activator.CreateInstance<TValue>());
}
public TValue GetOrCreateValue(TKey key)
=> GetValue(key, k => Activator.CreateInstance<TValue>());
public bool Remove(TKey key)
{
if (key == null)
throw new ArgumentException("Null key", nameof(key));
{
if (key == null)
throw new ArgumentException("Null key", nameof(key));
return items.Remove(WeakRef(key));
}
public ConditionalWeakTable()
=> GCTracker.OnGC += OnGC;
~ConditionalWeakTable()
=> GCTracker.OnGC -= OnGC;
}
public ConditionalWeakTable()
=> GCTracker.OnGC += OnGC;
~ConditionalWeakTable()
=> GCTracker.OnGC -= OnGC;
private void OnGC()
{
// on each GC, we want to clear the entire set of empty keys
var nullWeakRef = WeakRef(null);
while (items.Remove(nullWeakRef)) ; // just loop
}
}
}
}
}
}

+ 9
- 60
Net3-Proxy/Net3-Proxy.csproj View File

@ -1,66 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{642F52DA-90F9-40E3-8784-6964F36752FB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworks>net35</TargetFrameworks>
<RootNamespace>Net3_Proxy</RootNamespace>
<AssemblyName>Net3-Proxy</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>portable</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Array.cs" />
<Compile Include="CompilerServices.cs" />
<Compile Include="Directory.cs" />
<Compile Include="ExpressionEx.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="File.cs" />
<Compile Include="ReadOnlyCollections.cs" />
<Compile Include="Path.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TaskEx6.cs" />
<Compile Include="Tuple.cs" />
<Compile Include="TypeUtils.cs" />
<Compile Include="Utils.cs" />
<Compile Include="WeakReference.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncBridge">
<Version>0.3.1</Version>
</PackageReference>
<PackageReference Include="Portable.System.ValueTuple">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="AsyncBridge" Version="0.3.1" />
<PackageReference Include="Portable.System.ValueTuple" Version="1.0.1" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>

+ 2
- 2
README.md View File

@ -1,3 +1,3 @@
# ![BSIPA](docs/images/banner_dark.svg) [![Build status](https://ci.appveyor.com/api/projects/status/1ruhnnfeudrrd097?svg=true)](https://ci.appveyor.com/project/nike4613/beatsaber-ipa-reloaded-9smsb)
# ![BSIPA](docs/images/banner_dark.svg) [![Build](https://github.com/bsmg/BeatSaber-IPA-Reloaded/workflows/Build/badge.svg)](https://github.com/bsmg/BeatSaber-IPA-Reloaded)
[ALL DOCUMENTATION HAS MOVED HERE](https://beat-saber-modding-group.github.io/BeatSaber-IPA-Reloaded/)
[ALL DOCUMENTATION HAS MOVED HERE](https://bsmg.github.io/BeatSaber-IPA-Reloaded/)

+ 0
- 182
appveyor.yml View File

@ -1,182 +0,0 @@
version: 'BSIPA-{branch}-{build}'
environment:
bsipa_version: '4.0.6'
gh_token:
secure: E42gl/yepETuoLSwbJZ1GmEIPK6cCJu6zkd59NA21XiICtEV6COOLW7aehi1tcVU
do_deploy: true
BuildForBeatSaber: 'false'
BUILD_DOC: 'no'
pull_requests:
do_not_increment_build_number: true
init:
- git config --global core.autocrlf true
install:
- git submodule update --init --recursive
- nuget restore
- ps: |
if (-Not $env:APPVEYOR_PULL_REQUEST_TITLE -And $env:BUILD_DOC -Eq 'yes')
{
choco install docfx -y
}
image: Visual Studio 2019
configuration: Release
platform:
- x64-Net4
- x86-Net4
- x64-Net3
- x86-Net3
artifacts: # When Net3 is added, this will need to be moved to the for block to only run for Net4 builds
- path: BSIPA-ModList/bin/Release
name: ModList
- path: BSIPA-Meta/bin/$(platform)/$(configuration)
name: BSIPA-$(platform)
matrix:
allow_failures:
- platform: x64-Net3
- platform: x86-Net3
for:
-
matrix:
only:
- platform: x64-Net4
environment:
BuildForBeatSaber: 'true'
-
matrix:
except:
- BUILD_DOC: 'yes'
skip_tags: true
-
matrix:
only:
- BUILD_DOC: 'yes'
artifacts:
environment:
do_deploy: false
skip_tags: false
build_script:
- ps: |
cd docs
$tagsName = "tags"
$branchName = "branch"
function Git-Do {
git config --global core.autocrlf true
git config --global credential.helper store
Add-Content "$HOME\.git-credentials" "https://$($env:gh_token):[email protected]`n"
git config --global user.email $env:APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL
git config --global user.name $env:APPVEYOR_REPO_COMMIT_AUTHOR
git clone -q "https://github.com/beat-saber-modding-group/BeatSaber-IPA-Reloaded.git" -b gh-pages origin_site
if (-Not (Test-Path origin_site/$tagsName))
{ New-Item -ItemType directory -Path origin_site/$tagsName }
if (-Not (Test-Path origin_site/$branchName))
{ New-Item -ItemType directory -Path origin_site/$branchName }
}
function Do-DocFX
{
Add-Content link_branch.json "{`"_gitContribute`":{`"sourceBranch`":`"$env:APPVEYOR_REPO_COMMIT`",`"apiSpecFolder`":`"docs/override`"}}"
powershell .\build.ps1
if ($lastexitcode -ne 0){
throw [System.Exception] "docfx build failed with exit code $lastexitcode."
}
}
if ($env:APPVEYOR_REPO_TAG -eq "true" -And $env:APPVEYOR_REPO_BRANCH -eq 'master')
{ # Copy current site into tags
& Do-DocFX
& Git-Do
cd origin_site # make things a bit easier
$tagPath = "$tagsName/$env:APPVEYOR_REPO_TAG_NAME"
Move-Item ../_site $tagPath
git add -A 2>&1
git commit -q -a -m "Saved tag $env:APPVEYOR_REPO_TAG_NAME" 2>&1
}
elseif (-Not $env:APPVEYOR_PULL_REQUEST_TITLE)
{ # Generate docs
$message = ""
if ($env:APPVEYOR_REPO_BRANCH -eq 'master')
{ # do the special generation for master
& Do-DocFX
& Git-Do
Move-Item origin_site/.git _site
Move-Item origin_site/$tagsName _site
Move-Item origin_site/$branchName _site
cd _site
$message = "Generated Docs -- $env:APPVEYOR_REPO_COMMIT_MESSAGE"
}
else
{ # generate for another branch; this is more similar to the tag code
& Do-DocFX
& Git-Do
cd origin_site # make things a bit easier
$branchPath = "$branchName/$env:APPVEYOR_REPO_BRANCH"
# force remove it
Get-ChildItem -Path $branchPath -Recurse | Remove-Item -Force -Recurse
Remove-Item $branchPath -Force
# move generated into place
Move-Item ../_site $branchPath
$message = "Generated Docs ($env:APPVEYOR_REPO_BRANCH) -- $env:APPVEYOR_REPO_COMMIT_MESSAGE"
}
git add -A 2>&1
git commit -q -a -m "$message" 2>&1
}
git push -q origin gh-pages 2>&1
branches:
except:
- gh-pages
cache:
- '%LocalAppData%\NuGet\v3-cache' # NuGet v3
build:
verbosity: normal
project: BSIPA.sln
deploy:
- provider: GitHub
release: BSIPA $(bsipa_version)-draft
tag: $(bsipa_version)-d
description: |
**Build:** [$(bsipa_version)-$(APPVEYOR_BUILD_NUMBER)](https://ci.appveyor.com/project/nike4613/beatsaber-ipa-reloaded-9smsb/builds/$(APPVEYOR_BUILD_ID))
**Latest Commit:** $(APPVEYOR_REPO_COMMIT)
- `$(APPVEYOR_REPO_COMMIT_MESSAGE)`
- `$(APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED)`
auth_token:
secure: KhF3q/zWEFwrW0QeZLqE3NAkWR4u9iVhsmcyzXvwwJ28fUy+MzW4CWBx3RxNM60t
artifact: '/.*[^_]\.zip/'
draft: true
force_update: true
on:
branch: master
APPVEYOR_REPO_TAG: false
do_deploy: true

Loading…
Cancel
Save