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