diff --git a/.github/release_draft.yml b/.github/release_draft.yml new file mode 100644 index 00000000..065b41c8 --- /dev/null +++ b/.github/release_draft.yml @@ -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) \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..7e03ec99 --- /dev/null +++ b/.github/workflows/build.yml @@ -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/ \ No newline at end of file diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 45f0e3f6..df137a93 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -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: diff --git a/BSIPA-Meta/BSIPA-Meta.csproj b/BSIPA-Meta/BSIPA-Meta.csproj index 3e2e4722..b91fbb9b 100644 --- a/BSIPA-Meta/BSIPA-Meta.csproj +++ b/BSIPA-Meta/BSIPA-Meta.csproj @@ -1,99 +1,68 @@ - - - + + - Debug - x64-Net4 - {880A3560-82CD-4836-996B-11BEFE6B44DB} - Library + net35;net461 + x86;x64 + Debug;Release;Verbose;Verbose_Release + BSIPA_Meta - Meta Project - v4.6.1 - 512 - true - true - bin\$(Platform)\$(Configuration)\ - - - - Win32 - - - x64 - - - Net4 - - - Net3 - - - AnyCPU - true - full - false - DEBUG;TRACE - prompt - 4 - Debug - Debug - Release + false + true + + Assemble + Assemble - - AnyCPU - pdbonly - true - TRACE - prompt - 4 - Release - Release + + + bin\$(Platform)\$(Configuration)\ + + false + true + + $(Configuration) + Debug + Release + Release + Verbose_Release + + Win32 + x64 - - AnyCPU - true - full - false - DEBUG;TRACE - prompt - 4 - Debug - Verbose - Verbose_Release - - - AnyCPU - pdbonly - true - TRACE - prompt - 4 - Release - Verbose_Release - Verbose_Release - - + + + + + Configuration=$(NoVerboseConfig) + Platform=AnyCPU + + + Configuration=$(NoVerboseConfig) + Platform=AnyCPU + + + Configuration=$(ProxyConfig) + Platform=$(ProxyPlatform) + + + - - - - + - + - + @@ -107,4 +76,5 @@ - \ No newline at end of file + + diff --git a/BSIPA.sln b/BSIPA.sln index f18b56a4..bda99539 100644 --- a/BSIPA.sln +++ b/BSIPA.sln @@ -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 diff --git a/IPA.Injector/IPA.Injector.csproj b/IPA.Injector/IPA.Injector.csproj index ce6b687c..537ac45d 100644 --- a/IPA.Injector/IPA.Injector.csproj +++ b/IPA.Injector/IPA.Injector.csproj @@ -1,155 +1,106 @@ - - - - - Debug - Net4 - true - {2A1AF16B-27F1-46E0-9A95-181516BC1CB7} - Library - Properties - IPA.Injector - IPA.Injector - 512 - true - $(SolutionDir)=C:\ - portable - false - true - net461;net35 - 8.0 - true - - - true - false - bin\$(Platform)\Debug\ - DEBUG;TRACE - prompt - 4 - - - true - bin\$(Platform)\Release\ - TRACE - prompt - 4 - - - v4.6.1 - $(DefineConstants);NET4 - - - v3.5 - $(DefineConstants);NET3 - - - $(DefineConstants);BeatSaber - - - - - - - - - - ..\Refs\UnityEngine.CoreModule.Net4.dll - False - - - ..\Refs\UnityEngine.CoreModule.Net3.dll - False - - - - - - - - - - - - - - - - - {5ad344f0-01a0-4ca8-92e5-9d095737744d} - IPA.Loader - - - {642F52DA-90F9-40E3-8784-6964F36752FB} - Net3-Proxy - - - - - Libraries\Mono\I18N.dll - Always - - - Libraries\Mono\I18N.West.dll - Always - - - Libraries\Mono\Microsoft.CSharp.dll - Always - - - Libraries\Mono\System.Runtime.Serialization.dll - Always - - - - - Libraries\Mono\I18N.dll - Always - - - Libraries\Mono\I18N.West.dll - Always - - - Libraries\Mono\System.Runtime.Serialization.dll - Always - - - - - 0.10.4 - - - 1.2.2 - - - 0.3.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + net461;net35 + IPA.Injector + + portable + 8.0 + true + CA1031 + false + false + true + + + + $(DefineConstants);NET4 + + + $(DefineConstants);NET3 + + + $(DefineConstants);BeatSaber + + + + + + + + + + ..\Refs\UnityEngine.CoreModule.Net4.dll + False + + + ..\Refs\UnityEngine.CoreModule.Net3.dll + False + + + + + + Libraries\Mono\I18N.dll + Always + + + Libraries\Mono\I18N.West.dll + Always + + + Libraries\Mono\Microsoft.CSharp.dll + Always + + + Libraries\Mono\System.Runtime.Serialization.dll + Always + + + + + Libraries\Mono\I18N.dll + Always + + + Libraries\Mono\I18N.West.dll + Always + + + Libraries\Mono\System.Runtime.Serialization.dll + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IPA.Loader/Config/SelfConfig.cs b/IPA.Loader/Config/SelfConfig.cs index 2611a6cb..e682eaea 100644 --- a/IPA.Loader/Config/SelfConfig.cs +++ b/IPA.Loader/Config/SelfConfig.cs @@ -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 diff --git a/IPA.Loader/IPA.Loader.csproj b/IPA.Loader/IPA.Loader.csproj index c5b0d59e..2ccd3b90 100644 --- a/IPA.Loader/IPA.Loader.csproj +++ b/IPA.Loader/IPA.Loader.csproj @@ -1,68 +1,29 @@ - - - + + - Debug - Net4 - true - {5AD344F0-01A0-4CA8-92E5-9D095737744D} - Library - Properties + net461;net35 IPA - IPA.Loader - 512 - true - $(SolutionDir)=C:\ + portable - false - true - net461;net35 8.0 true CA1031 + true + false + true - - true - false - bin\$(Platform)\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - true - bin\$(Platform)\Release\ - TRACE - prompt - 4 - false - - - v4.6.1 + + $(DefineConstants);NET4 - - v3.5 + $(DefineConstants);NET3 - + $(DefineConstants);BeatSaber - - $(OutputPath)IPA.Loader.xml - - - - - - - - - - - - + + ..\Refs\UnityEngine.CoreModule.Net4.dll False @@ -72,7 +33,7 @@ False - + ..\Refs\UnityEngine.CoreModule.Net3.dll False @@ -82,131 +43,25 @@ False + - - {642F52DA-90F9-40E3-8784-6964F36752FB} - Net3-Proxy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - 1.9.1.8 - - - 2.0.0.7 - - - 0.10.4 - - - 12.0.3 - - - 1.0.1 - - - 1.2.2 - - - 0.3.1 - + + + + + + + + - - - - - - \ No newline at end of file + + diff --git a/IPA.Loader/JsonConverters/FeaturesFieldConverter.cs b/IPA.Loader/JsonConverters/FeaturesFieldConverter.cs new file mode 100644 index 00000000..97cccb18 --- /dev/null +++ b/IPA.Loader/JsonConverters/FeaturesFieldConverter.cs @@ -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> + { + public override Dictionary ReadJson(JsonReader reader, Type objectType, Dictionary existingValue, bool hasExistingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.StartArray) + { + _ = serializer.Deserialize(reader); + Logger.features.Warn("Encountered old features used. They no longer do anything, please move to the new format."); + return existingValue; + } + + return serializer.Deserialize>(reader); + } + + public override void WriteJson(JsonWriter writer, Dictionary value, JsonSerializer serializer) + { + serializer.Serialize(writer, value); + } + } +} diff --git a/IPA.Loader/Loader/Features/ConfigProviderFeature.cs b/IPA.Loader/Loader/Features/ConfigProviderFeature.cs index 95c4ff38..61ab95f9 100644 --- a/IPA.Loader/Loader/Features/ConfigProviderFeature.cs +++ b/IPA.Loader/Loader/Features/ConfigProviderFeature.cs @@ -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(); + } + 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) diff --git a/IPA.Loader/Loader/Features/DefineFeature.cs b/IPA.Loader/Loader/Features/DefineFeature.cs index 6835cc32..9cba0a8c 100644 --- a/IPA.Loader/Loader/Features/DefineFeature.cs +++ b/IPA.Loader/Loader/Features/DefineFeature.cs @@ -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(); + } + 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; } } } diff --git a/IPA.Loader/Loader/Features/Feature.cs b/IPA.Loader/Loader/Features/Feature.cs index 20d07728..df70401e 100644 --- a/IPA.Loader/Loader/Features/Feature.cs +++ b/IPA.Loader/Loader/Features/Feature.cs @@ -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 { /// - /// Initializes the feature with the parameters provided in the definition. - /// - /// Note: When no parenthesis are provided, is an empty array. + /// Initializes the feature with the data provided in the definition. /// /// - /// This gets called BEFORE *your* `Init` method. - /// - /// Returning does *not* prevent the plugin from being loaded. It simply prevents the feature from being used. + /// This gets called AFTER your Init method, but BEFORE the target's Init method. If it is applied to the defining plugin, BeforeInit is not called. + /// Returning does not prevent the plugin from being loaded. It simply prevents the feature from being used. /// /// the metadata of the plugin that is being prepared - /// the parameters passed to the feature definition, or null + /// the data provided with the feature /// if the feature is valid for the plugin, otherwise - public abstract bool Initialize(PluginMetadata meta, string[] parameters); - - /// - /// 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 from - /// - /// the truthiness of the Feature. - public virtual bool Evaluate() => true; + protected abstract bool Initialize(PluginMetadata meta, JObject featureData); /// /// The message to be logged when the feature is not valid for a plugin. - /// This should also be set whenever either or returns false. + /// This should also be set whenever either returns false. /// /// the message to show when the feature is marked invalid public virtual string InvalidMessage { get; protected set; } - /// - /// Called before a plugin is loaded. This should never throw an exception. An exception will abort the loading of the plugin with an error. - /// - /// - /// The assembly will still be loaded, but the plugin will not be constructed if this returns . - /// Any features it defines, for example, will still be loaded. - /// - /// the plugin about to be loaded - /// whether or not the plugin should be loaded - public virtual bool BeforeLoad(PluginMetadata plugin) => true; - /// /// 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. /// /// the plugin to be initialized /// whether or not to call the Init method - public virtual bool BeforeInit(PluginMetadata plugin) => true; + public virtual void BeforeInit(PluginMetadata plugin) { } /// /// 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) { } /// - /// Ensures a plugin's assembly is loaded. Do not use unless you need to. - /// - /// the plugin to ensure is loaded. - protected void RequireLoaded(PluginMetadata plugin) => PluginLoader.Load(plugin); - - /// - /// 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. /// - /// if this will be stored on the plugin metadata, otherwise - protected internal virtual bool StoreOnPlugin => true; + /// the plugin that was disabled + 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 { - { "define-feature", typeof(DefineFeature) } + { "IPA.DefineFeature", typeof(DefineFeature) } + }; + featureDelcarers = new Dictionary + { + { "IPA.DefineFeature", null } }; } private static Dictionary featureTypes; + private static Dictionary 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; } - } + }*/ } } \ No newline at end of file diff --git a/IPA.Loader/Loader/Features/InitInjectorFeature.cs b/IPA.Loader/Loader/Features/InitInjectorFeature.cs deleted file mode 100644 index af6487f9..00000000 --- a/IPA.Loader/Loader/Features/InitInjectorFeature.cs +++ /dev/null @@ -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()); - } - 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; - } - } - } -} diff --git a/IPA.Loader/Loader/Features/NoUpdateFeature.cs b/IPA.Loader/Loader/Features/NoUpdateFeature.cs deleted file mode 100644 index afe38972..00000000 --- a/IPA.Loader/Loader/Features/NoUpdateFeature.cs +++ /dev/null @@ -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"; - } -} diff --git a/IPA.Loader/Loader/Features/PrintFeature.cs b/IPA.Loader/Loader/Features/PrintFeature.cs deleted file mode 100644 index 2acc48d8..00000000 --- a/IPA.Loader/Loader/Features/PrintFeature.cs +++ /dev/null @@ -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; - } - } -} diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index 98e377e8..95038cfb 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -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 in an structure, the member /// will contain the thrown exception. /// - Error, + Error, /// /// 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. /// - Released, + Released, /// /// The plugin this reason is associated with was denied from loading by a /// that it marks. /// - Feature, + Feature, /// /// The plugin this reason is assoicated with is unsupported. /// @@ -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 ignoredPlugins = new Dictionary(); @@ -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(); var ignore = new Dictionary(); var resolved = new List(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(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 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(); var loaded = new HashSet(); 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); } } diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs index c8af2db6..28f117f0 100644 --- a/IPA.Loader/Loader/PluginManager.cs +++ b/IPA.Loader/Loader/PluginManager.cs @@ -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); diff --git a/IPA.Loader/Loader/PluginManifest.cs b/IPA.Loader/Loader/PluginManifest.cs index f36f6e9d..7361975e 100644 --- a/IPA.Loader/Loader/PluginManifest.cs +++ b/IPA.Loader/Loader/PluginManifest.cs @@ -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 Conflicts = new Dictionary(); - [JsonProperty("features", Required = Required.DisallowNull)] - public string[] Features = Array.Empty(); + [JsonProperty("features", Required = Required.DisallowNull), JsonConverter(typeof(FeaturesFieldConverter))] + public Dictionary Features = new Dictionary(); [JsonProperty("loadBefore", Required = Required.DisallowNull)] public string[] LoadBefore = Array.Empty(); diff --git a/IPA.Loader/Loader/PluginMetadata.cs b/IPA.Loader/Loader/PluginMetadata.cs index 22e83805..5ff7b92b 100644 --- a/IPA.Loader/Loader/PluginMetadata.cs +++ b/IPA.Loader/Loader/PluginMetadata.cs @@ -76,6 +76,10 @@ namespace IPA.Loader internal readonly List InternalFeatures = new List(); + internal readonly HashSet UnloadedFeatures = new HashSet(); + + internal readonly List CreateFeaturesWhenLoaded = new List(); + /// /// A list of files (that aren't ) that are associated with this plugin. /// diff --git a/IPA.Loader/Loader/manifest.json b/IPA.Loader/Loader/manifest.json index a38fc719..9eddc4b7 100644 --- a/IPA.Loader/Loader/manifest.json +++ b/IPA.Loader/Loader/manifest.json @@ -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": [ diff --git a/IPA.Loader/Thumbs.db b/IPA.Loader/Thumbs.db deleted file mode 100644 index 25f19c79..00000000 Binary files a/IPA.Loader/Thumbs.db and /dev/null differ diff --git a/IPA.Loader/Updating/BeatMods/Updater.cs b/IPA.Loader/Updating/BeatMods/Updater.cs index 200c8d0c..33b4596c 100644 --- a/IPA.Loader/Updating/BeatMods/Updater.cs +++ b/IPA.Loader/Updating/BeatMods/Updater.cs @@ -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); } } diff --git a/IPA.Loader/Utilities/Async/Coroutines.cs b/IPA.Loader/Utilities/Async/Coroutines.cs index b4134dfd..b474e566 100644 --- a/IPA.Loader/Utilities/Async/Coroutines.cs +++ b/IPA.Loader/Utilities/Async/Coroutines.cs @@ -56,16 +56,22 @@ namespace IPA.Utilities.Async if (!UnityGame.OnMainThread) return UnityMainThreadTaskScheduler.Factory.StartNew(() => AsTask(coroutine)).Unwrap(); - var tcs = new TaskCompletionSource(coroutine, TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(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 locations) - : base(string.Join("\n", locations.Select(s => "in " + s))) + : base(string.Join("\n", Utils.StrJP(locations.Select(s => "in " + s)))) { } } diff --git a/IPA.Loader/Utilities/CriticalSection.cs b/IPA.Loader/Utilities/CriticalSection.cs index 60930b50..c5ed1029 100644 --- a/IPA.Loader/Utilities/CriticalSection.cs +++ b/IPA.Loader/Utilities/CriticalSection.cs @@ -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 -{ - /// - /// Provides utilities for managing various critical sections. - /// - 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 +{ + /// + /// Provides utilities for managing various critical sections. + /// + 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; - - /// - /// A struct that allows using blocks to manage an execute section. - /// - public struct AutoExecuteSection : IDisposable - { - private readonly bool constructed; - internal AutoExecuteSection(bool val) - { - constructed = val && !isInExecuteSection; - if (constructed) - EnterExecuteSection(); - } - - void IDisposable.Dispose() - { - if (constructed) - ExitExecuteSection(); - } - } - - /// - /// Creates an for automated management of an execute section. - /// - /// the new that manages the section - public static AutoExecuteSection ExecuteSection() => new AutoExecuteSection(true); - - /// - /// Enters a critical execution section. Does not nest. - /// - /// - /// 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. - /// - public static void EnterExecuteSection() - { - ResetExitHandlers(); - - exitRecieved = false; - _handler = sig => exitRecieved = true; - isInExecuteSection = true; - } - - /// - /// Exits a critical execution section. Does not nest. - /// - /// - /// 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. - /// - 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; + + /// + /// A struct that allows using blocks to manage an execute section. + /// + public struct AutoExecuteSection : IDisposable + { + private readonly bool constructed; + internal AutoExecuteSection(bool val) + { + constructed = val && !isInExecuteSection; + if (constructed) + EnterExecuteSection(); + } + + void IDisposable.Dispose() + { + if (constructed) + ExitExecuteSection(); + } + } + + /// + /// Creates an for automated management of an execute section. + /// + /// the new that manages the section + public static AutoExecuteSection ExecuteSection() => new AutoExecuteSection(true); + + /// + /// Enters a critical execution section. Does not nest. + /// + /// + /// 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. + /// + public static void EnterExecuteSection() + { + ResetExitHandlers(); + + exitRecieved = false; + _handler = sig => exitRecieved = true; + isInExecuteSection = true; + } + + /// + /// Exits a critical execution section. Does not nest. + /// + /// + /// 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. + /// + public static void ExitExecuteSection() + { + _handler = null; + isInExecuteSection = false; + + Reset(null, null); + + if (exitRecieved) + Environment.Exit(1); + } + + #endregion + } +} diff --git a/IPA/Program.cs b/IPA/Program.cs index 0f95ca8e..9c6b100f 100644 --- a/IPA/Program.cs +++ b/IPA/Program.cs @@ -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; diff --git a/Net3-Proxy/CompilerServices.cs b/Net3-Proxy/CompilerServices.cs index 5ef760f5..d721f4b3 100644 --- a/Net3-Proxy/CompilerServices.cs +++ b/Net3-Proxy/CompilerServices.cs @@ -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 where TKey : class where TValue : class - { - private readonly Dictionary, TValue> items = new Dictionary, TValue>(); - private readonly object _lock = new object(); - + { + private readonly Dictionary, TValue> items = new Dictionary, TValue>(); + private readonly object _lock = new object(); + private sealed class KeyComparer : IEqualityComparer> { public bool Equals(WeakReference x, WeakReference y) @@ -17,11 +17,11 @@ namespace System.Runtime.CompilerServices public int GetHashCode(WeakReference obj) => obj.TryGetTarget(out var key) ? key.GetHashCode() : 0; - } - - private static WeakReference WeakRef(TKey key) - => new WeakReference(key); - + } + + private static WeakReference WeakRef(TKey key) + => new WeakReference(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()); - + } + + public TValue GetOrCreateValue(TKey key) + => GetValue(key, k => Activator.CreateInstance()); + 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 - } - } -} + } + } +} diff --git a/Net3-Proxy/Net3-Proxy.csproj b/Net3-Proxy/Net3-Proxy.csproj index 7d2de56c..40e0a7c0 100644 --- a/Net3-Proxy/Net3-Proxy.csproj +++ b/Net3-Proxy/Net3-Proxy.csproj @@ -1,66 +1,15 @@ - - - + + - Debug - AnyCPU - {642F52DA-90F9-40E3-8784-6964F36752FB} - Library - Properties + net35 Net3_Proxy - Net3-Proxy - v3.5 - 512 - true - - - true - portable - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - portable - true - bin\Release\ - TRACE - prompt - 4 + false + - - - - - - - - - - - - - - - - - - - - - - - - - - 0.3.1 - - - 1.0.1 - + + - - \ No newline at end of file + + diff --git a/README.md b/README.md index 4e4bbb17..21998ae1 100644 --- a/README.md +++ b/README.md @@ -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/) diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index c1756399..00000000 --- a/appveyor.yml +++ /dev/null @@ -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):x-oauth-basic@github.com`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