diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d2da10f66..00aa44c22 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,4 +1,5 @@
name: Build MelonLoader
+run-name: ${{ vars.DEVVERSION }}${{ github.event_name != 'workflow_dispatch' && format('-ci.{0}', github.run_number) || '' }} | ${{ github.event_name != 'workflow_dispatch' && (github.event.head_commit.message || format('`[PR]` {0}', github.event.pull_request.title)) || 'Manual Build' }}
on:
push:
@@ -8,35 +9,47 @@ on:
workflow_dispatch:
jobs:
- build_core_debug:
+ build_core:
+ name: Build Managed Binaries
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- - name: setup-msbuild
- uses: microsoft/setup-msbuild@v2
- - name: Build Melonloader Core
- shell: cmd
- run: msbuild /restore /p:Platform="Windows - x64" # Platform is actually irrelevant for core, it's compiled as AnyCPU either way
- - name: Upload core artifact
+ - name: Setup dotnet
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+
+ - name: Restore Dependencies
+ run: dotnet restore
+
+ - name: Build Melonloader Core Debug
+ run: dotnet build --no-restore -c Debug -p:Platform="Windows - x64" -p:Version="${{ vars.DEVVERSION }}${{ github.event_name != 'workflow_dispatch' && format('.{0}', github.run_number) || '' }}" # Platform is actually irrelevant for core, it's compiled as AnyCPU either way
+
+ - name: Upload Debug Core Artifact
uses: actions/upload-artifact@v4
with:
name: MLCoreDebug
path: Output/Debug/MelonLoader/
- build_core_release:
- runs-on: windows-latest
- steps:
- - uses: actions/checkout@v4
- - name: setup-msbuild
- uses: microsoft/setup-msbuild@v2
- - name: Build Melonloader Core
- shell: cmd
- run: msbuild /restore /p:Configuration=Release /p:Platform="Windows - x64"
- - name: Upload core artifact
+
+ - name: Build MelonLoader Core Release
+ run: dotnet build --no-restore -c Release -p:Platform="Windows - x64" -p:Version="${{ vars.DEVVERSION }}${{ github.event_name != 'workflow_dispatch' && format('.{0}', github.run_number) || '' }}"
+
+ - name: Upload Release Core Artifact
uses: actions/upload-artifact@v4
with:
name: MLCoreRelease
path: Output/Release/MelonLoader/
+
+ - name: Pack NuGet Package
+ run: dotnet pack --no-build -c Release -p:Version="${{ vars.DEVVERSION }}${{ github.event_name != 'workflow_dispatch' && format('-ci.{0}', github.run_number) || '' }}"
+
+ - name: Upload NuGet Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: MelonLoader.NuGet
+ path: Output/Release/MelonLoader/LavaGang.MelonLoader.${{ vars.DEVVERSION }}${{ github.event_name != 'workflow_dispatch' && format('-ci.{0}', github.run_number) || '' }}.nupkg
build_rust_windows:
+ name: Build Native Binaries (Windows)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
@@ -109,6 +122,7 @@ jobs:
name: MLBootstrapX64-Windows-Debug
path: target/x86_64-pc-windows-msvc/debug/Bootstrap.dll
build_rust_linux:
+ name: Build Native Binaries (Linux)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -150,279 +164,250 @@ jobs:
with:
name: MLBootstrapX64-Linux-Debug
path: target/x86_64-unknown-linux-gnu/debug/libBootstrap.so
- finalize_x64_debug_zip_windows:
- runs-on: windows-latest
- needs: [build_core_debug, build_rust_windows]
+
+ finalize_windows:
+ name: Finalize Windows Artifacts
+ runs-on: ubuntu-22.04
+ needs: [build_core, build_rust_windows]
steps:
- uses: actions/checkout@v4
- - name: Download core artifact
+ - name: Download Debug Managed Artifact
uses: actions/download-artifact@v4
with:
name: MLCoreDebug
- path: Output/Debug/x64/MelonLoader/
- - name: Download proxy x64
+ path: Output/Debug/Managed/
+ - name: Download Debug Proxy x64 Artifact
uses: actions/download-artifact@v4
with:
name: MLProxyX64-Windows-Debug
path: Output/Debug/x64/
- - name: Download bootstrap x64
+ - name: Download Debug Bootstrap x64 Artifact
uses: actions/download-artifact@v4
with:
name: MLBootstrapX64-Windows-Debug
path: Output/Debug/x64/MelonLoader/Dependencies/
- - name: Package x64 zip
- shell: cmd
+ - name: Package Debug x64 Artifact
run: |
echo Copying Managed Libs...
- mkdir Output\Debug\x64\MelonLoader\Dependencies\Mono
- xcopy BaseLibs\Mono Output\Debug\x64\MelonLoader\Dependencies\Mono\ /E /H /Y
- xcopy BaseLibs\net35 Output\Debug\x64\MelonLoader\net35\ /E /H /Y
- xcopy BaseLibs\net6 Output\Debug\x64\MelonLoader\net6\ /E /H /Y
- echo.
+ mkdir -p Output/Debug/x64/MelonLoader/Dependencies/Mono
+ cp -r Output/Debug/Managed/* Output/Debug/x64/MelonLoader/
+ cp -r BaseLibs/Mono Output/Debug/x64/MelonLoader/Dependencies/
+ cp -r BaseLibs/net35 Output/Debug/x64/MelonLoader/
+ cp -r BaseLibs/net6 Output/Debug/x64/MelonLoader/
+ mkdir -p Output/Debug/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ cp -r BaseLibs/NetStandardPatches Output/Debug/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ echo
echo Copying Dobby x64...
- xcopy BaseLibs\dobby_x64.dll Output\Debug\x64\MelonLoader\Dependencies\dobby.dll*
- echo.
+ cp BaseLibs/dobby_x64.dll Output/Debug/x64/MelonLoader/Dependencies/dobby.dll
+ echo
echo Copying documentation files...
- copy NOTICE.txt Output\Debug\x64
- mkdir Output\Debug\x64\MelonLoader\Documentation
- copy CHANGELOG.md Output\Debug\x64\MelonLoader\Documentation\
- copy LICENSE.md Output\Debug\x64\MelonLoader\Documentation\
- copy NOTICE.txt Output\Debug\x64\MelonLoader\Documentation\
- copy README.md Output\Debug\x64\MelonLoader\Documentation\
- del Output\Debug\x64\MelonLoader\net6\MelonStartScreen.dll
- del Output\Debug\x64\MelonLoader\net6\MelonStartScreen.deps.json
+ mkdir -p Output/Debug/x64/MelonLoader/Documentation
+ cp CHANGELOG.md Output/Debug/x64/MelonLoader/Documentation/
+ cp LICENSE.md Output/Debug/x64/MelonLoader/Documentation/
+ cp NOTICE.txt Output/Debug/x64/MelonLoader/Documentation/
+ cp README.md Output/Debug/x64/MelonLoader/Documentation/
- uses: actions/upload-artifact@v4
- name: Upload Zip | Windows - x64
+ name: Upload Zip | Windows - Debug - x64
with:
name: MelonLoader.Windows.x64.CI.Debug
path: ./Output/Debug/x64/*
- finalize_x86_debug_zip_windows:
- runs-on: windows-latest
- needs: [build_core_debug, build_rust_windows]
- steps:
- - uses: actions/checkout@v4
- - name: Download core artifact
- uses: actions/download-artifact@v4
- with:
- name: MLCoreDebug
- path: Output/Debug/x86/MelonLoader/
- - name: Download proxy x86
- uses: actions/download-artifact@v4
- with:
- name: MLProxyX86-Windows-Debug
- path: Output/Debug/x86/
- - name: Download bootstrap x86
- uses: actions/download-artifact@v4
- with:
- name: MLBootstrapX86-Windows-Debug
- path: Output/Debug/x86/MelonLoader/Dependencies/
- - name: Package x86 zip
- shell: cmd
- run: |
- echo Copying Managed Libs...
- mkdir Output\Debug\x86\MelonLoader\Dependencies\Mono
- xcopy BaseLibs\Mono Output\Debug\x86\MelonLoader\Dependencies\Mono\ /E /H /Y
- xcopy BaseLibs\net35 Output\Debug\x86\MelonLoader\net35\ /E /H /Y
- xcopy BaseLibs\net6 Output\Debug\x86\MelonLoader\net6\ /E /H /Y
- echo.
- echo Copying Dobby x86...
- xcopy BaseLibs\dobby_x86.dll Output\Debug\x86\MelonLoader\Dependencies\dobby.dll*
- echo.
- echo Copying documentation files...
- copy NOTICE.txt Output\Debug\x86
- mkdir Output\Debug\x86\MelonLoader\Documentation
- copy CHANGELOG.md Output\Debug\x86\MelonLoader\Documentation\
- copy LICENSE.md Output\Debug\x86\MelonLoader\Documentation\
- copy NOTICE.txt Output\Debug\x86\MelonLoader\Documentation\
- copy README.md Output\Debug\x86\MelonLoader\Documentation\
- del Output\Debug\x86\MelonLoader\net6\MelonStartScreen.dll
- del Output\Debug\x86\MelonLoader\net6\MelonStartScreen.deps.json
- - uses: actions/upload-artifact@v4
- name: Upload Zip | Windows - x86
- with:
- name: MelonLoader.Windows.x86.CI.Debug
- path: ./Output/Debug/x86/*
- finalize_x64_release_zip_windows:
- runs-on: windows-latest
- needs: [build_core_release, build_rust_windows]
- steps:
- - uses: actions/checkout@v4
- - name: Download core artifact
+
+ - name: Download Release Managed Artifact
uses: actions/download-artifact@v4
with:
name: MLCoreRelease
- path: Output/Release/x64/MelonLoader/
- - name: Download proxy x64
+ path: Output/Release/Managed/
+ - name: Download Release Proxy x64 Artifact
uses: actions/download-artifact@v4
with:
name: MLProxyX64-Windows-Release
path: Output/Release/x64/
- - name: Download bootstrap x64
+ - name: Download Debug Bootstrap x64 Artifact
uses: actions/download-artifact@v4
with:
name: MLBootstrapX64-Windows-Release
path: Output/Release/x64/MelonLoader/Dependencies/
- - name: Package x64 zip
- shell: cmd
+ - name: Package Release x64 Artifact
run: |
echo Copying Managed Libs...
- mkdir Output\Release\x64\MelonLoader\Dependencies\Mono
- xcopy BaseLibs\Mono Output\Release\x64\MelonLoader\Dependencies\Mono\ /E /H /Y
- xcopy BaseLibs\net35 Output\Release\x64\MelonLoader\net35\ /E /H /Y
- xcopy BaseLibs\net6 Output\Release\x64\MelonLoader\net6\ /E /H /Y
- echo.
+ mkdir -p Output/Release/x64/MelonLoader/Dependencies/Mono
+ cp -r Output/Release/Managed/* Output/Release/x64/MelonLoader/
+ cp -r BaseLibs/Mono Output/Release/x64/MelonLoader/Dependencies/
+ cp -r BaseLibs/net35 Output/Release/x64/MelonLoader/
+ cp -r BaseLibs/net6 Output/Release/x64/MelonLoader/
+ mkdir -p Output/Release/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ cp -r BaseLibs/NetStandardPatches Output/Release/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ echo
echo Copying Dobby x64...
- xcopy BaseLibs\dobby_x64.dll Output\Release\x64\MelonLoader\Dependencies\dobby.dll*
- echo.
+ cp BaseLibs/dobby_x64.dll Output/Release/x64/MelonLoader/Dependencies/dobby.dll
+ echo
echo Copying documentation files...
- copy NOTICE.txt Output\Release\x64
- mkdir Output\Release\x64\MelonLoader\Documentation
- copy CHANGELOG.md Output\Release\x64\MelonLoader\Documentation\
- copy LICENSE.md Output\Release\x64\MelonLoader\Documentation\
- copy NOTICE.txt Output\Release\x64\MelonLoader\Documentation\
- copy README.md Output\Release\x64\MelonLoader\Documentation\
- del Output\Release\x64\MelonLoader\net6\MelonStartScreen.dll
- del Output\Release\x64\MelonLoader\net6\MelonStartScreen.deps.json
+ mkdir -p Output/Release/x64/MelonLoader/Documentation
+ cp CHANGELOG.md Output/Release/x64/MelonLoader/Documentation/
+ cp LICENSE.md Output/Release/x64/MelonLoader/Documentation/
+ cp NOTICE.txt Output/Release/x64/MelonLoader/Documentation/
+ cp README.md Output/Release/x64/MelonLoader/Documentation/
- uses: actions/upload-artifact@v4
- name: Upload Zip | Windows - x64
+ name: Upload Zip | Windows - Release - x64
with:
name: MelonLoader.Windows.x64.CI.Release
path: ./Output/Release/x64/*
- finalize_x86_release_zip_windows:
- runs-on: windows-latest
- needs: [build_core_release, build_rust_windows]
- steps:
- - uses: actions/checkout@v4
- - name: Download core artifact
+
+ - name: Download Debug Proxy x86 Artifact
uses: actions/download-artifact@v4
with:
- name: MLCoreRelease
- path: Output/Release/x86/MelonLoader/
- - name: Download proxy x86
+ name: MLProxyX86-Windows-Debug
+ path: Output/Debug/x86/
+ - name: Download Debug Bootstrap x86 Artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: MLBootstrapX86-Windows-Debug
+ path: Output/Debug/x86/MelonLoader/Dependencies/
+ - name: Package Debug x86 Artifact
+ run: |
+ echo Copying Managed Libs...
+ mkdir -p Output/Debug/x86/MelonLoader/Dependencies/Mono
+ cp -r Output/Debug/Managed/* Output/Debug/x86/MelonLoader/
+ cp -r BaseLibs/Mono Output/Debug/x86/MelonLoader/Dependencies/
+ cp -r BaseLibs/net35 Output/Debug/x86/MelonLoader/
+ cp -r BaseLibs/net6 Output/Debug/x86/MelonLoader/
+ mkdir -p Output/Debug/x86/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ cp -r BaseLibs/NetStandardPatches Output/Debug/x86/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ echo
+ echo Copying Dobby x86...
+ cp BaseLibs/dobby_x86.dll Output/Debug/x86/MelonLoader/Dependencies/dobby.dll
+ echo
+ echo Copying documentation files...
+ mkdir -p Output/Debug/x86/MelonLoader/Documentation
+ cp CHANGELOG.md Output/Debug/x86/MelonLoader/Documentation/
+ cp LICENSE.md Output/Debug/x86/MelonLoader/Documentation/
+ cp NOTICE.txt Output/Debug/x86/MelonLoader/Documentation/
+ cp README.md Output/Debug/x86/MelonLoader/Documentation/
+ - uses: actions/upload-artifact@v4
+ name: Upload Zip | Windows - Debug - x86
+ with:
+ name: MelonLoader.Windows.x86.CI.Debug
+ path: ./Output/Debug/x86/*
+
+ - name: Download Release Proxy x86 Artifact
uses: actions/download-artifact@v4
with:
name: MLProxyX86-Windows-Release
path: Output/Release/x86/
- - name: Download bootstrap x86
+ - name: Download Release Bootstrap x86 Artifact
uses: actions/download-artifact@v4
with:
name: MLBootstrapX86-Windows-Release
path: Output/Release/x86/MelonLoader/Dependencies/
- - name: Package x86 zip
- shell: cmd
+ - name: Package Release x86 Artifact
run: |
echo Copying Managed Libs...
- mkdir Output\Release\x86\MelonLoader\Dependencies\Mono
- xcopy BaseLibs\Mono Output\Release\x86\MelonLoader\Dependencies\Mono\ /E /H /Y
- xcopy BaseLibs\net35 Output\Release\x86\MelonLoader\net35\ /E /H /Y
- xcopy BaseLibs\net6 Output\Release\x86\MelonLoader\net6\ /E /H /Y
- echo.
+ mkdir -p Output/Release/x86/MelonLoader/Dependencies/Mono
+ cp -r Output/Release/Managed/* Output/Release/x86/MelonLoader/
+ cp -r BaseLibs/Mono Output/Release/x86/MelonLoader/Dependencies/
+ cp -r BaseLibs/net35 Output/Release/x86/MelonLoader/
+ cp -r BaseLibs/net6 Output/Release/x86/MelonLoader/
+ mkdir -p Output/Release/x86/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ cp -r BaseLibs/NetStandardPatches Output/Release/x86/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ echo
echo Copying Dobby x86...
- xcopy BaseLibs\dobby_x86.dll Output\Release\x86\MelonLoader\Dependencies\dobby.dll*
- echo.
+ cp BaseLibs/dobby_x86.dll Output/Release/x86/MelonLoader/Dependencies/dobby.dll
+ echo
echo Copying documentation files...
- copy NOTICE.txt Output\Release\x86
- mkdir Output\Release\x86\MelonLoader\Documentation
- copy CHANGELOG.md Output\Release\x86\MelonLoader\Documentation\
- copy LICENSE.md Output\Release\x86\MelonLoader\Documentation\
- copy NOTICE.txt Output\Release\x86\MelonLoader\Documentation\
- copy README.md Output\Release\x86\MelonLoader\Documentation\
- del Output\Release\x86\MelonLoader\net6\MelonStartScreen.dll
- del Output\Release\x86\MelonLoader\net6\MelonStartScreen.deps.json
+ mkdir -p Output/Release/x86/MelonLoader/Documentation
+ cp CHANGELOG.md Output/Release/x86/MelonLoader/Documentation/
+ cp LICENSE.md Output/Release/x86/MelonLoader/Documentation/
+ cp NOTICE.txt Output/Release/x86/MelonLoader/Documentation/
+ cp README.md Output/Release/x86/MelonLoader/Documentation/
- uses: actions/upload-artifact@v4
- name: Upload Zip | Windows - x86
+ name: Upload Zip | Windows - Release - x86
with:
name: MelonLoader.Windows.x86.CI.Release
path: ./Output/Release/x86/*
- finalize_x64_debug_zip_linux:
- runs-on: windows-latest
- needs: [build_core_debug, build_rust_linux]
+
+ finalize_linux:
+ name: Finalize Linux Artifacts
+ runs-on: ubuntu-22.04
+ needs: [build_core, build_rust_linux]
steps:
- uses: actions/checkout@v4
- - name: Download core artifact
+ - name: Download Debug Managed Artifact
uses: actions/download-artifact@v4
with:
name: MLCoreDebug
path: Output/Debug/x64/MelonLoader/
- - name: Download proxy x64
+ - name: Download Debug Proxy Artifact
uses: actions/download-artifact@v4
with:
name: MLProxyX64-Linux-Debug
path: Output/Debug/x64/
- - name: Download bootstrap x64
+ - name: Download Debug Bootstrap Artifact
uses: actions/download-artifact@v4
with:
name: MLBootstrapX64-Linux-Debug
path: Output/Debug/x64/MelonLoader/Dependencies/
- - name: Package x64 zip
- shell: cmd
+ - name: Package Debug Zip
run: |
echo Copying Managed Libs...
- mkdir Output\Debug\x64\MelonLoader\Dependencies\Mono
- xcopy BaseLibs\Mono Output\Debug\x64\MelonLoader\Dependencies\Mono\ /E /H /Y
- xcopy BaseLibs\net35 Output\Debug\x64\MelonLoader\net35\ /E /H /Y
- xcopy BaseLibs\net6 Output\Debug\x64\MelonLoader\net6\ /E /H /Y
- echo.
+ mkdir -p Output/Debug/x64/MelonLoader/Dependencies/Mono
+ cp -r BaseLibs/Mono Output/Debug/x64/MelonLoader/Dependencies/
+ cp -r BaseLibs/net35 Output/Debug/x64/MelonLoader/
+ cp -r BaseLibs/net6 Output/Debug/x64/MelonLoader/
+ mkdir -p Output/Debug/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ cp -r BaseLibs/NetStandardPatches Output/Debug/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ echo
echo Copying documentation files...
- copy NOTICE.txt Output\Debug\x64
- mkdir Output\Debug\x64\MelonLoader\Documentation
- copy CHANGELOG.md Output\Debug\x64\MelonLoader\Documentation\
- copy LICENSE.md Output\Debug\x64\MelonLoader\Documentation\
- copy NOTICE.txt Output\Debug\x64\MelonLoader\Documentation\
- copy README.md Output\Debug\x64\MelonLoader\Documentation\
- del Output\Debug\x64\MelonLoader\net6\MelonStartScreen.dll
- del Output\Debug\x64\MelonLoader\net6\MelonStartScreen.deps.json
+ mkdir -p Output/Debug/x64/MelonLoader/Documentation
+ cp CHANGELOG.md Output/Debug/x64/MelonLoader/Documentation/
+ cp LICENSE.md Output/Debug/x64/MelonLoader/Documentation/
+ cp NOTICE.txt Output/Debug/x64/MelonLoader/Documentation/
+ cp README.md Output/Debug/x64/MelonLoader/Documentation/
- uses: actions/upload-artifact@v4
- name: Upload Zip | Linux - x64
+ name: Upload Zip | Linux - Debug - x64
with:
name: MelonLoader.Linux.x64.CI.Debug
path: ./Output/Debug/x64/*
- finalize_x64_release_zip_linux:
- runs-on: windows-latest
- needs: [build_core_release, build_rust_linux]
- steps:
- - uses: actions/checkout@v4
- - name: Download core artifact
+ - name: Download Release Managed Artifact
uses: actions/download-artifact@v4
with:
name: MLCoreRelease
path: Output/Release/x64/MelonLoader/
- - name: Download proxy x64
+ - name: Download Release Proxy Artifact
uses: actions/download-artifact@v4
with:
name: MLProxyX64-Linux-Release
path: Output/Release/x64/
- - name: Download bootstrap x64
+ - name: Download Release Bootstrap Artifact
uses: actions/download-artifact@v4
with:
name: MLBootstrapX64-Linux-Release
path: Output/Release/x64/MelonLoader/Dependencies/
- - name: Package x64 zip
- shell: cmd
+ - name: Package Release Zip
run: |
echo Copying Managed Libs...
- mkdir Output\Release\x64\MelonLoader\Dependencies\Mono
- xcopy BaseLibs\Mono Output\Release\x64\MelonLoader\Dependencies\Mono\ /E /H /Y
- xcopy BaseLibs\net35 Output\Release\x64\MelonLoader\net35\ /E /H /Y
- xcopy BaseLibs\net6 Output\Release\x64\MelonLoader\net6\ /E /H /Y
- echo.
+ mkdir -p Output/Release/x64/MelonLoader/Dependencies/Mono
+ cp -r BaseLibs/Mono Output/Release/x64/MelonLoader/Dependencies/
+ cp -r BaseLibs/net35 Output/Release/x64/MelonLoader/
+ cp -r BaseLibs/net6 Output/Release/x64/MelonLoader/
+ mkdir -p Output/Release/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ cp -r BaseLibs/NetStandardPatches Output/Release/x64/MelonLoader/Dependencies/SupportModules/NetStandardPatches
+ echo
echo Copying documentation files...
- copy NOTICE.txt Output\Release\x64
- mkdir Output\Release\x64\MelonLoader\Documentation
- copy CHANGELOG.md Output\Release\x64\MelonLoader\Documentation\
- copy LICENSE.md Output\Release\x64\MelonLoader\Documentation\
- copy NOTICE.txt Output\Release\x64\MelonLoader\Documentation\
- copy README.md Output\Release\x64\MelonLoader\Documentation\
- del Output\Release\x64\MelonLoader\net6\MelonStartScreen.dll
- del Output\Release\x64\MelonLoader\net6\MelonStartScreen.deps.json
+ mkdir -p Output/Release/x64/MelonLoader/Documentation
+ cp CHANGELOG.md Output/Release/x64/MelonLoader/Documentation/
+ cp LICENSE.md Output/Release/x64/MelonLoader/Documentation/
+ cp NOTICE.txt Output/Release/x64/MelonLoader/Documentation/
+ cp README.md Output/Release/x64/MelonLoader/Documentation/
- uses: actions/upload-artifact@v4
- name: Upload Zip | Linux - x64
+ name: Upload Zip | Linux - Release - x64
with:
name: MelonLoader.Linux.x64.CI.Release
path: ./Output/Release/x64/*
+
cleanup_artifacts:
- runs-on: windows-latest
- needs: [finalize_x86_debug_zip_windows, finalize_x64_debug_zip_windows, finalize_x86_release_zip_windows, finalize_x64_release_zip_windows, finalize_x64_debug_zip_linux, finalize_x64_release_zip_linux]
+ name: Cleanup Artifacts
+ runs-on: ubuntu-22.04
+ needs: [finalize_windows, finalize_linux]
steps:
- uses: GeekyEggo/delete-artifact@v5.0.0
with:
@@ -440,4 +425,5 @@ jobs:
MLProxyX64-Windows-Release
MLBootstrapX64-Windows-Release
MLProxyX64-Linux-Release
- MLBootstrapX64-Linux-Release
\ No newline at end of file
+ MLBootstrapX64-Linux-Release
+
\ No newline at end of file
diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml
deleted file mode 100644
index 78042b0af..000000000
--- a/.github/workflows/nuget.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: Build NuGet Package
-
-on:
- push:
- branches: [ master, alpha-development, v0.6.0-rewrite ]
- pull_request:
- branches: [ master, alpha-development, v0.6.0-rewrite ]
- workflow_dispatch:
-
-jobs:
- build_nuget_package:
- runs-on: windows-latest
- steps:
- - uses: actions/checkout@v4
- - name: Setup .NET
- uses: actions/setup-dotnet@v4.0.1
- with:
- dotnet-version: 7.0.x
- - name: .NET Pack
- run: dotnet pack -c Release
- working-directory: ./MelonLoader/
- - name: Upload artifact
- uses: actions/upload-artifact@v4
- with:
- name: MelonLoaderNuGetPackage
- path: MelonLoader/Output/Release/MelonLoader/LavaGang.MelonLoader.0.6.6.nupkg
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Preload/Resources/System.Core.dll b/BaseLibs/NetStandardPatches/System.Core.dll
similarity index 100%
rename from Dependencies/SupportModules/Preload/Resources/System.Core.dll
rename to BaseLibs/NetStandardPatches/System.Core.dll
diff --git a/Dependencies/SupportModules/Preload/Resources/System.Drawing.dll b/BaseLibs/NetStandardPatches/System.Drawing.dll
similarity index 100%
rename from Dependencies/SupportModules/Preload/Resources/System.Drawing.dll
rename to BaseLibs/NetStandardPatches/System.Drawing.dll
diff --git a/Dependencies/SupportModules/Preload/Resources/System.dll b/BaseLibs/NetStandardPatches/System.dll
similarity index 100%
rename from Dependencies/SupportModules/Preload/Resources/System.dll
rename to BaseLibs/NetStandardPatches/System.dll
diff --git a/CHANGELOG.md b/CHANGELOG.md
index da8e3655b..39a24557a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,25 +41,36 @@
### v0.6.6
1. Updated Il2CppInterop to 1.4.6-ci.579
-2. Implemented a RegisterTypeInIl2CppWithInterfaces attribute
-3. Implemented Recursive Melon Folders with extended UserLib Resolving
-4. Reimplemented NetFramework Variant of Cpp2IL as fallback
-5. Standardized Assembly Searching and Resolving to work on both Mono and Il2Cpp Games
-6. Temporarily removed Start Screen for being broken in most cases
-7. Modified Command-Line Argument Logging to show Internal Arguments Only
-8. Added UserLibs folders to Native Library Search Directories
-9. Moved `dobby.dll` to `MelonLoader\Dependencies`
-10. Moved Assembly Resolver Related Classes to `MelonLoader.Resolver` Namespace
-11. Moved `MonoLibrary` class to `MelonLoader.Utils` Namespace
-12. Removed Useless TODO Warning from Il2CppAssemblyGenerator
-13. Removed EOS Compatibility Layer for being Unneeded
-14. Fixed Regression with LemonMD5, LemonSHA256, and LemonSHA512
-15. Fixed an issue with older Cpp2IL versions causing a download failure
-16. Fixed an issue with Il2CppInterop not properly logging Trampoline Exceptions
-17. Fixed an issue with Il2Cpp Class Injection Attributes causing exceptions to be thrown on Mono games
-18. Fixed an issue with the Bootstrap not reading `--melonloader.basedir` correctly
-19. Fixed an issue with Loading `dobby.dll` in some rare cases
-20. Fixed an issue with Compatibility Layers getting Garbage Collected while still in use
+2. Reverted AssetTools.NET to 3.0.0-preview3
+3. Implemented a RegisterTypeInIl2CppWithInterfaces attribute
+4. Implemented Recursive Melon Folders with extended UserLib Resolving
+5. Implemented Melon Preprocessor to prevent Loading Duplicates
+6. Reimplemented NetFramework Variant of Cpp2IL as fallback
+7. Standardized Assembly Searching and Resolving to work on both Mono and Il2Cpp Games
+8. Temporarily removed Start Screen for being broken in most cases
+9. Modified Command-Line Argument Logging to show Internal Arguments Only
+10. Reworked Il2CppICallInjector to use Il2CppInterop's Native to Manage trampoline generation
+11. Reworked Launch Option Parsing to ignore First Element
+12. Added UserLibs folders to Native Library Search Directories
+13. Moved `dobby.dll` to `MelonLoader\Dependencies`
+14. Moved Assembly Resolver Related Classes to `MelonLoader.Resolver` Namespace
+15. Moved `MonoLibrary` class to `MelonLoader.Utils` Namespace
+16. Moved dobby scan to check Game Directory after Base Directory
+17. Removed Useless TODO Warning from Il2CppAssemblyGenerator
+18. Removed EOS Compatibility Layer for being Unneeded
+19. Fixed Regression with LemonMD5, LemonSHA256, and LemonSHA512
+20. Fixed an issue with older Cpp2IL versions causing a download failure
+21. Fixed an issue with Il2CppInterop not properly logging Trampoline Exceptions
+22. Fixed an issue with Il2Cpp Class Injection Attributes causing exceptions to be thrown on Mono games
+23. Fixed an issue with the Bootstrap not reading `--melonloader.basedir` correctly
+24. Fixed an issue with Loading `dobby.dll` in some rare cases
+25. Fixed an issue with Compatibility Layers getting Garbage Collected while still in use
+26. Fixed an issue with Linux Proxy failing to find dobby
+27. Fixed an issue with trying to load Managed Assemblies from Native Libraries inside UserLibs
+28. Fixed an issue with Compatibility Layer loading not validating Names Checked
+29. Fixed an issue with Type Load spamming errors when failing to resolve a Dependency
+30. Fixed an issue with Launch Option Parsing ignoring Argument Values
+31. Fixed a race condition crash with Multi-Launching a Game and the Logger trying to delete old files
---
diff --git a/Dependencies/CompatibilityLayers/Demeo/Demeo.csproj b/Dependencies/CompatibilityLayers/Demeo/Demeo.csproj
index 8ba1116ea..a3c7b7a95 100644
--- a/Dependencies/CompatibilityLayers/Demeo/Demeo.csproj
+++ b/Dependencies/CompatibilityLayers/Demeo/Demeo.csproj
@@ -2,9 +2,7 @@
MelonLoader.CompatibilityLayers
net472
- Latest
true
- false
false
$(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\CompatibilityLayers\
true
@@ -12,8 +10,6 @@
-
- Runtime
-
+
\ No newline at end of file
diff --git a/Dependencies/CompatibilityLayers/Demeo/Module.cs b/Dependencies/CompatibilityLayers/Demeo/Module.cs
index 9ec9d47e5..8bd856fde 100644
--- a/Dependencies/CompatibilityLayers/Demeo/Module.cs
+++ b/Dependencies/CompatibilityLayers/Demeo/Module.cs
@@ -4,6 +4,8 @@
using System.Reflection;
using MelonLoader.Modules;
+[assembly: MelonLoader.PatchShield]
+
namespace MelonLoader.CompatibilityLayers
{
internal class Demeo_Module : MelonModule
diff --git a/Dependencies/CompatibilityLayers/Demeo/Properties/AssemblyInfo.cs b/Dependencies/CompatibilityLayers/Demeo/Properties/AssemblyInfo.cs
deleted file mode 100644
index 81808f72e..000000000
--- a/Dependencies/CompatibilityLayers/Demeo/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("FEAA0159-5871-4419-9827-3CF5CAD69A53")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
-[assembly: MelonLoader.PatchShield]
\ No newline at end of file
diff --git a/Dependencies/CompatibilityLayers/IPA/IPA.csproj b/Dependencies/CompatibilityLayers/IPA/IPA.csproj
index cc4d68bae..73734cb79 100644
--- a/Dependencies/CompatibilityLayers/IPA/IPA.csproj
+++ b/Dependencies/CompatibilityLayers/IPA/IPA.csproj
@@ -2,9 +2,7 @@
MelonLoader.CompatibilityLayers
net35
- Latest
true
- false
false
$(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\CompatibilityLayers\
true
diff --git a/Dependencies/CompatibilityLayers/IPA/Module.cs b/Dependencies/CompatibilityLayers/IPA/Module.cs
index 018263c95..87cb99a13 100644
--- a/Dependencies/CompatibilityLayers/IPA/Module.cs
+++ b/Dependencies/CompatibilityLayers/IPA/Module.cs
@@ -7,6 +7,8 @@
using MelonLoader.Modules;
using MelonLoader.Resolver;
+[assembly: MelonLoader.PatchShield]
+
namespace MelonLoader.CompatibilityLayers
{
internal class IPA_Module : MelonModule
diff --git a/Dependencies/CompatibilityLayers/IPA/Properties/AssemblyInfo.cs b/Dependencies/CompatibilityLayers/IPA/Properties/AssemblyInfo.cs
deleted file mode 100644
index 0f2b1903f..000000000
--- a/Dependencies/CompatibilityLayers/IPA/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("5100810A-9842-4073-9658-E5841FDF9D73")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
-[assembly: MelonLoader.PatchShield]
\ No newline at end of file
diff --git a/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Module.cs b/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Module.cs
index 0551542a4..80c8d1ce0 100644
--- a/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Module.cs
+++ b/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Module.cs
@@ -6,6 +6,8 @@
using ModHelper;
using MelonLoader.Resolver;
+[assembly: MelonLoader.PatchShield]
+
namespace MelonLoader.CompatibilityLayers
{
internal class Muse_Dash_Mono_Module : MelonModule
diff --git a/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Muse_Dash_Mono.csproj b/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Muse_Dash_Mono.csproj
index cc4d68bae..73734cb79 100644
--- a/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Muse_Dash_Mono.csproj
+++ b/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Muse_Dash_Mono.csproj
@@ -2,9 +2,7 @@
MelonLoader.CompatibilityLayers
net35
- Latest
true
- false
false
$(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\CompatibilityLayers\
true
diff --git a/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Properties/AssemblyInfo.cs b/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Properties/AssemblyInfo.cs
deleted file mode 100644
index 7982318b0..000000000
--- a/Dependencies/CompatibilityLayers/Muse_Dash_Mono/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("C268E68B-3DF1-4EE3-A49F-750A8F55B799")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
-[assembly: MelonLoader.PatchShield]
\ No newline at end of file
diff --git a/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Module.cs b/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Module.cs
index 791f9c824..a71f73b76 100644
--- a/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Module.cs
+++ b/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Module.cs
@@ -1,6 +1,8 @@
using MelonLoader.Modules;
using System.Collections.Generic;
+[assembly: MelonLoader.PatchShield]
+
namespace MelonLoader.CompatibilityLayers
{
internal class SLZ_Module : MelonModule
diff --git a/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Properties/AssemblyInfo.cs b/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Properties/AssemblyInfo.cs
deleted file mode 100644
index 81808f72e..000000000
--- a/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("FEAA0159-5871-4419-9827-3CF5CAD69A53")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
-[assembly: MelonLoader.PatchShield]
\ No newline at end of file
diff --git a/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Stress_Level_Zero_Il2Cpp.csproj b/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Stress_Level_Zero_Il2Cpp.csproj
index 938439701..c2eab15ea 100644
--- a/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Stress_Level_Zero_Il2Cpp.csproj
+++ b/Dependencies/CompatibilityLayers/Stress_Level_Zero_Il2Cpp/Stress_Level_Zero_Il2Cpp.csproj
@@ -2,9 +2,7 @@
MelonLoader.CompatibilityLayers
net472
- Latest
true
- false
false
$(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\CompatibilityLayers\
true
@@ -17,9 +15,9 @@
-
- false
- false
-
+
+ false
+ false
+
\ No newline at end of file
diff --git a/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj b/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj
index 09f20a55d..b7c195233 100644
--- a/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj
+++ b/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj
@@ -2,9 +2,7 @@
MelonLoader.Il2CppAssemblyGenerator
net6
- Latest
true
- false
true
false
$(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\Il2CppAssemblyGenerator\
@@ -18,7 +16,7 @@
-
+
\ No newline at end of file
diff --git a/Dependencies/Il2CppAssemblyGenerator/Properties/AssemblyInfo.cs b/Dependencies/Il2CppAssemblyGenerator/Properties/AssemblyInfo.cs
deleted file mode 100644
index e98f6337e..000000000
--- a/Dependencies/Il2CppAssemblyGenerator/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("0E4C9125-D149-441D-B7B6-16D9D8CF1DA5")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
\ No newline at end of file
diff --git a/Dependencies/MelonStartScreen/MelonStartScreen.csproj b/Dependencies/MelonStartScreen/MelonStartScreen.csproj
index e6ca3c748..587ad73ee 100644
--- a/Dependencies/MelonStartScreen/MelonStartScreen.csproj
+++ b/Dependencies/MelonStartScreen/MelonStartScreen.csproj
@@ -1,26 +1,25 @@
-
- MelonLoader.MelonStartScreen
- net35;net6
- Latest
- true
- false
- true
- $(SolutionDir)Output\$(Configuration)\MelonLoader\
- true
- embedded
-
-
-
-
-
-
-
-
-
-
-
- Runtime
-
-
+
+ MelonLoader.MelonStartScreen
+ net35;net6
+ true
+ true
+ $(SolutionDir)Output\$(Configuration)\MelonLoader\
+ true
+ embedded
+
+
+
+
+
+
+
+
+
+
+
+ Runtime
+
+
\ No newline at end of file
diff --git a/Dependencies/MelonStartScreen/Properties/AssemblyInfo.cs b/Dependencies/MelonStartScreen/Properties/AssemblyInfo.cs
deleted file mode 100644
index efe736458..000000000
--- a/Dependencies/MelonStartScreen/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("762d7545-6f6b-441a-b040-49cc31a1713b")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj b/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj
index 53f3003ca..b661db0ff 100644
--- a/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj
+++ b/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj
@@ -2,9 +2,7 @@
MelonLoader.Support
net6
- Latest
true
- false
false
$(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\SupportModules\
true
@@ -12,15 +10,8 @@
SM_Il2Cpp
true
-
- https://nuget.bepinex.dev/v3/index.json
-
+ https://nuget.bepinex.dev/v3/index.json
-
-
-
-
-
Libs\Il2Cppmscorlib.dll
@@ -49,7 +40,7 @@
-
+
diff --git a/Dependencies/SupportModules/Il2Cpp/Main.cs b/Dependencies/SupportModules/Il2Cpp/Main.cs
index 49f65d0c1..21c3d41cc 100644
--- a/Dependencies/SupportModules/Il2Cpp/Main.cs
+++ b/Dependencies/SupportModules/Il2Cpp/Main.cs
@@ -12,6 +12,8 @@
using MelonLoader.Utils;
using System.IO;
+[assembly: MelonLoader.PatchShield]
+
#pragma warning disable CS0618 // Type or member is obsolete
namespace MelonLoader.Support
diff --git a/Dependencies/SupportModules/Il2Cpp/Properties/AssemblyInfo.cs b/Dependencies/SupportModules/Il2Cpp/Properties/AssemblyInfo.cs
deleted file mode 100644
index d64189128..000000000
--- a/Dependencies/SupportModules/Il2Cpp/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("CD98B694-D833-41B0-AF57-A6B9D024B045")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
-[assembly: MelonLoader.PatchShield]
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Mono/Main.cs b/Dependencies/SupportModules/Mono/Main.cs
index ea95dea2c..a12bce579 100644
--- a/Dependencies/SupportModules/Mono/Main.cs
+++ b/Dependencies/SupportModules/Mono/Main.cs
@@ -3,6 +3,8 @@
using MelonLoader.Support.Preferences;
using UnityEngine;
+[assembly: MelonLoader.PatchShield]
+
namespace MelonLoader.Support
{
internal static class Main
diff --git a/Dependencies/SupportModules/Mono/Mono.csproj b/Dependencies/SupportModules/Mono/Mono.csproj
index 99ac434c8..53d0fbf85 100644
--- a/Dependencies/SupportModules/Mono/Mono.csproj
+++ b/Dependencies/SupportModules/Mono/Mono.csproj
@@ -2,24 +2,14 @@
MelonLoader.Support
net35
- Latest
true
- false
false
- $(SolutionDir)\Output\$(Configuration)\MelonLoader\Dependencies\SupportModules\
+ $(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\SupportModules\
true
embedded
-
-
-
-
-
-
- Libs\UnityEngine.dll
- False
-
+
@@ -29,8 +19,6 @@
-
- Runtime
-
+
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Mono/Properties/AssemblyInfo.cs b/Dependencies/SupportModules/Mono/Properties/AssemblyInfo.cs
deleted file mode 100644
index 1d42e64c4..000000000
--- a/Dependencies/SupportModules/Mono/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("EE48CA52-CCD3-48A5-B507-91773672E216")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
-[assembly: MelonLoader.PatchShield]
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Preload/Preload.cs b/Dependencies/SupportModules/Preload/Preload.cs
index 1e0c30c67..a74b603ef 100644
--- a/Dependencies/SupportModules/Preload/Preload.cs
+++ b/Dependencies/SupportModules/Preload/Preload.cs
@@ -1,5 +1,4 @@
using System.IO;
-using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System;
@@ -13,26 +12,30 @@ private static void Initialize()
if (Environment.Version >= new Version("3.0.0.0"))
return;
- string managedFolder = string.Copy(GetManagedDirectory());
+ var ownDir = typeof(Preload).Assembly.Location;
+ if (string.IsNullOrEmpty(ownDir))
+ return;
- WriteResource(Properties.Resources.System, Path.Combine(managedFolder, "System.dll"));
- WriteResource(Properties.Resources.System_Core, Path.Combine(managedFolder, "System.Core.dll"));
- WriteResource(Properties.Resources.System_Drawing, Path.Combine(managedFolder, "System.Drawing.dll"));
- }
+ ownDir = Path.GetDirectoryName(ownDir);
- [MethodImpl(MethodImplOptions.InternalCall)]
- [return: MarshalAs(UnmanagedType.LPStr)]
- private static extern string GetManagedDirectory();
+ var managedFolder = GetManagedDirectory();
- private static void WriteResource(byte[] data, string destination)
- {
- try
+ var patchesDir = Path.Combine(ownDir, "NetStandardPatches");
+ if (!Directory.Exists(patchesDir))
+ return;
+
+ foreach (var patch in Directory.GetFiles(patchesDir))
{
- if (File.Exists(destination))
- File.Delete(destination);
- File.WriteAllBytes(destination, data);
+ try
+ {
+ File.Copy(patch, Path.Combine(managedFolder, Path.GetFileName(patch)), true);
+ }
+ catch { }
}
- catch { }
}
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [return: MarshalAs(UnmanagedType.LPStr)]
+ private static extern string GetManagedDirectory();
}
}
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Preload/Preload.csproj b/Dependencies/SupportModules/Preload/Preload.csproj
index 0c79f1ccd..6dbe152a9 100644
--- a/Dependencies/SupportModules/Preload/Preload.csproj
+++ b/Dependencies/SupportModules/Preload/Preload.csproj
@@ -2,9 +2,7 @@
MelonLoader.Support
net20
- Latest
true
- false
false
$(SolutionDir)Output\$(Configuration)\MelonLoader\Dependencies\SupportModules\
true
@@ -17,22 +15,6 @@
-
-
-
-
-
-
-
- True
- True
- Resources.resx
-
-
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
-
+
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Preload/Properties/AssemblyInfo.cs b/Dependencies/SupportModules/Preload/Properties/AssemblyInfo.cs
deleted file mode 100644
index a078c0f7d..000000000
--- a/Dependencies/SupportModules/Preload/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("08BE056B-C854-4F88-92E8-F3B39187B6AF")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
\ No newline at end of file
diff --git a/Dependencies/SupportModules/Preload/Properties/Resources.Designer.cs b/Dependencies/SupportModules/Preload/Properties/Resources.Designer.cs
deleted file mode 100644
index d7760797e..000000000
--- a/Dependencies/SupportModules/Preload/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace MelonLoader.Support.Properties {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MelonLoader.Support.Properties.Resources", typeof(Resources).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Byte[].
- ///
- internal static byte[] System {
- get {
- object obj = ResourceManager.GetObject("System", resourceCulture);
- return ((byte[])(obj));
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Byte[].
- ///
- internal static byte[] System_Core {
- get {
- object obj = ResourceManager.GetObject("System.Core", resourceCulture);
- return ((byte[])(obj));
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Byte[].
- ///
- internal static byte[] System_Drawing {
- get {
- object obj = ResourceManager.GetObject("System.Drawing", resourceCulture);
- return ((byte[])(obj));
- }
- }
- }
-}
diff --git a/Dependencies/SupportModules/Preload/Properties/Resources.resx b/Dependencies/SupportModules/Preload/Properties/Resources.resx
deleted file mode 100644
index a2b6ad7b2..000000000
--- a/Dependencies/SupportModules/Preload/Properties/Resources.resx
+++ /dev/null
@@ -1,130 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
- ..\Resources\System.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\System.Core.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\System.Drawing.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
\ No newline at end of file
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 000000000..4b42315a4
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,11 @@
+
+
+ 0.6.6
+ Lava Gang
+ discord.gg/2Wn3N2P
+ Copyright (c) 2022 Lava Gang
+ Latest
+ false
+
+
+
\ No newline at end of file
diff --git a/MelonLoader.NativeHost/MelonLoader.NativeHost.csproj b/MelonLoader.NativeHost/MelonLoader.NativeHost.csproj
index 438c05c0f..ca78036f7 100644
--- a/MelonLoader.NativeHost/MelonLoader.NativeHost.csproj
+++ b/MelonLoader.NativeHost/MelonLoader.NativeHost.csproj
@@ -1,17 +1,17 @@
-
- net6
- enable
- enable
- $(SolutionDir)Output\$(Configuration)\MelonLoader\
- true
- True
- embedded
-
+
+ net6
+ enable
+ enable
+ $(SolutionDir)Output\$(Configuration)\MelonLoader\
+ true
+ True
+ embedded
+
-
-
-
+
+
+
-
+
\ No newline at end of file
diff --git a/MelonLoader.sln b/MelonLoader.sln
index a432ca006..01a75c5d9 100644
--- a/MelonLoader.sln
+++ b/MelonLoader.sln
@@ -96,13 +96,11 @@ Global
{762D7545-6F6B-441A-B040-49CC31A1713B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Debug|Windows - x64.ActiveCfg = Debug|Any CPU
- {762D7545-6F6B-441A-B040-49CC31A1713B}.Debug|Windows - x64.Build.0 = Debug|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Debug|Windows - x86.ActiveCfg = Debug|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Debug|Windows - x86.Build.0 = Debug|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Release|Any CPU.Build.0 = Release|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Release|Windows - x64.ActiveCfg = Release|Any CPU
- {762D7545-6F6B-441A-B040-49CC31A1713B}.Release|Windows - x64.Build.0 = Release|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Release|Windows - x86.ActiveCfg = Release|Any CPU
{762D7545-6F6B-441A-B040-49CC31A1713B}.Release|Windows - x86.Build.0 = Release|Any CPU
{542EC51D-E480-4802-B5AA-96EEC05AF19C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
diff --git a/MelonLoader/Attributes/VerifyLoaderVersionAttribute.cs b/MelonLoader/Attributes/VerifyLoaderVersionAttribute.cs
index ae49bf02b..941f841b0 100644
--- a/MelonLoader/Attributes/VerifyLoaderVersionAttribute.cs
+++ b/MelonLoader/Attributes/VerifyLoaderVersionAttribute.cs
@@ -1,51 +1,50 @@
using System;
using Semver;
-namespace MelonLoader
+namespace MelonLoader;
+
+[AttributeUsage(AttributeTargets.Assembly)]
+public class VerifyLoaderVersionAttribute(SemVersion semver, bool is_minimum) : Attribute
{
- [AttributeUsage(AttributeTargets.Assembly)]
- public class VerifyLoaderVersionAttribute : Attribute
- {
- ///
- /// Specified SemVersion.
- ///
- public SemVersion SemVer { get; private set; }
-
- ///
- /// Specified Version Major.
- ///
- public int Major { get; }
-
- ///
- /// Specified Version Minor.
- ///
- public int Minor { get; }
-
- ///
- /// Specified Version Patch.
- ///
- public int Patch { get; }
-
- ///
- /// If Version Specified is a Minimum.
- ///
- public bool IsMinimum { get; private set; }
-
-
- public VerifyLoaderVersionAttribute(int major, int minor, int patch) : this(new SemVersion(major, minor, patch), false) { }
- public VerifyLoaderVersionAttribute(int major, int minor, int patch, bool is_minimum) : this(new SemVersion(major, minor, patch), is_minimum) { }
- public VerifyLoaderVersionAttribute(string version) : this(version, false) { }
- public VerifyLoaderVersionAttribute(string version, bool is_minimum) : this(SemVersion.Parse(version), is_minimum) { }
- public VerifyLoaderVersionAttribute(SemVersion semver, bool is_minimum)
- {
- SemVer = semver;
- IsMinimum = is_minimum;
- }
-
- public bool IsCompatible(SemVersion version)
- => SemVer == null || version == null || (IsMinimum ? SemVer <= version : SemVer == version);
-
- public bool IsCompatible(string version)
- => !SemVersion.TryParse(version, out SemVersion ver) || IsCompatible(ver);
- }
+ ///
+ /// Specified SemVersion.
+ ///
+ public SemVersion SemVer { get; private set; } = semver;
+
+ ///
+ /// Specified Version Major.
+ ///
+ public int Major => SemVer.Major;
+
+ ///
+ /// Specified Version Minor.
+ ///
+ public int Minor => SemVer.Minor;
+
+ ///
+ /// Specified Version Patch.
+ ///
+ public int Patch => SemVer.Patch;
+
+ ///
+ /// Specified Version Prerelease.
+ ///
+ public string Prerelease => SemVer.Prerelease;
+
+ ///
+ /// If Version Specified is a Minimum.
+ ///
+ public bool IsMinimum { get; private set; } = is_minimum;
+
+ public VerifyLoaderVersionAttribute(int major, int minor, int patch) : this(new SemVersion(major, minor, patch), false) { }
+ public VerifyLoaderVersionAttribute(int major, int minor, int patch, string prerelease, bool is_minimum = false) : this(new SemVersion(major, minor, patch, prerelease), is_minimum) { }
+ public VerifyLoaderVersionAttribute(int major, int minor, int patch, bool is_minimum) : this(new SemVersion(major, minor, patch), is_minimum) { }
+ public VerifyLoaderVersionAttribute(string version) : this(version, false) { }
+ public VerifyLoaderVersionAttribute(string version, bool is_minimum) : this(SemVersion.Parse(version), is_minimum) { }
+
+ public bool IsCompatible(SemVersion version)
+ => SemVer == null || version == null || (IsMinimum ? SemVer <= version : SemVer == version);
+
+ public bool IsCompatible(string version)
+ => !SemVersion.TryParse(version, out SemVersion ver) || IsCompatible(ver);
}
\ No newline at end of file
diff --git a/MelonLoader/BuildInfo.cs b/MelonLoader/BuildInfo.cs
new file mode 100644
index 000000000..c83b90ff7
--- /dev/null
+++ b/MelonLoader/BuildInfo.cs
@@ -0,0 +1,23 @@
+using Semver;
+
+namespace MelonLoader;
+
+public static class BuildInfo
+{
+ public const string Name = "MelonLoader";
+ public const string Description = "MelonLoader";
+ public const string Author = "Lava Gang";
+ public const string Company = "discord.gg/2Wn3N2P";
+
+ public static SemVersion VersionNumber { get; private set; }
+
+ // NOTICE: This used to be a constant. Making it a property won't break backwards compatibility.
+ public static string Version { get; private set; }
+
+ static BuildInfo()
+ {
+ var version = typeof(BuildInfo).Assembly.GetName().Version!;
+ VersionNumber = new(version.Major, version.Minor, version.Build, version.Revision == 0 ? "" : ("ci." + version.Revision.ToString()));
+ Version = VersionNumber.ToString();
+ }
+}
\ No newline at end of file
diff --git a/MelonLoader/CompatibilityLayers/MelonCompatibilityLayer.cs b/MelonLoader/CompatibilityLayers/MelonCompatibilityLayer.cs
index 0f380aa48..f9b622239 100644
--- a/MelonLoader/CompatibilityLayers/MelonCompatibilityLayer.cs
+++ b/MelonLoader/CompatibilityLayers/MelonCompatibilityLayer.cs
@@ -18,10 +18,15 @@ public static class MelonCompatibilityLayer
private static void CheckGameLayerWithPlatform(string name, Func shouldBeIgnored)
{
+ if (string.IsNullOrEmpty(name))
+ return;
+
string nameNoSpaces = name.Replace(' ', '_');
foreach (var file in Directory.GetFiles(baseDirectory))
{
string fileName = Path.GetFileNameWithoutExtension(file);
+ if (string.IsNullOrEmpty(fileName))
+ continue;
if (fileName.StartsWith(nameNoSpaces))
layers.Add(new MelonModule.Info(file, shouldBeIgnored));
}
@@ -29,6 +34,9 @@ private static void CheckGameLayerWithPlatform(string name, Func shouldBeI
private static void CheckGameLayer(string name)
{
+ if (string.IsNullOrEmpty(name))
+ return;
+
CheckGameLayerWithPlatform(name, () => false);
CheckGameLayerWithPlatform($"{name}_Mono", () => MelonUtils.IsGameIl2Cpp());
CheckGameLayerWithPlatform($"{name}_Il2Cpp", () => !MelonUtils.IsGameIl2Cpp());
@@ -37,6 +45,9 @@ private static void CheckGameLayer(string name)
if (spaceIndex > 0)
{
name = name.Substring(0, spaceIndex - 1);
+ if (string.IsNullOrEmpty(name))
+ return;
+
CheckGameLayerWithPlatform(name, () => false);
CheckGameLayerWithPlatform($"{name}_Mono", () => MelonUtils.IsGameIl2Cpp());
CheckGameLayerWithPlatform($"{name}_Il2Cpp", () => !MelonUtils.IsGameIl2Cpp());
diff --git a/MelonLoader/Core.cs b/MelonLoader/Core.cs
index 5f5819b14..bb2206877 100644
--- a/MelonLoader/Core.cs
+++ b/MelonLoader/Core.cs
@@ -7,6 +7,9 @@
using MelonLoader.Resolver;
using MelonLoader.Utils;
using MelonLoader.InternalUtils;
+
+[assembly: MelonLoader.PatchShield]
+
#pragma warning disable IDE0051 // Prevent the IDE from complaining about private unreferenced methods
namespace MelonLoader
@@ -107,7 +110,7 @@ internal static int Initialize()
bHapticsManager.Connect(BuildInfo.Name, UnityInformationHandler.GameName);
MelonHandler.LoadUserlibs(MelonEnvironment.UserLibsDirectory);
- MelonHandler.LoadMelonFolders(MelonEnvironment.PluginsDirectory);
+ MelonHandler.LoadMelonsFromDirectory(MelonEnvironment.PluginsDirectory);
MelonEvents.MelonHarmonyEarlyInit.Invoke();
MelonEvents.OnPreInitialization.Invoke();
@@ -137,7 +140,7 @@ internal static int Start()
return 1;
MelonEvents.OnPreModsLoaded.Invoke();
- MelonHandler.LoadMelonFolders(MelonEnvironment.ModsDirectory);
+ MelonHandler.LoadMelonsFromDirectory(MelonEnvironment.ModsDirectory);
MelonEvents.OnPreSupportModule.Invoke();
if (!SupportModule.Setup())
diff --git a/MelonLoader/Fixes/Il2CppICallInjector.cs b/MelonLoader/Fixes/Il2CppICallInjector.cs
index bc2a8e7d7..7c4e00a4f 100644
--- a/MelonLoader/Fixes/Il2CppICallInjector.cs
+++ b/MelonLoader/Fixes/Il2CppICallInjector.cs
@@ -1,23 +1,22 @@
#if NET6_0_OR_GREATER
-using Il2CppInterop.Runtime;
-using Il2CppInterop.Runtime.InteropTypes;
using MelonLoader.NativeUtils;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using System;
using System.Collections.Generic;
using System.Reflection;
-using System.Reflection.Emit;
using System.Runtime.InteropServices;
+using Il2CppInterop.HarmonySupport;
+using HarmonyLib;
+
+#pragma warning disable 0649
namespace MelonLoader.Fixes
{
internal static class Il2CppICallInjector
{
- private const string _customICallSuffix = "_INative";
-
- private static Dictionary _lookup = new();
+ private static Dictionary _lookup = new();
private delegate IntPtr dil2cpp_resolve_icall(IntPtr signature);
private static NativeHook il2cpp_resolve_icall_hook;
@@ -25,18 +24,10 @@ internal static class Il2CppICallInjector
private delegate void dil2cpp_add_internal_call(IntPtr signature, IntPtr funcPtr);
private static dil2cpp_add_internal_call il2cpp_add_internal_call;
- private static Type _stringType;
- private static Type _intPtrType;
- private static Type _exceptionType;
- private static Type _il2CppObjectBaseType;
-
- private static MethodInfo _stringConcat;
- private static MethodInfo _objectToString;
- private static MethodInfo _melonLoggerError;
- private static MethodInfo _stringToIl2CppPtr;
- private static MethodInfo _il2CppPtrToString;
- private static MethodInfo _il2CppObjectBaseGetPointer;
+ private static Type _il2CppDetourMethodPatcher;
+ private static MethodInfo _generateNativeToManagedTrampoline;
+ private static bool _extendedDebug;
private static MelonLogger.Instance _logger;
internal static unsafe void Install()
@@ -45,41 +36,13 @@ internal static unsafe void Install()
{
_logger = new MelonLogger.Instance(nameof(Il2CppICallInjector));
- Type thisType = typeof(Il2CppICallInjector);
- Type objectType = typeof(object);
- Type il2cppType = typeof(IL2CPP);
-
- _il2CppObjectBaseType = typeof(Il2CppObjectBase);
- _exceptionType = typeof(Exception);
- _intPtrType = typeof(IntPtr);
- _stringType = typeof(string);
-
- _stringConcat = _stringType.GetMethod(nameof(string.Concat), [_stringType, _stringType]);
- if (_stringConcat == null)
- throw new Exception("Failed to get string.Concat");
-
- _objectToString = objectType.GetMethod(nameof(ToString));
- if (_objectToString == null)
- throw new Exception("Failed to get object.ToString");
-
- _stringToIl2CppPtr = il2cppType.GetMethod(nameof(IL2CPP.ManagedStringToIl2Cpp));
- if (_stringToIl2CppPtr == null)
- throw new Exception("Failed to get IL2CPP.ManagedStringToIl2Cpp");
-
- _melonLoggerError = thisType.GetMethod(nameof(LogError),
- BindingFlags.Static | BindingFlags.NonPublic,
- [_stringType]);
- if (_melonLoggerError == null)
- throw new Exception("Failed to get MelonLogger.Error");
+ _il2CppDetourMethodPatcher = typeof(HarmonySupport).Assembly.GetType("Il2CppInterop.HarmonySupport.Il2CppDetourMethodPatcher");
+ if (_il2CppDetourMethodPatcher == null)
+ throw new Exception("Failed to get Il2CppDetourMethodPatcher");
- _il2CppPtrToString = il2cppType.GetMethod(nameof(IL2CPP.Il2CppStringToManaged));
- if (_il2CppPtrToString == null)
- throw new Exception("Failed to get IL2CPP.Il2CppStringToManaged");
-
- PropertyInfo pointerProp = _il2CppObjectBaseType.GetProperty(nameof(Il2CppObjectBase.Pointer));
- if (_il2CppPtrToString == null)
- throw new Exception("Failed to get Il2CppObjectBase.Pointer");
- _il2CppObjectBaseGetPointer = pointerProp.GetMethod;
+ _generateNativeToManagedTrampoline = _il2CppDetourMethodPatcher.GetMethod("GenerateNativeToManagedTrampoline", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (_generateNativeToManagedTrampoline == null)
+ throw new Exception("Failed to get Il2CppDetourMethodPatcher.GenerateNativeToManagedTrampoline");
string gameAssemblyName = "GameAssembly";
NativeLibrary gameAssemblyLib = NativeLibrary.Load(gameAssemblyName);
@@ -101,7 +64,7 @@ internal static unsafe void Install()
}
catch (Exception e)
{
- LogError(e.ToString());
+ LogDebugWarning(e.ToString());
}
}
@@ -122,8 +85,24 @@ internal static void Shutdown()
}
}
+ private static void LogMsg(string msg)
+ => _logger.Msg(msg);
private static void LogError(string msg)
=> _logger.Error(msg);
+ private static void LogDebugMsg(string msg)
+ {
+ if (!_extendedDebug
+ || !MelonDebug.IsEnabled())
+ return;
+ _logger.Msg(msg);
+ }
+ private static void LogDebugWarning(string msg)
+ {
+ if (!_extendedDebug
+ || !MelonDebug.IsEnabled())
+ return;
+ _logger.Warning(msg);
+ }
private static IntPtr il2cpp_resolve_icall_Detour(IntPtr signature)
{
@@ -134,31 +113,44 @@ private static IntPtr il2cpp_resolve_icall_Detour(IntPtr signature)
// Check Cache
if (_lookup.TryGetValue(signatureStr, out var result))
- return result.Item3;
+ {
+ LogDebugMsg($"Resolved {signatureStr} to ICall in Cache");
+ return result.Item4;
+ }
// Run Original
IntPtr originalResult = il2cpp_resolve_icall_hook.Trampoline(signature);
if (originalResult != IntPtr.Zero)
{
// Cache Original Result
- _lookup[signatureStr] = (null, null, originalResult);
+ LogDebugMsg($"Resolved {signatureStr} to Unity ICall");
+ _lookup[signatureStr] = (null, null, null, originalResult);
return originalResult;
}
// Check if Injection is Needed
if (!ShouldInject(signatureStr, out MethodInfo unityShimMethod))
+ {
+ LogDebugWarning($"Unable to find suitable method to inject for {signatureStr}");
return IntPtr.Zero;
+ }
// Create Injected Function and Cache Return
- var pair =
- _lookup[signatureStr] = GenerateTrampoline(unityShimMethod);
+ LogDebugMsg($"Generating Trampoline for {signatureStr}");
+ var pair = GenerateTrampoline(unityShimMethod);
+ if (pair.Item4 == IntPtr.Zero)
+ {
+ LogDebugWarning($"Failed to generate trampoline for {signatureStr}");
+ return IntPtr.Zero;
+ }
// Add New ICall to Il2Cpp Domain
- il2cpp_add_internal_call(signature, pair.Item3);
- _logger.Msg($"Registered mono icall {signatureStr} in il2cpp domain");
+ _lookup[signatureStr] = pair;
+ il2cpp_add_internal_call(signature, pair.Item4);
+ LogMsg($"Registered mono icall {signatureStr} in il2cpp domain");
// Return New Function Pointer
- return pair.Item3;
+ return pair.Item4;
}
private static Type FindType(string typeFullName)
@@ -192,6 +184,7 @@ private static bool ShouldInject(string signature, out MethodInfo unityShimMetho
// Split the Signature
string[] split = signature.Split("::");
string typeName = split[0];
+ string methodName = split[1];
// Find Managed Type
Type newType = FindType(typeName);
@@ -199,166 +192,67 @@ private static bool ShouldInject(string signature, out MethodInfo unityShimMetho
return false;
// Find Managed Method
- string methodName = split[1];
- MethodInfo method = newType.FindMethod(methodName);
- if (method == null)
+ MethodInfo targetMethod = null;
+ try
+ {
+ // Get All Methods
+ MethodInfo[] allMethods = newType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
+ foreach (var method in allMethods)
+ {
+ // Validate Method
+ if ((method == null)
+ || (method.Name != methodName))
+ continue;
+
+ // Check for Generic Method since ICalls can't be Generic
+ if (method.IsGenericMethod)
+ continue;
+
+ // Check for PInvoke to prevent Recursion
+ if (method.Attributes.HasFlag(MethodAttributes.PinvokeImpl))
+ continue;
+
+ // Check for Extern to prevent Recursion
+ var methodImpl = method.GetMethodImplementationFlags();
+ if (methodImpl.HasFlag(MethodImplAttributes.InternalCall)
+ || methodImpl.HasFlag(MethodImplAttributes.Native)
+ || methodImpl.HasFlag(MethodImplAttributes.Unmanaged))
+ continue;
+
+ // Check if Method has no Body or just throws NotImplementedException
+ if (!method.HasMethodBody()
+ || method.IsNotImplemented())
+ continue;
+
+ // Found Shim
+ targetMethod = method;
+ break;
+ }
+ }
+ catch { return false; }
+ if (targetMethod == null)
return false;
// Inject ICall
- unityShimMethod = method;
+ unityShimMethod = targetMethod;
return true;
}
- private static (DynamicMethodDefinition, MethodInfo, IntPtr) GenerateTrampoline(MethodInfo unityShimMethod)
+ private static (object, DynamicMethodDefinition, MethodInfo, IntPtr) GenerateTrampoline(MethodInfo unityShimMethod)
{
- // Convert Method Parameters to Native Parameters
- var methodParams = unityShimMethod.GetParameters();
- int offset = unityShimMethod.IsStatic ? 0 : 1;
- Type[] paramTypes = new Type[methodParams.Length + offset];
- if (!unityShimMethod.IsStatic)
- paramTypes[0] = _intPtrType;
- for (int i = 0; i < methodParams.Length; i++)
- {
- if ((methodParams[i].ParameterType != _stringType)
- && methodParams[i].ParameterType.IsValueType)
- paramTypes[i + offset] = methodParams[i].ParameterType;
- else
- paramTypes[i + offset] = _intPtrType;
- }
-
- // Convert Return Type
- Type returnType = unityShimMethod.ReturnType;
- if ((returnType == _stringType)
- || !returnType.IsValueType)
- returnType = _intPtrType;
+ // Create Patcher
+ object patcher = Activator.CreateInstance(_il2CppDetourMethodPatcher, [ unityShimMethod ]);
+ if (patcher == null)
+ return (null, null, null, IntPtr.Zero);
// Create New Injected ICall Method
- string newMethodName = $"{unityShimMethod.Name}{_customICallSuffix}";
- var trampoline = new DynamicMethodDefinition(
- newMethodName,
- returnType,
- paramTypes);
- var ilGenerator = trampoline.GetILGenerator();
-
- // Begin Try-Catch
- ilGenerator.BeginExceptionBlock();
-
- // Emit This Object
- if (!unityShimMethod.IsStatic)
- ilGenerator.EmitPtrArgToManagedObject(0, unityShimMethod.DeclaringType);
-
- // Convert Method Parameters to Managed Objects
- for (var i = 0; i < methodParams.Length; i++)
- {
- var param = methodParams[i];
- var paramType = param.ParameterType;
- if (paramType == _stringType)
- ilGenerator.EmitPtrArgToString(i + offset);
- else if (paramType.IsValueType)
- ilGenerator.EmitArg(i + offset);
- else
- ilGenerator.EmitPtrArgToManagedObject(i + offset, paramType);
- }
-
- // Call Existing Method
- ilGenerator.Emit(OpCodes.Call, unityShimMethod);
-
- // Convert Managed Return
- var oldreturnType = unityShimMethod.ReturnType;
- if (oldreturnType == _stringType)
- ilGenerator.EmitStringToPtr();
- else if ((oldreturnType == _il2CppObjectBaseType)
- || oldreturnType.IsSubclassOf(_il2CppObjectBaseType))
- ilGenerator.EmitIl2CppObjectBaseToPtr();
-
- // Cache Return Value in Lcal
- LocalBuilder returnLocal = null;
- if (returnType != typeof(void))
- {
- returnLocal = ilGenerator.DeclareLocal(returnType);
- ilGenerator.Emit(OpCodes.Stloc, returnLocal);
- }
-
- // End Try-Catch
- ilGenerator.EmitExceptionCatch();
-
- // Restore Return Value from Local
- if (returnLocal != null)
- ilGenerator.Emit(OpCodes.Ldloc, returnLocal);
-
- // Return even if there is no Return Value
- ilGenerator.Emit(OpCodes.Ret);
-
+ DynamicMethodDefinition trampoline = (DynamicMethodDefinition)_generateNativeToManagedTrampoline.Invoke(patcher, [ unityShimMethod ]);
+ if (trampoline == null)
+ return (null, null, null, IntPtr.Zero);
+
// Return the New Method
MethodInfo newMethod = trampoline.Generate().Pin();
- return (trampoline, newMethod, newMethod.GetNativeStart());
- }
-
- private static void EmitArg(this ILGenerator ilGenerator,
- int index)
- => ilGenerator.Emit(OpCodes.Ldarg, index);
-
- private static void EmitPtrArgToString(this ILGenerator ilGenerator,
- int argIndex)
- {
- ilGenerator.EmitArg(argIndex);
- ilGenerator.Emit(OpCodes.Call, _il2CppPtrToString);
- }
-
- private static void EmitStringToPtr(this ILGenerator ilGenerator)
- => ilGenerator.Emit(OpCodes.Call, _stringToIl2CppPtr);
-
- private static void EmitPtrArgToManagedObject(this ILGenerator ilGenerator,
- int argIndex,
- Type managedType)
- {
- ilGenerator.EmitArg(argIndex);
-
- var labelNull = ilGenerator.DefineLabel();
- var labelDone = ilGenerator.DefineLabel();
- ilGenerator.Emit(OpCodes.Brfalse, labelNull);
- ilGenerator.EmitArg(argIndex);
-
- ilGenerator.Emit(OpCodes.Newobj,
- managedType.GetConstructor([ _intPtrType ]));
-
- ilGenerator.Emit(OpCodes.Br, labelDone);
- ilGenerator.MarkLabel(labelNull);
- ilGenerator.Emit(OpCodes.Ldnull);
- ilGenerator.MarkLabel(labelDone);
- }
-
- private static void EmitIl2CppObjectBaseToPtr(this ILGenerator ilGenerator)
- {
- var labelNull = ilGenerator.DefineLabel();
- var labelDone = ilGenerator.DefineLabel();
- ilGenerator.Emit(OpCodes.Dup);
- ilGenerator.Emit(OpCodes.Brfalse, labelNull);
-
- ilGenerator.Emit(OpCodes.Call, _il2CppObjectBaseGetPointer);
-
- ilGenerator.Emit(OpCodes.Br, labelDone);
- ilGenerator.MarkLabel(labelNull);
- ilGenerator.Emit(OpCodes.Pop);
- ilGenerator.Emit(OpCodes.Ldc_I4_0);
- ilGenerator.Emit(OpCodes.Conv_I);
- ilGenerator.MarkLabel(labelDone);
- }
-
- private static void EmitExceptionCatch(this ILGenerator ilGenerator)
- {
- var exceptionLocal = ilGenerator.DeclareLocal(_exceptionType);
- ilGenerator.BeginCatchBlock(_exceptionType);
-
- ilGenerator.Emit(OpCodes.Stloc, exceptionLocal);
- ilGenerator.Emit(OpCodes.Ldstr, "Exception in IL2CPP Injected ICall: ");
- ilGenerator.Emit(OpCodes.Ldloc, exceptionLocal);
-
- ilGenerator.Emit(OpCodes.Callvirt, _objectToString);
- ilGenerator.Emit(OpCodes.Call, _stringConcat);
- ilGenerator.Emit(OpCodes.Call, _melonLoggerError);
-
- ilGenerator.EndExceptionBlock();
+ return (patcher, trampoline, newMethod, newMethod.GetNativeStart());
}
}
}
diff --git a/MelonLoader/Fixes/Il2CppInteropFixes.cs b/MelonLoader/Fixes/Il2CppInteropFixes.cs
index ea58d70aa..c94fc0351 100644
--- a/MelonLoader/Fixes/Il2CppInteropFixes.cs
+++ b/MelonLoader/Fixes/Il2CppInteropFixes.cs
@@ -67,6 +67,19 @@ internal unsafe static class Il2CppInteropFixes
private static MethodInfo _reportException;
private static MethodInfo _reportException_Prefix;
+ private static void LogMsg(string msg)
+ => _logger.Msg(msg);
+ private static void LogError(Exception ex)
+ => _logger.Error(ex);
+ private static void LogError(string msg, Exception ex)
+ => _logger.Error(msg, ex);
+ private static void LogDebugMsg(string msg)
+ {
+ if (!MelonDebug.IsEnabled())
+ return;
+ _logger.Msg(msg);
+ }
+
internal static void Install()
{
try
@@ -173,61 +186,61 @@ internal static void Install()
_rewriteGlobalContext_TryGetNewTypeForOriginal_Prefix = thisType.GetMethod(nameof(RewriteGlobalContext_TryGetNewTypeForOriginal_Prefix), BindingFlags.NonPublic | BindingFlags.Static);
_reportException_Prefix = thisType.GetMethod(nameof(ReportException_Prefix), BindingFlags.NonPublic | BindingFlags.Static);
- MelonDebug.Msg("Patching Il2CppInterop ClassInjector.SystemTypeFromIl2CppType...");
+ LogDebugMsg("Patching Il2CppInterop ClassInjector.SystemTypeFromIl2CppType...");
Core.HarmonyInstance.Patch(_systemTypeFromIl2CppType,
new HarmonyMethod(_systemTypeFromIl2CppType_Prefix),
null,
new HarmonyMethod(_systemTypeFromIl2CppType_Transpiler));
- MelonDebug.Msg("Patching Il2CppInterop ClassInjector.RegisterTypeInIl2Cpp...");
+ LogDebugMsg("Patching Il2CppInterop ClassInjector.RegisterTypeInIl2Cpp...");
Core.HarmonyInstance.Patch(_registerTypeInIl2Cpp,
null,
null,
new HarmonyMethod(_registerTypeInIl2Cpp_Transpiler));
- MelonDebug.Msg("Patching Il2CppInterop ClassInjector.IsTypeSupported...");
+ LogDebugMsg("Patching Il2CppInterop ClassInjector.IsTypeSupported...");
Core.HarmonyInstance.Patch(_isTypeSupported,
null,
null,
new HarmonyMethod(_isTypeSupported_Transpiler));
- MelonDebug.Msg("Patching Il2CppInterop ClassInjector.RewriteType...");
+ LogDebugMsg("Patching Il2CppInterop ClassInjector.RewriteType...");
Core.HarmonyInstance.Patch(_rewriteType,
new HarmonyMethod(_rewriteType_Prefix));
- MelonDebug.Msg("Patching Il2CppInterop ClassInjector.ConvertMethodInfo...");
+ LogDebugMsg("Patching Il2CppInterop ClassInjector.ConvertMethodInfo...");
Core.HarmonyInstance.Patch(_convertMethodInfo,
null,
null,
new HarmonyMethod(_convertMethodInfo_Transpiler));
- MelonDebug.Msg("Patching Il2CppInterop ILGeneratorEx.EmitObjectToPointer...");
+ LogDebugMsg("Patching Il2CppInterop ILGeneratorEx.EmitObjectToPointer...");
Core.HarmonyInstance.Patch(_emitObjectToPointer,
new HarmonyMethod(_emitObjectToPointer_Prefix));
- MelonDebug.Msg("Patching Il2CppInterop RewriteGlobalContext.AddAssemblyContext...");
+ LogDebugMsg("Patching Il2CppInterop RewriteGlobalContext.AddAssemblyContext...");
Core.HarmonyInstance.Patch(_rewriteGlobalContext_AddAssemblyContext,
null, new HarmonyMethod(_rewriteGlobalContext_AddAssemblyContext_Postfix));
- MelonDebug.Msg("Patching Il2CppInterop RewriteGlobalContext.Dispose...");
+ LogDebugMsg("Patching Il2CppInterop RewriteGlobalContext.Dispose...");
Core.HarmonyInstance.Patch(_rewriteGlobalContext_Dispose,
new HarmonyMethod(_rewriteGlobalContext_Dispose_Prefix));
- MelonDebug.Msg("Patching Il2CppInterop RewriteGlobalContext.GetNewAssemblyForOriginal...");
+ LogDebugMsg("Patching Il2CppInterop RewriteGlobalContext.GetNewAssemblyForOriginal...");
Core.HarmonyInstance.Patch(_rewriteGlobalContext_GetNewAssemblyForOriginal,
new HarmonyMethod(_rewriteGlobalContext_GetNewAssemblyForOriginal_Prefix));
- MelonDebug.Msg("Patching Il2CppInterop RewriteGlobalContext.TryGetNewTypeForOriginal...");
+ LogDebugMsg("Patching Il2CppInterop RewriteGlobalContext.TryGetNewTypeForOriginal...");
Core.HarmonyInstance.Patch(_rewriteGlobalContext_TryGetNewTypeForOriginal,
new HarmonyMethod(_rewriteGlobalContext_TryGetNewTypeForOriginal_Prefix));
- MelonDebug.Msg("Patching Il2CppInterop Il2CppDetourMethodPatcher.ReportException...");
+ LogDebugMsg("Patching Il2CppInterop Il2CppDetourMethodPatcher.ReportException...");
Core.HarmonyInstance.Patch(_reportException,
new HarmonyMethod(_reportException_Prefix));
}
catch (Exception e)
{
- MelonLogger.Error(e);
+ LogError(e);
}
}
@@ -299,15 +312,13 @@ private static void FixedAddTypeToLookup(Type type, IntPtr typePointer)
private static bool ReportException_Prefix(Exception __0)
{
- _logger.Error("During invoking native->managed trampoline", __0);
-
+ LogError("During invoking native->managed trampoline", __0);
return false;
}
private static bool EmitObjectToPointer_Prefix(bool __7, ref bool __8)
{
__8 = __7;
-
return true;
}
@@ -342,7 +353,7 @@ private static void RewriteGlobalContext_AddAssemblyContext_Postfix(RewriteGloba
return;
contexts[assemblyName] = __1;
- //MelonDebug.Msg($"[RewriteGlobalContext] Added: {assemblyName}");
+ //LogDebugMsg($"[RewriteGlobalContext] Added: {assemblyName}");
}
private static bool RewriteGlobalContext_Dispose_Prefix(RewriteGlobalContext __instance)
@@ -370,7 +381,7 @@ private static bool RewriteGlobalContext_GetNewAssemblyForOriginal_Prefix(Rewrit
string assemblyName = __0.Name;
if (contexts.TryGetValue(assemblyName, out __result))
{
- //MelonDebug.Msg($"[RewriteGlobalContext] Found: {assemblyName}");
+ //LogDebugMsg($"[RewriteGlobalContext] Found: {assemblyName}");
return false;
}
@@ -381,7 +392,7 @@ private static bool RewriteGlobalContext_GetNewAssemblyForOriginal_Prefix(Rewrit
if (contexts.TryGetValue(assemblyName, out __result))
{
- //MelonDebug.Msg($"[RewriteGlobalContext] Found: {assemblyName}");
+ //LogDebugMsg($"[RewriteGlobalContext] Found: {assemblyName}");
return false;
}
@@ -407,7 +418,7 @@ private static bool RewriteGlobalContext_TryGetNewTypeForOriginal_Prefix(Rewrite
AssemblyRewriteContext rewriteContext = null;
if (contexts.TryGetValue(assemblyName, out rewriteContext))
{
- //MelonDebug.Msg($"[RewriteGlobalContext] Found: {assemblyName}");
+ //LogDebugMsg($"[RewriteGlobalContext] Found: {assemblyName}");
__result = rewriteContext.TryGetContextForOriginalType(__0);
return false;
}
@@ -418,7 +429,7 @@ private static bool RewriteGlobalContext_TryGetNewTypeForOriginal_Prefix(Rewrite
assemblyName = $"Il2Cpp{assemblyName}";
if (contexts.TryGetValue(assemblyName, out rewriteContext))
{
- //MelonDebug.Msg($"[RewriteGlobalContext] Found: {assemblyName}");
+ //LogDebugMsg($"[RewriteGlobalContext] Found: {assemblyName}");
__result = rewriteContext.TryGetContextForOriginalType(__0);
return false;
}
@@ -510,7 +521,7 @@ private static IEnumerable SystemTypeFromIl2CppType_Transpiler(
instruction.opcode = OpCodes.Call;
instruction.operand = _fixedFindType;
- MelonDebug.Msg("Patched Il2CppInterop ClassInjector.SystemTypeFromIl2CppType -> Type.GetType");
+ LogDebugMsg("Patched Il2CppInterop ClassInjector.SystemTypeFromIl2CppType -> Type.GetType");
}
yield return instruction;
@@ -529,7 +540,7 @@ private static IEnumerable RegisterTypeInIl2Cpp_Transpiler(IEnu
found = true;
instruction.opcode = OpCodes.Call;
instruction.operand = _fixedAddTypeToLookup;
- MelonDebug.Msg("Patched Il2CppInterop ClassInjector.RegisterTypeInIl2Cpp -> InjectorHelpers.AddTypeToLookup");
+ LogDebugMsg("Patched Il2CppInterop ClassInjector.RegisterTypeInIl2Cpp -> InjectorHelpers.AddTypeToLookup");
}
if (!found2
@@ -539,7 +550,7 @@ private static IEnumerable RegisterTypeInIl2Cpp_Transpiler(IEnu
found2 = true;
instruction.opcode = OpCodes.Call;
instruction.operand = _fixedFindAbstractMethods;
- MelonDebug.Msg("Patched Il2CppInterop ClassInjector.RegisterTypeInIl2Cpp -> FindAbstractMethods");
+ LogDebugMsg("Patched Il2CppInterop ClassInjector.RegisterTypeInIl2Cpp -> FindAbstractMethods");
}
yield return instruction;
@@ -558,7 +569,7 @@ private static IEnumerable ConvertMethodInfo_Transpiler(IEnumer
found = true;
instruction.opcode = OpCodes.Call;
instruction.operand = _fixedIsByRef;
- MelonDebug.Msg("Patched Il2CppInterop ClassInjector.ConvertMethodInfo -> Type.IsByRef");
+ LogDebugMsg("Patched Il2CppInterop ClassInjector.ConvertMethodInfo -> Type.IsByRef");
}
yield return instruction;
@@ -576,7 +587,7 @@ private static IEnumerable IsTypeSupported_Transpiler(IEnumerab
found = true;
instruction.opcode = OpCodes.Call;
instruction.operand = _fixedIsByRef;
- MelonDebug.Msg("Patched Il2CppInterop ClassInjector.IsTypeSupported -> Type.IsByRef");
+ LogDebugMsg("Patched Il2CppInterop ClassInjector.IsTypeSupported -> Type.IsByRef");
}
yield return instruction;
diff --git a/MelonLoader/InternalUtils/DependencyGraph.cs b/MelonLoader/InternalUtils/DependencyGraph.cs
index 546fbdbaa..8c232ef92 100644
--- a/MelonLoader/InternalUtils/DependencyGraph.cs
+++ b/MelonLoader/InternalUtils/DependencyGraph.cs
@@ -179,7 +179,7 @@ private static string BuildMissingDependencyMessage(IDictionary argEnumerator = new LemonEnumerator(CommandLineArgs);
- while (argEnumerator.MoveNext())
+ string[] args = CommandLineArgs;
+ int maxLen = args.Length;
+ for (int i = 1; i < maxLen; i++)
{
- string fullcmd = argEnumerator.Current;
+ string fullcmd = args[i];
if (string.IsNullOrEmpty(fullcmd))
continue;
@@ -78,11 +79,12 @@ internal static void Load()
noPrefixCmd = split[0];
cmdArg = split[1];
}
+
if ((string.IsNullOrEmpty(cmdArg)
- && !argEnumerator.Peek(out cmdArg))
+ && ((i + 1) >= maxLen))
|| string.IsNullOrEmpty(cmdArg)
- || !cmdArg.StartsWith("--")
- || !cmdArg.StartsWith("-"))
+ || cmdArg.StartsWith("--")
+ || cmdArg.StartsWith("-"))
{
// Unknown Command, Add it to Dictionary
ExternalArguments.Add(noPrefixCmd, null);
diff --git a/MelonLoader/MelonLoader.csproj b/MelonLoader/MelonLoader.csproj
index 7b13fc509..8abca3600 100644
--- a/MelonLoader/MelonLoader.csproj
+++ b/MelonLoader/MelonLoader.csproj
@@ -1,26 +1,21 @@
-
+
net35;net6
- Latest
true
- false
true
$(SolutionDir)Output\$(Configuration)\MelonLoader\
$(OutputPath)$(TargetFramework)\MelonLoader.xml
true
true
embedded
-
- 0.6.6
+
+ true
LavaGang.MelonLoader
modding unity
https://github.com/LavaGang/MelonLoader
Apache-2.0
git
https://github.com/LavaGang/MelonLoader
- Lava Gang
- Lava Gang
- Copyright (c) 2022 Lava Gang
The World's First Universal Mod Loader for Unity Games compatible with both Il2Cpp and Mono.
@@ -31,30 +26,41 @@
all
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
-
+
+
+
-
-
-
+
diff --git a/MelonLoader/MelonUtils.cs b/MelonLoader/MelonUtils.cs
index fa0e64974..281a33ce8 100644
--- a/MelonLoader/MelonUtils.cs
+++ b/MelonLoader/MelonUtils.cs
@@ -51,7 +51,7 @@ internal static void Setup(AppDomain domain)
UnityInformationHandler.Setup();
CurrentGameAttribute = new MelonGameAttribute(UnityInformationHandler.GameDeveloper, UnityInformationHandler.GameName);
- CurrentPlatform = IsGame32Bit() ? MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X86 : MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64; // Temporarily
+ CurrentPlatform = IsGame32Bit() ? MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X86 : MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64;
CurrentDomain = IsGameIl2Cpp() ? MelonPlatformDomainAttribute.CompatibleDomains.IL2CPP : MelonPlatformDomainAttribute.CompatibleDomains.MONO;
}
@@ -303,11 +303,14 @@ public static IEnumerable GetValidTypes(this Assembly asm, LemonFunc (x != null) && (predicate == null || predicate(x)));
}
@@ -318,9 +321,9 @@ public static Type GetValidType(this Assembly asm, string typeName, LemonFunc FindIncompatiblities(game, processName, gameVersion, SemVersion.Parse(mlVersion), mlBuildHashCode, platform, domain);
+
+ public Incompatibility[] FindIncompatiblities(MelonGameAttribute game, string processName, string gameVersion,
+ SemVersion mlVersion, string mlBuildHashCode, MelonPlatformAttribute.CompatiblePlatforms platform,
+ MelonPlatformDomainAttribute.CompatibleDomains domain)
{
var result = new List();
if (!(Games.Length == 0 || Games.Any(x => x.IsCompatible(game))))
@@ -305,7 +311,7 @@ public Incompatibility[] FindIncompatiblities(MelonGameAttribute game, string pr
public Incompatibility[] FindIncompatiblitiesFromContext()
{
- return FindIncompatiblities(MelonUtils.CurrentGameAttribute, Process.GetCurrentProcess().ProcessName, MelonUtils.GameVersion, BuildInfo.Version, MelonUtils.HashCode, MelonUtils.CurrentPlatform, MelonUtils.CurrentDomain);
+ return FindIncompatiblities(MelonUtils.CurrentGameAttribute, Process.GetCurrentProcess().ProcessName, MelonUtils.GameVersion, BuildInfo.VersionNumber, MelonUtils.HashCode, MelonUtils.CurrentPlatform, MelonUtils.CurrentDomain);
}
public static void PrintIncompatibilities(Incompatibility[] incompatibilities, MelonBase melon)
diff --git a/MelonLoader/Melons/MelonFolderHandler.cs b/MelonLoader/Melons/MelonFolderHandler.cs
index 49db61987..44213d085 100644
--- a/MelonLoader/Melons/MelonFolderHandler.cs
+++ b/MelonLoader/Melons/MelonFolderHandler.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Drawing;
using System.IO;
@@ -6,7 +7,32 @@ namespace MelonLoader.Melons
{
internal class MelonFolderHandler
{
- internal static void Scan(string path) where T : MelonTypeBase
+ private static bool firstSpacer = false;
+
+ internal enum eScanType
+ {
+ UserLibs,
+ Plugins,
+ Mods,
+ }
+
+ internal static void ScanUserLibs(string path)
+ {
+ // Get Full Directory Path
+ path = Path.GetFullPath(path);
+
+ // Log Loading Message
+ var loadingMsg = $"Loading UserLibs from '{path}'...";
+ MelonLogger.WriteSpacer();
+ MelonLogger.Msg(loadingMsg);
+
+ // Parse Folders
+ bool hasWroteLine = false;
+ List melonAssemblies = new();
+ ProcessFolder(eScanType.UserLibs, path, ref hasWroteLine, ref melonAssemblies);
+ }
+
+ internal static void ScanMelons(string path) where T : MelonTypeBase
{
// Get Full Directory Path
path = Path.GetFullPath(path);
@@ -17,9 +43,11 @@ internal static void Scan(string path) where T : MelonTypeBase
MelonLogger.Msg(loadingMsg);
// Parse Folders
+ Type melonType = typeof(T);
+ bool isMod = melonType == typeof(MelonMod);
bool hasWroteLine = false;
List melonAssemblies = new();
- ProcessFolder(path, ref hasWroteLine, ref melonAssemblies);
+ ProcessFolder(isMod ? eScanType.Mods : eScanType.Plugins, path, ref hasWroteLine, ref melonAssemblies);
// Parse Queue
var melons = new List();
@@ -57,120 +85,97 @@ internal static void Scan(string path) where T : MelonTypeBase
// Log Melon Count
var count = MelonTypeBase._registeredMelons.Count;
MelonLogger.Msg($"{count} {MelonTypeBase.TypeName.MakePlural(count)} loaded.");
- if (MelonHandler.firstSpacer || (typeof(T) == typeof(MelonMod)))
+ if (firstSpacer || (typeof(T) == typeof(MelonMod)))
MelonLogger.WriteSpacer();
- MelonHandler.firstSpacer = true;
+ firstSpacer = true;
}
- private static void LoadFolder(string path,
- bool addToList,
+ private static void ProcessFolder(eScanType scanType,
+ string path,
ref bool hasWroteLine,
- ref List melonAssemblies) where T : MelonTypeBase
+ ref List melonAssemblies)
{
- // Get DLLs in Directory
- var files = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly);
- foreach (var f in files)
- {
- // Log
- if (!hasWroteLine)
- {
- hasWroteLine = true;
- MelonLogger.WriteLine(Color.Magenta);
- }
+ // Validate Path
+ if (!Directory.Exists(path))
+ return;
- // Load Assembly
- var asm = MelonAssembly.LoadMelonAssembly(f, false);
- if (asm == null)
- continue;
+ // Scan Directories
+ List melonDirectories = new();
+ List userLibDirectories = new();
+ ScanFolder(scanType, path, ref melonDirectories, ref userLibDirectories);
- // Queue Assembly for Melon Parsing
- if (addToList)
- melonAssemblies.Add(asm);
+ // Add Base Path to End of Directories List
+ if (scanType == eScanType.UserLibs)
+ userLibDirectories.Add(path);
+ else
+ melonDirectories.Add(path);
+
+ // Add Directories to Resolver
+ foreach (string directory in userLibDirectories)
+ {
+ MelonUtils.AddNativeDLLDirectory(directory);
+ Resolver.MelonAssemblyResolver.AddSearchDirectory(directory);
}
- }
+ if (scanType != eScanType.UserLibs)
+ foreach (string directory in melonDirectories)
+ Resolver.MelonAssemblyResolver.AddSearchDirectory(directory);
- private static bool IsUserLibsFolder(string dirNameLower)
- => dirNameLower.StartsWith("userlibs")
- || dirNameLower.EndsWith("userlibs");
+ // Load UserLibs
+ MelonPreprocessor.LoadFolders(userLibDirectories, false, ref hasWroteLine, ref melonAssemblies);
- private static bool IsDisabledFolder(string path,
- out string dirNameLower)
- {
- string dirName = new DirectoryInfo(path).Name;
- dirNameLower = dirName.ToLowerInvariant();
- return dirNameLower.StartsWith("disabled")
- || dirNameLower.EndsWith("disabled")
- || dirNameLower.StartsWith("old")
- || dirNameLower.EndsWith("old");
+ // Load Melons from Folders
+ if (scanType != eScanType.UserLibs)
+ MelonPreprocessor.LoadFolders(melonDirectories, true, ref hasWroteLine, ref melonAssemblies);
}
- private static void ProcessFolder(string path,
- ref bool hasWroteLine,
- ref List melonAssemblies) where T : MelonTypeBase
+ private static void ScanFolder(eScanType scanType,
+ string path,
+ ref List melonDirectories,
+ ref List userLibDirectories)
{
- // Validate Path
- if (!Directory.Exists(path))
- return;
-
- // Add Base Path to Resolver
- Resolver.MelonAssemblyResolver.AddSearchDirectory(path);
-
// Get Directories
- var directories = Directory.GetDirectories(path, "*", SearchOption.AllDirectories);
+ string[] directories = Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly);
+ if ((directories == null)
+ || (directories.Length <= 0))
+ return;
- // Add Directories to Resolver
- if ((directories != null) && (directories.Length > 0))
+ // Parse Directories
+ foreach (var dir in directories)
{
- foreach (var dir in directories)
- {
- // Validate Path
- if (!Directory.Exists(dir))
- continue;
-
- // Skip Disabled Folders
- if (IsDisabledFolder(dir, out string dirNameLower))
- continue;
+ // Validate Path
+ if (!Directory.Exists(dir))
+ continue;
- // Load Assemblies
- if (IsUserLibsFolder(dirNameLower))
- MelonUtils.AddNativeDLLDirectory(dir);
- Resolver.MelonAssemblyResolver.AddSearchDirectory(dir);
- }
+ // Validate Manifest
+ string manifestPath = Path.Combine(dir, "manifest.json");
+ if (!File.Exists(manifestPath))
+ continue;
- // Load UserLibs
- foreach (var dir in directories)
+ // Check for Deeper UserLibs
+ string userLibsPath = Path.Combine(dir, "UserLibs");
+ if (Directory.Exists(userLibsPath))
{
- // Validate Path
- if (!Directory.Exists(dir))
- continue;
-
- // Skip Disabled Folders and any folders that doesn't end with or isn't equal to UserLibs
- if (IsDisabledFolder(dir, out string dirNameLower)
- || !IsUserLibsFolder(dirNameLower))
- continue;
-
- // Load Assemblies
- LoadFolder(dir, false, ref hasWroteLine, ref melonAssemblies);
+ userLibDirectories.Add(userLibsPath);
+ ScanFolder(eScanType.UserLibs, userLibsPath, ref melonDirectories, ref userLibDirectories);
}
- // Load Melons from Extended Folders
- foreach (var dir in directories)
+ // Is UserLibs Scan?
+ if (scanType == eScanType.UserLibs)
+ userLibDirectories.Add(dir); // Add to Directories List
+ else
{
- // Validate Path
- if (!Directory.Exists(dir))
- continue;
-
- // Skip Disabled Folders
- if (IsDisabledFolder(dir, out _))
- continue;
+ // Check for Deeper Melon Folder
+ string melonPath = Path.Combine(dir, (scanType == eScanType.Plugins) ? "Plugins" : "Mods");
+ if (Directory.Exists(melonPath))
+ {
+ melonDirectories.Add(melonPath);
+ ScanFolder(scanType, melonPath, ref melonDirectories, ref userLibDirectories);
+ }
- // Load Melons from Extended Folder
- LoadFolder(dir, true, ref hasWroteLine, ref melonAssemblies);
+ // Add to Directories List
+ melonDirectories.Add(dir);
}
}
-
- // Load Melons from Base Path
- LoadFolder(path, true, ref hasWroteLine, ref melonAssemblies);
}
}
}
\ No newline at end of file
diff --git a/MelonLoader/Melons/MelonHandler.cs b/MelonLoader/Melons/MelonHandler.cs
index 80725eaf7..8abe773fa 100644
--- a/MelonLoader/Melons/MelonHandler.cs
+++ b/MelonLoader/Melons/MelonHandler.cs
@@ -32,91 +32,12 @@ internal static void Setup()
Directory.CreateDirectory(MelonEnvironment.ModsDirectory);
}
- internal static bool firstSpacer = false;
- public static void LoadMelonsFromDirectory(string path) where T : MelonTypeBase
- {
- path = Path.GetFullPath(path);
-
- var loadingMsg = $"Loading {MelonTypeBase.TypeName}s from '{path}'...";
- MelonLogger.WriteSpacer();
- MelonLogger.Msg(loadingMsg);
-
- bool hasWroteLine = false;
-
- var files = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly);
- var melonAssemblies = new List();
- foreach (var f in files)
- {
- if (!hasWroteLine)
- {
- hasWroteLine = true;
- MelonLogger.WriteLine(Color.Magenta);
- }
-
- var asm = MelonAssembly.LoadMelonAssembly(f, false);
- if (asm == null)
- continue;
-
- melonAssemblies.Add(asm);
- }
-
- var melons = new List();
- foreach (var asm in melonAssemblies)
- {
- asm.LoadMelons();
- foreach (var m in asm.LoadedMelons)
- {
- if (m is T t)
- {
- melons.Add(t);
- }
- else
- {
- MelonLogger.Warning($"Failed to load Melon '{m.Info.Name}' from '{path}': The given Melon is a {m.MelonTypeName} and cannot be loaded as a {MelonTypeBase.TypeName}. Make sure it's in the right folder.");
- continue;
- }
- }
- }
-
- if (hasWroteLine)
- MelonLogger.WriteSpacer();
-
- MelonBase.RegisterSorted(melons);
-
- if (hasWroteLine)
- MelonLogger.WriteLine(Color.Magenta);
-
- var count = MelonTypeBase._registeredMelons.Count;
- MelonLogger.Msg($"{count} {MelonTypeBase.TypeName.MakePlural(count)} loaded.");
- if (firstSpacer || (typeof(T) == typeof(MelonMod)))
- MelonLogger.WriteSpacer();
- firstSpacer = true;
- }
-
public static void LoadUserlibs(string path)
- {
- path = Path.GetFullPath(path);
-
- var loadingMsg = $"Loading UserLibs from '{path}'...";
- MelonLogger.WriteSpacer();
- MelonLogger.Msg(loadingMsg);
-
- bool hasWroteLine = false;
- var files = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly);
- foreach (var f in files)
- {
- if (!hasWroteLine)
- {
- hasWroteLine = true;
- MelonLogger.WriteLine(Color.Magenta);
- }
-
- MelonAssembly.LoadMelonAssembly(f, false);
- }
- }
+ => MelonFolderHandler.ScanUserLibs(path);
- public static void LoadMelonFolders(string path) where T : MelonTypeBase
- => MelonFolderHandler.Scan(path);
+ public static void LoadMelonsFromDirectory(string path)
+ where T : MelonTypeBase
+ => MelonFolderHandler.ScanMelons(path);
#region Obsolete Members
///
diff --git a/MelonLoader/Melons/MelonPreprocessor.cs b/MelonLoader/Melons/MelonPreprocessor.cs
new file mode 100644
index 000000000..950971709
--- /dev/null
+++ b/MelonLoader/Melons/MelonPreprocessor.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using Mono.Cecil;
+
+namespace MelonLoader.Melons
+{
+ internal static class MelonPreprocessor
+ {
+ internal static void LoadFolders(List directoryPaths,
+ bool isMelon,
+ ref bool hasWroteLine,
+ ref List melonAssemblies)
+ {
+ // Find All Assemblies
+ Dictionary foundAssemblies = new();
+ foreach (string path in directoryPaths)
+ PreprocessFolder(path, isMelon, ref foundAssemblies);
+
+ // Load from File Paths
+ foreach (var foundFile in foundAssemblies)
+ {
+ // Log
+ if (!hasWroteLine)
+ {
+ hasWroteLine = true;
+ MelonLogger.WriteLine(Color.Magenta);
+ }
+
+ // Load Assembly
+ var asm = MelonAssembly.LoadMelonAssembly(foundFile.Value.Item2, false);
+ if (asm == null)
+ continue;
+
+ // Queue Assembly for Melon Parsing
+ if (isMelon)
+ melonAssemblies.Add(asm);
+ }
+ }
+
+ private static void PreprocessFolder(string path,
+ bool isMelon,
+ ref Dictionary foundAssemblies)
+ {
+ // Validate Path
+ if (!Directory.Exists(path))
+ return;
+
+ // Get DLLs in Directory
+ var files = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly);
+ foreach (var f in files)
+ {
+ // Ignore Native DLLs
+ if (!MelonUtils.IsManagedDLL(f))
+ continue;
+
+ // Load Definition using Cecil
+ AssemblyDefinition asmDef = LoadDefinition(f);
+ if (asmDef == null)
+ continue;
+
+ // Pull Name and Version from AssemblyDefinitionName
+ string name = $"{asmDef.Name.Name}";
+ Version version = new(asmDef.Name.Version.ToString());
+
+ // Dispose of Definition
+ asmDef.Dispose();
+
+ // Check for Existing Version
+ if (foundAssemblies.TryGetValue(name, out (Version, string) existingVersion)
+ && (existingVersion.Item1 >= version))
+ continue;
+
+ // Add File to List
+ foundAssemblies[name] = (version, f);
+ }
+ }
+
+ private static AssemblyDefinition LoadDefinition(string path)
+ {
+ path = Path.GetFullPath(path);
+
+ try
+ {
+ return AssemblyDefinition.ReadAssembly(path);
+ }
+ catch (Exception ex)
+ {
+ MelonLogger.Error($"Failed to load AssemblyDefinition from '{path}':\n{ex}");
+ return null;
+ }
+ }
+ }
+}
diff --git a/MelonLoader/Properties/AssemblyInfo.cs b/MelonLoader/Properties/AssemblyInfo.cs
deleted file mode 100644
index 3277cba2d..000000000
--- a/MelonLoader/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyDescription(MelonLoader.BuildInfo.Description)]
-[assembly: AssemblyCompany(MelonLoader.BuildInfo.Company)]
-[assembly: AssemblyProduct(MelonLoader.BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + MelonLoader.BuildInfo.Author)]
-[assembly: AssemblyTrademark(MelonLoader.BuildInfo.Company)]
-[assembly: Guid("A662769A-B294-434F-83B5-176FC4795334")]
-[assembly: AssemblyVersion(MelonLoader.BuildInfo.Version)]
-[assembly: AssemblyFileVersion(MelonLoader.BuildInfo.Version)]
-[assembly: MelonLoader.PatchShield]
-
-[assembly: InternalsVisibleTo("MelonLoader.NativeHost")]
-[assembly: InternalsVisibleTo("Il2CppAssemblyGenerator")]
-[assembly: InternalsVisibleTo("Il2CppUnityTls")]
-[assembly: InternalsVisibleTo("Il2Cpp")]
-[assembly: InternalsVisibleTo("MelonStartScreen")]
-[assembly: InternalsVisibleTo("EOS")]
\ No newline at end of file
diff --git a/MelonLoader/Properties/BuildInfo.cs b/MelonLoader/Properties/BuildInfo.cs
deleted file mode 100644
index c6ff6b100..000000000
--- a/MelonLoader/Properties/BuildInfo.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace MelonLoader
-{
- public static class BuildInfo
- {
- public const string Name = "MelonLoader";
- public const string Description = "MelonLoader";
- public const string Author = "Lava Gang";
- public const string Company = "discord.gg/2Wn3N2P";
- public const string Version = "0.6.6";
- }
-}
\ No newline at end of file
diff --git a/MelonLoader/Resolver/MelonAssemblyResolver.cs b/MelonLoader/Resolver/MelonAssemblyResolver.cs
index d4062503a..1840ae231 100644
--- a/MelonLoader/Resolver/MelonAssemblyResolver.cs
+++ b/MelonLoader/Resolver/MelonAssemblyResolver.cs
@@ -19,62 +19,83 @@ internal static void Setup()
return;
// Setup Search Directories
- string[] searchdirlist =
- {
+ AddSearchDirectories(
MelonEnvironment.UserLibsDirectory,
MelonEnvironment.PluginsDirectory,
MelonEnvironment.ModsDirectory,
- MelonEnvironment.MelonBaseDirectory,
- MelonEnvironment.GameRootDirectory,
+ (MelonUtils.IsGameIl2Cpp()
+ ? MelonEnvironment.Il2CppAssembliesDirectory
+ : MelonEnvironment.UnityGameManagedDirectory),
MelonEnvironment.OurRuntimeDirectory,
- MelonEnvironment.Il2CppAssembliesDirectory,
- MelonEnvironment.UnityGameManagedDirectory,
- };
- foreach (string path in searchdirlist)
- AddSearchDirectory(path);
-
- ForceResolveRuntime("Mono.Cecil.dll");
- ForceResolveRuntime("MonoMod.exe");
- ForceResolveRuntime("MonoMod.Utils.dll");
- ForceResolveRuntime("MonoMod.RuntimeDetour.dll");
+ MelonEnvironment.GameRootDirectory);
// Setup Redirections
- string[] assembly_list =
- {
- "MelonLoader",
- "MelonLoader.ModHandler",
- };
- Assembly base_assembly = typeof(MelonAssemblyResolver).Assembly;
- foreach (string assemblyName in assembly_list)
- GetAssemblyResolveInfo(assemblyName).Override = base_assembly;
+ OverrideBaseAssembly();
+
+ // Resolve Default Runtime Assemblies
+ ForceResolveRuntime(
+ "Mono.Cecil.dll",
+ "MonoMod.exe",
+ "MonoMod.Utils.dll",
+ "MonoMod.RuntimeDetour.dll");
MelonDebug.Msg("[MelonAssemblyResolver] Setup Successful!");
}
- private static void ForceResolveRuntime(string fileName)
+ private static void OverrideBaseAssembly()
{
- string filePath = Path.Combine(MelonEnvironment.OurRuntimeDirectory, fileName);
- if (!File.Exists(filePath))
- return;
+ Assembly base_assembly = typeof(MelonAssemblyResolver).Assembly;
+ GetAssemblyResolveInfo(base_assembly.GetName().Name).Override = base_assembly;
+ GetAssemblyResolveInfo("MelonLoader").Override = base_assembly;
+ GetAssemblyResolveInfo("MelonLoader.ModHandler").Override = base_assembly;
+ }
- Assembly assembly = null;
- try
+ private static void ForceResolveRuntime(params string[] fileNames)
+ {
+ foreach (string fileName in fileNames)
{
+ string filePath = Path.Combine(MelonEnvironment.OurRuntimeDirectory, fileName);
+ if (!File.Exists(filePath))
+ return;
+
+ Assembly assembly = null;
+ try
+ {
#if NET6_0_OR_GREATER
- assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(filePath);
+ assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(filePath);
#else
assembly = Assembly.LoadFrom(filePath);
#endif
- }
- catch { assembly = null; }
+ }
+ catch { assembly = null; }
- if (assembly == null)
- return;
+ if (assembly == null)
+ return;
- GetAssemblyResolveInfo(Path.GetFileNameWithoutExtension(fileName)).Override = assembly;
+ GetAssemblyResolveInfo(Path.GetFileNameWithoutExtension(fileName)).Override = assembly;
+ }
}
// Search Directories
+
+ public static void AddSearchDirectories(params string[] directories)
+ {
+ foreach (string directory in directories)
+ AddSearchDirectory(directory);
+ }
+
+ public static void AddSearchDirectories(int priority, params string[] directories)
+ {
+ foreach (string directory in directories)
+ AddSearchDirectory(directory, priority);
+ }
+
+ public static void AddSearchDirectories(params (string, int)[] directories)
+ {
+ foreach (var pair in directories)
+ AddSearchDirectory(pair.Item1, pair.Item2);
+ }
+
public static void AddSearchDirectory(string path, int priority = 0)
=> SearchDirectoryManager.Add(path, priority);
public static void RemoveSearchDirectory(string path)
diff --git a/MelonLoader/Semver/SemVersion.cs b/MelonLoader/Semver/SemVersion.cs
index 1b7aec5a2..72bdc9c90 100644
--- a/MelonLoader/Semver/SemVersion.cs
+++ b/MelonLoader/Semver/SemVersion.cs
@@ -337,8 +337,7 @@ public int CompareTo(SemVersion other)
var r = CompareByPrecedence(other);
if (r != 0) return r;
- // If other is null, CompareByPrecedence() returns 1
- return CompareComponent(Build, other.Build);
+ return CompareComponent(Prerelease, other.Prerelease, true);
}
///
diff --git a/MelonLoader/Utils/MelonLogger.cs b/MelonLoader/Utils/MelonLogger.cs
index 117a69372..365dc5fe6 100644
--- a/MelonLoader/Utils/MelonLogger.cs
+++ b/MelonLoader/Utils/MelonLogger.cs
@@ -55,7 +55,12 @@ internal static void Setup()
break;
else
{
- File.Delete(pair.Item1);
+ // This is cursed but better than crashing
+ try
+ {
+ File.Delete(pair.Item1);
+ }
+ catch { }
fileCount--;
}
}
diff --git a/MelonProxy/src/core.rs b/MelonProxy/src/core.rs
index 8f978b0fd..c80f17788 100644
--- a/MelonProxy/src/core.rs
+++ b/MelonProxy/src/core.rs
@@ -59,9 +59,11 @@ pub fn init() -> Result<(), Box> {
return Ok(());
}
- //fix dobby_rs link
- let dobby_path = files::get_dobby_dir(base_dir.clone(), game_dir)?;
- add_dll_directory(dobby_path);
+ if cfg!(target_os = "windows") {
+ //fix dobby_rs link
+ let dobby_path = files::get_dobby_dir(base_dir.clone(), game_dir)?;
+ add_dll_directory(dobby_path);
+ }
let bootstrap_path = files::get_bootstrap_path(&base_dir)?;