From 8dcd55c39d82cd0a5b619755948898be9a97781d Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Mon, 25 Aug 2025 18:10:21 +0300 Subject: [PATCH 01/42] Add compatibility checker with LDM repo --- .../actions/compatibility-check/action.yml | 183 +++++++++++++++++ .../actions/project-build-windows/action.yaml | 96 +++++++++ .github/actions/project-build/action.yaml | 24 +++ .github/workflows/Rocket.API.yaml | 20 ++ .github/workflows/Rocket.Core.yaml | 20 ++ .github/workflows/Rocket.Unturned.yaml | 20 ++ .github/workflows/RocketModFix.yaml | 20 ++ .github/workflows/api-suppressions.xml | 42 ++++ .github/workflows/compatibility-check.yaml | 192 ++++++++++++++++++ 9 files changed, 617 insertions(+) create mode 100644 .github/actions/compatibility-check/action.yml create mode 100644 .github/actions/project-build-windows/action.yaml create mode 100644 .github/workflows/api-suppressions.xml create mode 100644 .github/workflows/compatibility-check.yaml diff --git a/.github/actions/compatibility-check/action.yml b/.github/actions/compatibility-check/action.yml new file mode 100644 index 00000000..bf84e3f6 --- /dev/null +++ b/.github/actions/compatibility-check/action.yml @@ -0,0 +1,183 @@ +name: 'Compatibility Check' +description: 'Check for breaking changes against the original Legally-Distinct-Missile repository' + +inputs: + original-repo: + description: 'Original repository to compare against' + required: false + default: 'SmartlyDressedGames/Legally-Distinct-Missile' + original-branch: + description: 'Branch of original repository to compare against' + required: false + default: 'master' + runtime-version: + description: 'Runtime version for build paths' + required: false + default: 'linux-x64' + fail-on-breaking-changes: + description: 'Whether to fail the workflow if breaking changes are detected' + required: false + default: 'true' + +outputs: + has-breaking-changes: + description: 'Whether breaking changes were detected' + value: ${{ steps.check.outputs.has-breaking-changes }} + compatibility-report: + description: 'Path to the compatibility report' + value: ${{ steps.check.outputs.report-path }} + +runs: + using: 'composite' + steps: + - name: Checkout original repository + uses: actions/checkout@v5 + with: + repository: ${{ inputs.original-repo }} + ref: ${{ inputs.original-branch }} + path: original-repo + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + + - name: Build original repo's Rocket.API + run: | + cd original-repo + dotnet build Rocket/Rocket.API/Rocket.API.csproj --configuration Release --verbosity minimal + shell: bash + + - name: Build original repo's Rocket.Core + run: | + cd original-repo + dotnet build Rocket/Rocket.Core/Rocket.Core.csproj --configuration Release --verbosity minimal + shell: bash + + - name: Build original repo's Rocket.Unturned + run: | + cd original-repo + dotnet build Rocket.Unturned/Rocket.Unturned.csproj --configuration Release --verbosity minimal + shell: bash + + - name: Install API compatibility tools + shell: bash + run: | + dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool + + - name: Run compatibility checks + id: check + shell: bash + run: | + # Create reports directory + mkdir -p compatibility-reports + + # Check Rocket.API compatibility + apicompat \ + --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll \ + --right ./Rocket/Rocket.API/bin/Release/net461/${{ inputs.runtime-version }}/Rocket.API.dll \ + > ./compatibility-reports/api-compat-report.txt 2>&1 || true + + # Check Rocket.Core compatibility + apicompat \ + --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll \ + --right ./Rocket/Rocket.Core/bin/Release/net461/${{ inputs.runtime-version }}/Rocket.Core.dll \ + > ./compatibility-reports/core-compat-report.txt 2>&1 || true + + # Check Rocket.Unturned compatibility + apicompat \ + --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll \ + --right ./Rocket.Unturned/bin/Release/net461/${{ inputs.runtime-version }}/Rocket.Unturned.dll \ + > ./compatibility-reports/unturned-compat-report.txt 2>&1 || true + + # Check for breaking changes + has_breaking_changes=false + + for report in ./compatibility-reports/*.txt; do + if grep -q "Breaking Changes\|Error" "$report"; then + has_breaking_changes=true + break + fi + done + + echo "has-breaking-changes=$has_breaking_changes" >> $GITHUB_OUTPUT + echo "report-path=./compatibility-reports" >> $GITHUB_OUTPUT + + # Create summary report + cat > ./compatibility-reports/summary.md << EOF + # Compatibility Check Summary + + ## Results + - **Breaking Changes Detected**: $has_breaking_changes + - **Check Date**: $(date -u) + - **Original Repository**: ${{ inputs.original-repo }} + - **Original Branch**: ${{ inputs.original-branch }} + + ## Detailed Reports + - [API Compatibility](./api-compat-report.txt) + - [Core Compatibility](./core-compat-report.txt) + - [Unturned Compatibility](./unturned-compat-report.txt) + + ## Recommendations + EOF + + if [ "$has_breaking_changes" = "true" ]; then + cat >> ./compatibility-reports/summary.md << EOF + + ⚠️ **BREAKING CHANGES DETECTED** + + Your changes may break existing plugins. Please review the detailed reports above. + Consider: + 1. Reverting breaking changes if possible + 2. Adding compatibility layers + 3. Documenting migration steps for plugin developers + EOF + else + cat >> ./compatibility-reports/summary.md << EOF + + ✅ **No breaking changes detected** + + Your changes appear to be compatible with the original repository. + Existing plugins should continue to work without modification. + EOF + fi + + - name: Upload compatibility reports + uses: actions/upload-artifact@v4 + with: + name: compatibility-reports + path: ./compatibility-reports + + - name: Comment on PR if breaking changes detected + if: github.event_name == 'pull_request' && steps.check.outputs.has-breaking-changes == 'true' + uses: actions/github-script@v7 + with: + script: | + const workflowRunId = context.runId; + const repoOwner = context.repo.owner; + const repoName = context.repo.repo; + + const comment = `❌ **Breaking changes detected** + + Your changes may break existing plugins. Check the [compatibility reports](https://github.com/${repoOwner}/${repoName}/actions/runs/${workflowRunId}/artifacts) for details. + + ### Detailed Reports + - [API Compatibility Report](./api-compat-report.txt) + - [Core Compatibility Report](./core-compat-report.txt) + - [Unturned Compatibility Report](./unturned-compat-report.txt) + `; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); + + - name: Fail on breaking changes + if: inputs.fail-on-breaking-changes == 'true' && steps.check.outputs.has-breaking-changes == 'true' + shell: bash + run: | + echo "❌ Breaking changes detected! Check the compatibility reports for details." + exit 1 diff --git a/.github/actions/project-build-windows/action.yaml b/.github/actions/project-build-windows/action.yaml new file mode 100644 index 00000000..979fbb3b --- /dev/null +++ b/.github/actions/project-build-windows/action.yaml @@ -0,0 +1,96 @@ +name: 'Project Build Windows' +description: 'Builds RocketModFix projects on Windows runners (for .NET Framework compatibility)' +inputs: + project_path: + description: 'Path to project folder' + required: true + runtime_version: + description: 'Build runtime version default win-x64' + required: false + default: 'win-x64' + nuget_push: + description: 'Push to Nuget on release?' + required: false + default: false + nuget_key: + description: 'NuGet deploy key' + required: false + github_token: + description: 'GitHub token' + required: false +outputs: + version: + description: "Generated version (SemVersion compatible)" + value: ${{ steps.get-version.outputs.version }} + is_prerelease: + description: 'Gets if the version is a prerelease' + value: ${{ steps.check-prerelease.outputs.is_prerelease }} +runs: + using: "composite" + steps: + # Generate semver compatible version from current tag and commit hash + - name: Create version + id: get-version + run: echo "version=$(git describe --tags `git rev-list --tags --max-count=1`)+$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + shell: bash + + - name: Check Prerelease + id: check-prerelease + run: "if ${{ contains(steps.get-version.outputs.version, '-') }}; then + echo is_prerelease=true >> $GITHUB_OUTPUT; + else + echo is_prerelease=false >> $GITHUB_OUTPUT; + fi" + shell: bash + + # Commands that are used multiple times. + # Placed in one place to make sure that the arguments would always be the same + - name: Common commands + id: common-commands + run: | + echo "dotnet-restore=dotnet restore \$PROJECT_PATH --runtime ${{ inputs.runtime_version }}" >> $GITHUB_OUTPUT + echo "dotnet-build=dotnet build \$PROJECT_PATH --configuration Release --no-restore -p:RocketModFixVersion=${{ steps.get-version.outputs.version }} --runtime ${{ inputs.runtime_version }}" >> $GITHUB_OUTPUT + echo "dotnet-test=dotnet test \$PROJECT_PATH --configuration Release --no-restore --no-build --runtime ${{ inputs.runtime_version }}" >> $GITHUB_OUTPUT + shell: bash + + # Install dependencies (this needs to be a separate step from build for caching) + - name: Install dependencies + run: | + ${{ steps.common-commands.outputs.dotnet-restore }} + pwsh -File .github/actions/project-build/run-command-for-every-tests-project.ps1 "$PROJECT_PATH" '${{ steps.common-commands.outputs.dotnet-restore }}' + env: + PROJECT_PATH: ${{ inputs.project_path }} # Used by commands in `common-commands` step + shell: bash + + # Build project + - name: Build + run: | + ${{ steps.common-commands.outputs.dotnet-build }} + pwsh -File .github/actions/project-build/run-command-for-every-tests-project.ps1 "$PROJECT_PATH" '${{ steps.common-commands.outputs.dotnet-build }}' + env: + PROJECT_PATH: ${{ inputs.project_path }} # Used by commands in `common-commands` step + shell: bash + + # Test project + - name: Test + run: | + pwsh -File .github/actions/project-build/run-command-for-every-tests-project.ps1 "$PROJECT_PATH" '${{ steps.common-commands.outputs.dotnet-test }}' + env: + PROJECT_PATH: ${{ inputs.project_path }} # Used by commands in `common-commands` step + shell: bash + + # Push to GitHub packages on each commit and release + - name: Push to NuGet (Nightly) + if: | + inputs.nuget_push == 'true' && (github.event_name == 'push' || + github.event_name == 'create' && github.event.ref_type == 'tag') + run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.github_token }} --skip-duplicate --source https://nuget.pkg.github.com/RocketModFix/index.json; + shell: bash + + # Push to NuGet on each tag, but only if the tag is not a pre-release version + - name: Push to NuGet (Release) + if: | + inputs.nuget_push == 'true' && steps.check-prerelease.outputs.is_prerelease == 'false' && + github.event_name == 'create' && github.event.ref_type == 'tag' + run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.nuget_key }} --skip-duplicate --source https://api.nuget.org/v3/index.json; + shell: bash diff --git a/.github/actions/project-build/action.yaml b/.github/actions/project-build/action.yaml index 452c8b77..d6ceb878 100644 --- a/.github/actions/project-build/action.yaml +++ b/.github/actions/project-build/action.yaml @@ -28,6 +28,28 @@ outputs: runs: using: "composite" steps: + # Install .NET Framework reference assemblies for .NET Framework 4.8 + - name: Install .NET Framework Reference Assemblies + run: | + # Download and install .NET Framework 4.8 reference assemblies from official source + mkdir -p /tmp/net48-refs + curl -L -o /tmp/net48.zip "https://api.nuget.org/v3-flatcontainer/microsoft.netframework.referenceassemblies/1.0.3/microsoft.netframework.referenceassemblies.1.0.3.nupkg" + unzip -q /tmp/net48.zip -d /tmp/net48-refs/ + + # Create the target directory + mkdir -p /usr/share/dotnet/reference-assemblies/microsoft/framework/.netframework/v4.8 + + # Copy reference assemblies to the expected location + if [ -d "/tmp/net48-refs/build/.NETFramework/v4.8" ]; then + cp -r /tmp/net48-refs/build/.NETFramework/v4.8/* /usr/share/dotnet/reference-assemblies/microsoft/framework/.netframework/v4.8/ + elif [ -d "/tmp/net48-refs/ref/net48" ]; then + cp -r /tmp/net48-refs/ref/net48/* /usr/share/dotnet/reference-assemblies/microsoft/framework/.netframework/v4.8/ + fi + + # Clean up + rm -rf /tmp/net48-refs /tmp/net48.zip + shell: bash + # Generate semver compatible version from current tag and commit hash - name: Create version id: get-version @@ -71,6 +93,8 @@ runs: PROJECT_PATH: ${{ inputs.project_path }} # Used by commands in `common-commands` step shell: bash + + # Test project - name: Test run: | diff --git a/.github/workflows/Rocket.API.yaml b/.github/workflows/Rocket.API.yaml index 7e877509..41e75933 100644 --- a/.github/workflows/Rocket.API.yaml +++ b/.github/workflows/Rocket.API.yaml @@ -16,9 +16,29 @@ on: - 'Rocket/Rocket.API/**' jobs: + Compatibility-Check: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-dotnet@v4 + name: Setup .NET + with: + dotnet-version: 8.x + + - name: Check compatibility with original repository + uses: ./.github/actions/compatibility-check + with: + fail-on-breaking-changes: true + build: name: "Rocket.API Build" runs-on: ubuntu-latest + needs: Compatibility-Check steps: - uses: actions/checkout@v5 diff --git a/.github/workflows/Rocket.Core.yaml b/.github/workflows/Rocket.Core.yaml index edf05083..34683f8a 100644 --- a/.github/workflows/Rocket.Core.yaml +++ b/.github/workflows/Rocket.Core.yaml @@ -16,9 +16,29 @@ on: - 'Rocket/Rocket.Core/**' jobs: + Compatibility-Check: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-dotnet@v4 + name: Setup .NET + with: + dotnet-version: 8.x + + - name: Check compatibility with original repository + uses: ./.github/actions/compatibility-check + with: + fail-on-breaking-changes: true + build: name: "Rocket.Core Build" runs-on: ubuntu-latest + needs: Compatibility-Check steps: - uses: actions/checkout@v5 diff --git a/.github/workflows/Rocket.Unturned.yaml b/.github/workflows/Rocket.Unturned.yaml index 8a3916a5..eb1d23e9 100644 --- a/.github/workflows/Rocket.Unturned.yaml +++ b/.github/workflows/Rocket.Unturned.yaml @@ -16,9 +16,29 @@ on: - 'Rocket.Unturned/**' jobs: + Compatibility-Check: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-dotnet@v4 + name: Setup .NET + with: + dotnet-version: 8.x + + - name: Check compatibility with original repository + uses: ./.github/actions/compatibility-check + with: + fail-on-breaking-changes: true + build: name: "Rocket.Unturned Build" runs-on: ubuntu-latest + needs: Compatibility-Check steps: - uses: actions/checkout@v5 diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index c1df839d..a56174d5 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -19,8 +19,28 @@ on: - 'Rocket.Unturned/**' jobs: + Compatibility-Check: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-dotnet@v4 + name: Setup .NET + with: + dotnet-version: 8.x + + - name: Check compatibility with original repository + uses: ./.github/actions/compatibility-check + with: + fail-on-breaking-changes: true + Build: runs-on: ubuntu-latest + needs: Compatibility-Check steps: - name: Checkout code diff --git a/.github/workflows/api-suppressions.xml b/.github/workflows/api-suppressions.xml new file mode 100644 index 00000000..2694b93b --- /dev/null +++ b/.github/workflows/api-suppressions.xml @@ -0,0 +1,42 @@ + + + + + + CP0003 + Rocket.API, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll + ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll + + + + CP0003 + Rocket.Core, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll + ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll + + + + CP0003 + Rocket.Unturned, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll + ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll + + + + + CP0001 + T:Rocket.Unturned.Commands.CommandCompass + ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll + ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll + + + + + CP0021 + M:Rocket.Unturned.Player.UnturnedPlayer.GetComponent``1``0:!:UnityEngine.Component + ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll + ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll + + + diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml new file mode 100644 index 00000000..d0fc44e3 --- /dev/null +++ b/.github/workflows/compatibility-check.yaml @@ -0,0 +1,192 @@ +name: Compatibility-Check + +on: + pull_request: + branches: [ master ] + push: + branches: [ master ] + workflow_dispatch: + schedule: + - cron: "0 3 * * *" # every day at 03:00 UTC + +jobs: + api-compatibility: + name: API Compatibility Check + runs-on: windows-latest # yes, we need windows, cause can't build LDM on Linux, it can't install .NET 4.8. + + steps: + - name: Checkout current fork + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Checkout original repository + uses: actions/checkout@v5 + with: + repository: SmartlyDressedGames/Legally-Distinct-Missile + path: original-repo + fetch-depth: 0 + + - uses: actions/setup-dotnet@v4 + name: Setup .NET + with: + dotnet-version: 8.x + + - name: Build current fork (RocketModFix) + run: | + dotnet restore Rocket/Rocket.API/Rocket.API.csproj + dotnet restore Rocket/Rocket.Core/Rocket.Core.csproj + dotnet restore Rocket.Unturned/Rocket.Unturned.csproj + dotnet build Rocket/Rocket.API/Rocket.API.csproj --configuration Release --no-restore + dotnet build Rocket/Rocket.Core/Rocket.Core.csproj --configuration Release --no-restore + dotnet build Rocket.Unturned/Rocket.Unturned.csproj --configuration Release --no-restore + + - name: Build original repository (Legally-Distinct-Missile) + run: | + cd original-repo + dotnet build Rocket/Rocket.API/Rocket.API.csproj --configuration Release --verbosity minimal + dotnet build Rocket/Rocket.Core/Rocket.Core.csproj --configuration Release --verbosity minimal + dotnet build Rocket.Unturned/Rocket.Unturned.csproj --configuration Release --verbosity minimal + + - name: Verify assemblies exist + shell: cmd + run: | + echo "=== Checking if assemblies exist ===" + if exist "Rocket\Rocket.API\bin\Release\net461\Rocket.API.dll" ( + echo "✅ Rocket.API.dll exists" + ) else ( + echo "❌ Rocket.API.dll not found" + dir Rocket\Rocket.API\bin\Release\net461\ + exit /b 1 + ) + + if exist "Rocket\Rocket.Core\bin\Release\net461\Rocket.Core.dll" ( + echo "✅ Rocket.Core.dll exists" + ) else ( + echo "❌ Rocket.Core.dll not found" + dir Rocket\Rocket.Core\bin\Release\net461\ + exit /b 1 + ) + + if exist "Rocket.Unturned\bin\Release\net461\Rocket.Unturned.dll" ( + echo "✅ Rocket.Unturned.dll exists" + ) else ( + echo "❌ Rocket.Unturned.dll not found" + dir Rocket.Unturned\bin\Release\net461\ + exit /b 1 + ) + + if exist "original-repo\Rocket\Rocket.API\bin\Release\Rocket.API.dll" ( + echo "✅ Original Rocket.API.dll exists" + ) else ( + echo "❌ Original Rocket.API.dll not found" + dir original-repo\Rocket\Rocket.API\bin\Release\ + exit /b 1 + ) + + if exist "original-repo\Rocket\Rocket.Core\bin\Release\Rocket.Core.dll" ( + echo "✅ Original Rocket.Core.dll exists" + ) else ( + echo "❌ Original Rocket.Core.dll not found" + dir original-repo\Rocket\Rocket.Core\bin\Release\ + exit /b 1 + ) + + if exist "original-repo\Rocket.Unturned\bin\Release\Rocket.Unturned.dll" ( + echo "✅ Original Rocket.Unturned.dll exists" + ) else ( + echo "❌ Original Rocket.Unturned.dll not found" + dir original-repo\Rocket.Unturned\bin\Release\ + exit /b 1 + ) + + - name: Install API compatibility tools + run: | + dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool + + - name: Copy suppression file + run: | + copy .github\workflows\api-suppressions.xml api-suppressions.xml + + - name: Generate debug suppression file + shell: cmd + run: | + echo "Generating debug suppression file for all breaking changes..." + apicompat ^ + --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll ^ + --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll ^ + --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll ^ + --right ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll ^ + --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll ^ + --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll ^ + --generate-suppression-file ^ + --suppression-output-file ./debug-api-suppressions.xml + + echo "=== GENERATED SUPPRESSION FILE ===" + type debug-api-suppressions.xml + echo. + echo "=== END OF GENERATED FILE ===" + + - name: Generate baseline report + shell: cmd + run: | + apicompat --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll --right ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll > ./api-compat-baseline.txt 2>&1 || ( + echo "Baseline generated with differences" + ) + + - name: Check API compatibility + shell: cmd + run: | + apicompat --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll --right ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll --suppression-file ./api-suppressions.xml > ./api-compat-report.txt 2>&1 || ( + echo "❌ API compatibility check failed - breaking changes detected!" + type api-compat-report.txt + exit /b 1 + ) + echo "✅ API compatibility check passed" + + - name: Upload compatibility reports + uses: actions/upload-artifact@v4 + with: + name: api-compatibility-reports + path: | + ./api-compat-report.txt + ./api-compat-baseline.txt + ./api-suppressions.xml + + - name: Analyze compatibility reports + shell: cmd + run: | + echo "=== BASELINE REPORT (All Changes Detected) ===" + type api-compat-baseline.txt + echo. + echo. + echo. + echo "=== SUPPRESSED REPORT (After Suppression) ===" + type api-compat-report.txt + echo. + + REM Check for any remaining breaking changes after suppression + findstr /c:"API breaking changes found" api-compat-report.txt > nul + if %errorlevel% equ 0 ( + echo "❌ BREAKING CHANGES DETECTED!" + type api-compat-report.txt + exit /b 1 + ) + + findstr /c:"APICompat ran successfully without finding any breaking changes" api-compat-report.txt > nul + if %errorlevel% equ 0 ( + echo "✅ No breaking changes detected" + echo "Note: Expected differences have been suppressed" + exit /b 0 + ) + + echo "⚠️ Unexpected report output!" + exit /b 1 + + workflow-keepalive: + if: github.event_name == 'schedule' + runs-on: ubuntu-latest + permissions: + actions: write + steps: + - uses: liskin/gh-workflow-keepalive@v1 \ No newline at end of file From 3a92a7f720d0483543a18d54aa06e57997cd2b74 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Mon, 25 Aug 2025 18:14:36 +0300 Subject: [PATCH 02/42] Note in README about #126 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 290e65fc..d8906769 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ We're not planning to make any breaking changes with API. - [x] Update MSBuild to the `Microsoft.NET.Sdk`, because current MSBuild in RocketMod is outdated and its hard to support and understand what's going on inside. - [x] RocketMod NuGet Package containing all required libraries for RockeMod API usage. - [x] CI/CD and nightly builds with RocketMod .dlls. +- [x] Breaking changes detector ([see #126](https://github.com/RocketModFix/RocketModFix/issues/126)). - [x] Automatic Release on Tag creation (with RocketMod Module). - [x] Rocket.Unturned.Module Artifacts on PR. - [x] Rocket.Unturned NuGet Package. From 3c209233510f262507b9c99c4da1e67ef8b1fdcf Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Mon, 25 Aug 2025 19:19:25 +0300 Subject: [PATCH 03/42] Fix compatibility check CI --- .github/workflows/compatibility-check.yaml | 75 ++++++++-------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index d0fc44e3..042bf3e7 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -104,14 +104,14 @@ jobs: run: | dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool - - name: Copy suppression file + - name: Copy suppression file from repository run: | copy .github\workflows\api-suppressions.xml api-suppressions.xml - - name: Generate debug suppression file + - name: Generate suppression file for all breaking changes shell: cmd run: | - echo "Generating debug suppression file for all breaking changes..." + echo "Generating suppression file for all breaking changes..." apicompat ^ --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll ^ --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll ^ @@ -120,68 +120,43 @@ jobs: --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll ^ --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll ^ --generate-suppression-file ^ - --suppression-output-file ./debug-api-suppressions.xml + --suppression-output-file ./generated-api-suppressions.xml echo "=== GENERATED SUPPRESSION FILE ===" - type debug-api-suppressions.xml + type generated-api-suppressions.xml echo. echo "=== END OF GENERATED FILE ===" - - name: Generate baseline report - shell: cmd - run: | - apicompat --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll --right ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll > ./api-compat-baseline.txt 2>&1 || ( - echo "Baseline generated with differences" - ) - - - name: Check API compatibility + - name: Upload generated suppression file + uses: actions/upload-artifact@v4 + with: + name: generated-api-suppressions + path: ./generated-api-suppressions.xml + + - name: Check API compatibility with repository suppressions shell: cmd run: | - apicompat --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll --right ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll --suppression-file ./api-suppressions.xml > ./api-compat-report.txt 2>&1 || ( + echo "Checking API compatibility using repository suppression file..." + apicompat ^ + --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll ^ + --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll ^ + --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll ^ + --right ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll ^ + --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll ^ + --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll ^ + --suppression-file ./api-suppressions.xml > ./api-compat-report.txt 2>&1 || ( echo "❌ API compatibility check failed - breaking changes detected!" + echo "Download the generated-api-suppressions artifact and add needed suppressions to .github/workflows/api-suppressions.xml" type api-compat-report.txt exit /b 1 ) echo "✅ API compatibility check passed" - - name: Upload compatibility reports + - name: Upload compatibility report uses: actions/upload-artifact@v4 with: - name: api-compatibility-reports - path: | - ./api-compat-report.txt - ./api-compat-baseline.txt - ./api-suppressions.xml - - - name: Analyze compatibility reports - shell: cmd - run: | - echo "=== BASELINE REPORT (All Changes Detected) ===" - type api-compat-baseline.txt - echo. - echo. - echo. - echo "=== SUPPRESSED REPORT (After Suppression) ===" - type api-compat-report.txt - echo. - - REM Check for any remaining breaking changes after suppression - findstr /c:"API breaking changes found" api-compat-report.txt > nul - if %errorlevel% equ 0 ( - echo "❌ BREAKING CHANGES DETECTED!" - type api-compat-report.txt - exit /b 1 - ) - - findstr /c:"APICompat ran successfully without finding any breaking changes" api-compat-report.txt > nul - if %errorlevel% equ 0 ( - echo "✅ No breaking changes detected" - echo "Note: Expected differences have been suppressed" - exit /b 0 - ) - - echo "⚠️ Unexpected report output!" - exit /b 1 + name: api-compatibility-report + path: ./api-compat-report.txt workflow-keepalive: if: github.event_name == 'schedule' From 03c2be38c31703b149cd9eb9d3b67876cf279c0c Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Wed, 27 Aug 2025 19:21:35 +0300 Subject: [PATCH 04/42] Fix compatibility checker --- .github/workflows/api-suppressions.xml | 36 ++--- .../workflows/compare-api-suppressions.ps1 | 30 ++++ .github/workflows/compatibility-check.yaml | 129 +++++++----------- 3 files changed, 95 insertions(+), 100 deletions(-) create mode 100644 .github/workflows/compare-api-suppressions.ps1 diff --git a/.github/workflows/api-suppressions.xml b/.github/workflows/api-suppressions.xml index 2694b93b..a2c6106f 100644 --- a/.github/workflows/api-suppressions.xml +++ b/.github/workflows/api-suppressions.xml @@ -1,42 +1,34 @@ + - - + + CP0001 + T:Rocket.Unturned.Commands.CommandCompass + ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll + ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll + + + CP0003 + Rocket.Unturned, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll + ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll + CP0003 Rocket.API, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll - CP0003 Rocket.Core, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll - - - CP0003 - Rocket.Unturned, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null - ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll - ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll - - - - - CP0001 - T:Rocket.Unturned.Commands.CommandCompass - ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll - ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll - - - CP0021 M:Rocket.Unturned.Player.UnturnedPlayer.GetComponent``1``0:!:UnityEngine.Component ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll - - + \ No newline at end of file diff --git a/.github/workflows/compare-api-suppressions.ps1 b/.github/workflows/compare-api-suppressions.ps1 new file mode 100644 index 00000000..9eab8fe9 --- /dev/null +++ b/.github/workflows/compare-api-suppressions.ps1 @@ -0,0 +1,30 @@ +param( + [string]$RepoFile = "api-suppressions.xml", + [string]$GeneratedFile = "generated-api-suppressions.xml" +) + +Write-Host "Comparing suppression files..." + +# Check files exist +if (!(Test-Path $RepoFile)) { + Write-Host "❌ Repository file not found: $RepoFile" -ForegroundColor Red + exit 1 +} + +if (!(Test-Path $GeneratedFile)) { + Write-Host "❌ Generated file not found: $GeneratedFile" -ForegroundColor Red + exit 1 +} + +# Simple file comparison +$repoContent = Get-Content $RepoFile -Raw +$generatedContent = Get-Content $GeneratedFile -Raw + +if ($repoContent.Trim() -ne $generatedContent.Trim()) { + Write-Host "❌ Files are different!" -ForegroundColor Red + Write-Host "Please either fix breaking change or update $RepoFile with the content from $GeneratedFile if this is not important breaking change" -ForegroundColor Red + exit 1 +} else { + Write-Host "✅ Files match!" -ForegroundColor Green + exit 0 +} \ No newline at end of file diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index 042bf3e7..0901e169 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -10,22 +10,19 @@ on: - cron: "0 3 * * *" # every day at 03:00 UTC jobs: - api-compatibility: - name: API Compatibility Check - runs-on: windows-latest # yes, we need windows, cause can't build LDM on Linux, it can't install .NET 4.8. + build-and-generate: + name: Build and Generate Suppressions + runs-on: windows-latest steps: - name: Checkout current fork uses: actions/checkout@v5 - with: - fetch-depth: 0 - name: Checkout original repository uses: actions/checkout@v5 with: repository: SmartlyDressedGames/Legally-Distinct-Missile path: original-repo - fetch-depth: 0 - uses: actions/setup-dotnet@v4 name: Setup .NET @@ -52,66 +49,38 @@ jobs: shell: cmd run: | echo "=== Checking if assemblies exist ===" - if exist "Rocket\Rocket.API\bin\Release\net461\Rocket.API.dll" ( - echo "✅ Rocket.API.dll exists" - ) else ( - echo "❌ Rocket.API.dll not found" - dir Rocket\Rocket.API\bin\Release\net461\ - exit /b 1 - ) - - if exist "Rocket\Rocket.Core\bin\Release\net461\Rocket.Core.dll" ( - echo "✅ Rocket.Core.dll exists" - ) else ( - echo "❌ Rocket.Core.dll not found" - dir Rocket\Rocket.Core\bin\Release\net461\ - exit /b 1 - ) - - if exist "Rocket.Unturned\bin\Release\net461\Rocket.Unturned.dll" ( - echo "✅ Rocket.Unturned.dll exists" - ) else ( - echo "❌ Rocket.Unturned.dll not found" - dir Rocket.Unturned\bin\Release\net461\ - exit /b 1 - ) - - if exist "original-repo\Rocket\Rocket.API\bin\Release\Rocket.API.dll" ( - echo "✅ Original Rocket.API.dll exists" - ) else ( - echo "❌ Original Rocket.API.dll not found" - dir original-repo\Rocket\Rocket.API\bin\Release\ - exit /b 1 - ) - if exist "original-repo\Rocket\Rocket.Core\bin\Release\Rocket.Core.dll" ( - echo "✅ Original Rocket.Core.dll exists" - ) else ( - echo "❌ Original Rocket.Core.dll not found" - dir original-repo\Rocket\Rocket.Core\bin\Release\ - exit /b 1 - ) + REM Define list of required assemblies + set "assemblies=" + set "assemblies=%assemblies%Rocket\Rocket.API\bin\Release\net461\Rocket.API.dll " + set "assemblies=%assemblies%Rocket\Rocket.Core\bin\Release\net461\Rocket.Core.dll " + set "assemblies=%assemblies%Rocket.Unturned\bin\Release\net461\Rocket.Unturned.dll " + set "assemblies=%assemblies%original-repo\Rocket\Rocket.API\bin\Release\Rocket.API.dll " + set "assemblies=%assemblies%original-repo\Rocket\Rocket.Core\bin\Release\Rocket.Core.dll " + set "assemblies=%assemblies%original-repo\Rocket.Unturned\bin\Release\Rocket.Unturned.dll" - if exist "original-repo\Rocket.Unturned\bin\Release\Rocket.Unturned.dll" ( - echo "✅ Original Rocket.Unturned.dll exists" - ) else ( - echo "❌ Original Rocket.Unturned.dll not found" - dir original-repo\Rocket.Unturned\bin\Release\ - exit /b 1 + REM Check each assembly + for %%f in (%assemblies%) do ( + if exist "%%f" ( + echo "✅ %%~nxf exists" + ) else ( + echo "❌ %%~nxf not found" + echo "Expected path: %%f" + dir "%%~dpf" 2>nul || echo "Directory does not exist" + exit /b 1 + ) ) - name: Install API compatibility tools run: | dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool - - name: Copy suppression file from repository - run: | - copy .github\workflows\api-suppressions.xml api-suppressions.xml - - name: Generate suppression file for all breaking changes + id: generate shell: cmd run: | echo "Generating suppression file for all breaking changes..." + apicompat ^ --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll ^ --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll ^ @@ -121,37 +90,40 @@ jobs: --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll ^ --generate-suppression-file ^ --suppression-output-file ./generated-api-suppressions.xml - - echo "=== GENERATED SUPPRESSION FILE ===" - type generated-api-suppressions.xml - echo. - echo "=== END OF GENERATED FILE ===" - name: Upload generated suppression file uses: actions/upload-artifact@v4 with: name: generated-api-suppressions path: ./generated-api-suppressions.xml + retention-days: 30 + + api-compatibility: + name: API Compatibility Check + runs-on: windows-latest + needs: build-and-generate + + steps: + - name: Checkout repository + uses: actions/checkout@v5 - - name: Check API compatibility with repository suppressions - shell: cmd + - name: Download generated suppression file + uses: actions/download-artifact@v4 + with: + name: generated-api-suppressions + path: ./ + + - name: Copy suppression file from repository run: | - echo "Checking API compatibility using repository suppression file..." - apicompat ^ - --left ./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll ^ - --right ./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll ^ - --left ./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll ^ - --right ./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll ^ - --left ./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll ^ - --right ./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll ^ - --suppression-file ./api-suppressions.xml > ./api-compat-report.txt 2>&1 || ( - echo "❌ API compatibility check failed - breaking changes detected!" - echo "Download the generated-api-suppressions artifact and add needed suppressions to .github/workflows/api-suppressions.xml" - type api-compat-report.txt - exit /b 1 - ) - echo "✅ API compatibility check passed" - + copy .github\workflows\api-suppressions.xml api-suppressions.xml + + - name: Compare suppression files + shell: pwsh + run: | + .\.github\workflows\compare-api-suppressions.ps1 ` + -RepoFile ".github\workflows\api-suppressions.xml" ` + -GeneratedFile "generated-api-suppressions.xml" + - name: Upload compatibility report uses: actions/upload-artifact@v4 with: @@ -164,4 +136,5 @@ jobs: permissions: actions: write steps: - - uses: liskin/gh-workflow-keepalive@v1 \ No newline at end of file + - uses: liskin/gh-workflow-keepalive@v1 + \ No newline at end of file From 26d9b75d3aee771c55aed7adb13c12c7338a0a67 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Wed, 27 Aug 2025 23:21:40 +0300 Subject: [PATCH 05/42] Fix ApiCompat usage, it always returns 0 instead of 1 --- .github/workflows/api-suppressions.xml | 2 +- .../workflows/compare-api-suppressions.ps1 | 30 -------- .github/workflows/compatibility-check.yaml | 75 ++++++++++--------- 3 files changed, 42 insertions(+), 65 deletions(-) delete mode 100644 .github/workflows/compare-api-suppressions.ps1 diff --git a/.github/workflows/api-suppressions.xml b/.github/workflows/api-suppressions.xml index a2c6106f..70d5802f 100644 --- a/.github/workflows/api-suppressions.xml +++ b/.github/workflows/api-suppressions.xml @@ -1,4 +1,4 @@ - + diff --git a/.github/workflows/compare-api-suppressions.ps1 b/.github/workflows/compare-api-suppressions.ps1 deleted file mode 100644 index 9eab8fe9..00000000 --- a/.github/workflows/compare-api-suppressions.ps1 +++ /dev/null @@ -1,30 +0,0 @@ -param( - [string]$RepoFile = "api-suppressions.xml", - [string]$GeneratedFile = "generated-api-suppressions.xml" -) - -Write-Host "Comparing suppression files..." - -# Check files exist -if (!(Test-Path $RepoFile)) { - Write-Host "❌ Repository file not found: $RepoFile" -ForegroundColor Red - exit 1 -} - -if (!(Test-Path $GeneratedFile)) { - Write-Host "❌ Generated file not found: $GeneratedFile" -ForegroundColor Red - exit 1 -} - -# Simple file comparison -$repoContent = Get-Content $RepoFile -Raw -$generatedContent = Get-Content $GeneratedFile -Raw - -if ($repoContent.Trim() -ne $generatedContent.Trim()) { - Write-Host "❌ Files are different!" -ForegroundColor Red - Write-Host "Please either fix breaking change or update $RepoFile with the content from $GeneratedFile if this is not important breaking change" -ForegroundColor Red - exit 1 -} else { - Write-Host "✅ Files match!" -ForegroundColor Green - exit 0 -} \ No newline at end of file diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index 0901e169..22cd8739 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -10,8 +10,8 @@ on: - cron: "0 3 * * *" # every day at 03:00 UTC jobs: - build-and-generate: - name: Build and Generate Suppressions + api-compatibility-check: + name: API Compatibility Check runs-on: windows-latest steps: @@ -24,8 +24,8 @@ jobs: repository: SmartlyDressedGames/Legally-Distinct-Missile path: original-repo - - uses: actions/setup-dotnet@v4 - name: Setup .NET + - name: Setup dotnet + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.x @@ -72,8 +72,7 @@ jobs: ) - name: Install API compatibility tools - run: | - dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool + run: dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool - name: Generate suppression file for all breaking changes id: generate @@ -97,38 +96,46 @@ jobs: name: generated-api-suppressions path: ./generated-api-suppressions.xml retention-days: 30 - - api-compatibility: - name: API Compatibility Check - runs-on: windows-latest - needs: build-and-generate - - steps: - - name: Checkout repository - uses: actions/checkout@v5 - - name: Download generated suppression file - uses: actions/download-artifact@v4 - with: - name: generated-api-suppressions - path: ./ - - - name: Copy suppression file from repository - run: | - copy .github\workflows\api-suppressions.xml api-suppressions.xml - - - name: Compare suppression files + - name: Check API compatibility with manual suppressions shell: pwsh run: | - .\.github\workflows\compare-api-suppressions.ps1 ` - -RepoFile ".github\workflows\api-suppressions.xml" ` - -GeneratedFile "generated-api-suppressions.xml" + Write-Host "Checking API compatibility using manual suppression file..." + + # Run apicompat and capture output directly to variables + $output = & apicompat @( + "--left", "./original-repo/Rocket/Rocket.API/bin/Release/Rocket.API.dll", + "--right", "./Rocket/Rocket.API/bin/Release/net461/Rocket.API.dll", + "--left", "./original-repo/Rocket/Rocket.Core/bin/Release/Rocket.Core.dll", + "--right", "./Rocket/Rocket.Core/bin/Release/net461/Rocket.Core.dll", + "--left", "./original-repo/Rocket.Unturned/bin/Release/Rocket.Unturned.dll", + "--right", "./Rocket.Unturned/bin/Release/net461/Rocket.Unturned.dll", + "--suppression-file", ".github\workflows\api-suppressions.xml" + ) 2>&1 + + $exitCode = $LASTEXITCODE + $fullOutput = $output | Out-String + + # Always show apicompat output + Write-Host "=== apicompat output ===" + Write-Host $fullOutput + Write-Host "=== end of apicompat output ===" + Write-Host "Exit code: $exitCode" - - name: Upload compatibility report - uses: actions/upload-artifact@v4 - with: - name: api-compatibility-report - path: ./api-compat-report.txt + # Check output content instead of exit code, because for some reason it always returns 0, instead of 1! + if ($fullOutput -match "APICompat ran successfully without finding any breaking changes\.") { + Write-Host "✅ API compatibility check passed!" -ForegroundColor Green + Write-Host "No breaking changes found." + } elseif ($fullOutput -match "API breaking changes found") { + Write-Host "❌ API compatibility check failed!" -ForegroundColor Red + Write-Host "Breaking changes detected that are not covered by your suppression file." + Write-Host "Please either fix breaking change or update .github/workflows/api-suppressions.xml with generated-api-suppressions.xml from artifacts and commit if it's not important breaking change." + exit 1 + } else { + Write-Host "❌ API compatibility check failed!" -ForegroundColor Red + Write-Host "Unexpected output from apicompat. Please check the output above." + exit 1 + } workflow-keepalive: if: github.event_name == 'schedule' From e34084a6abc7695148eefaeefef0ee1370366e5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 10:17:46 +0000 Subject: [PATCH 06/42] github-actions(deps): bump actions/setup-dotnet from 4 to 5 Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4 to 5. - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](https://github.com/actions/setup-dotnet/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/Rocket.API.yaml | 4 ++-- .github/workflows/Rocket.Core.yaml | 4 ++-- .github/workflows/Rocket.Unturned.yaml | 4 ++-- .github/workflows/RocketModFix.yaml | 4 ++-- .github/workflows/compatibility-check.yaml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/Rocket.API.yaml b/.github/workflows/Rocket.API.yaml index 41e75933..36a822bf 100644 --- a/.github/workflows/Rocket.API.yaml +++ b/.github/workflows/Rocket.API.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x @@ -45,7 +45,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/Rocket.Core.yaml b/.github/workflows/Rocket.Core.yaml index 34683f8a..1c8304cd 100644 --- a/.github/workflows/Rocket.Core.yaml +++ b/.github/workflows/Rocket.Core.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x @@ -45,7 +45,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/Rocket.Unturned.yaml b/.github/workflows/Rocket.Unturned.yaml index eb1d23e9..c738a556 100644 --- a/.github/workflows/Rocket.Unturned.yaml +++ b/.github/workflows/Rocket.Unturned.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x @@ -45,7 +45,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index a56174d5..c56c81cd 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -28,7 +28,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x @@ -48,7 +48,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index 22cd8739..27163b0f 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -25,7 +25,7 @@ jobs: path: original-repo - name: Setup dotnet - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: 8.x From e901633f14ff50ef782b1fe792f65773187adc3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 10:17:51 +0000 Subject: [PATCH 07/42] github-actions(deps): bump ncipollo/release-action from 1.18.0 to 1.20.0 Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.18.0 to 1.20.0. - [Release notes](https://github.com/ncipollo/release-action/releases) - [Commits](https://github.com/ncipollo/release-action/compare/v1.18.0...v1.20.0) --- updated-dependencies: - dependency-name: ncipollo/release-action dependency-version: 1.20.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/RocketModFix.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index a56174d5..3ecba571 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -96,7 +96,7 @@ jobs: - name: Create Release if: github.event_name == 'create' && github.event.ref_type == 'tag' - uses: ncipollo/release-action@v1.18.0 + uses: ncipollo/release-action@v1.20.0 with: name: RocketModFix Release v${{ steps.auto-installer-build.outputs.version }} tag: ${{ steps.auto-installer-build.outputs.version }} From 2768b3eebcb01467a43a9550f7a80474ef354aac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Sep 2025 10:27:38 +0000 Subject: [PATCH 08/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.25.7.2 to 3.25.8.2 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.25.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index b0cbef7c..0dfa9eda 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index e775a643..9b96ef1e 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index e8967341..6dd13776 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From d10c9de79f7d7acbab7bbfd272b884d6ad711c39 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 13 Sep 2025 13:48:29 +0300 Subject: [PATCH 09/42] Update dependabot.yml --- .github/dependabot.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8095c401..4fb4812f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,8 +7,7 @@ updates: - package-ecosystem: "nuget" directory: "/" schedule: - interval: "weekly" - day: "monday" + interval: "daily" time: "09:00" timezone: "UTC" open-pull-requests-limit: 10 @@ -31,8 +30,7 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" - day: "monday" + interval: "daily" time: "09:00" timezone: "UTC" open-pull-requests-limit: 5 From 3d3cf9a874c84b0c105c2333153fdfb56bc2296d Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 13 Sep 2025 20:15:44 +0300 Subject: [PATCH 10/42] Implement plans from README for Rocket.AutoInstaller --- .../Installation/ExtrasInstaller.cs | 89 ++++++ .../Installation/GenericUriDownloader.cs | 46 +++ .../Installation/GitHubActionsDownloader.cs | 96 ++++++ .../Installation/GitHubAsset.cs | 64 ++++ .../Installation/GitHubRelease.cs | 32 -- .../Installation/Installer.cs | 119 ++++++-- .../Installation/LocalInstaller.cs | 275 ++++++++++++++++++ .../Installation/PathValidator.cs | 140 +++++++++ .../Installation/ReleaseCache.cs | 115 ++++++++ .../Installation/RetryHelper.cs | 67 +++++ Rocket.AutoInstaller/Module.cs | 36 ++- Rocket.AutoInstaller/README.md | 95 +++++- Rocket.AutoInstaller/config.json | 4 +- 13 files changed, 1091 insertions(+), 87 deletions(-) create mode 100644 Rocket.AutoInstaller/Installation/ExtrasInstaller.cs create mode 100644 Rocket.AutoInstaller/Installation/GenericUriDownloader.cs create mode 100644 Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs delete mode 100644 Rocket.AutoInstaller/Installation/GitHubRelease.cs create mode 100644 Rocket.AutoInstaller/Installation/LocalInstaller.cs create mode 100644 Rocket.AutoInstaller/Installation/PathValidator.cs create mode 100644 Rocket.AutoInstaller/Installation/ReleaseCache.cs create mode 100644 Rocket.AutoInstaller/Installation/RetryHelper.cs diff --git a/Rocket.AutoInstaller/Installation/ExtrasInstaller.cs b/Rocket.AutoInstaller/Installation/ExtrasInstaller.cs new file mode 100644 index 00000000..88188fd1 --- /dev/null +++ b/Rocket.AutoInstaller/Installation/ExtrasInstaller.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; +using System.IO; +using System.IO.Compression; +using System.Linq; +using SDG.Unturned; +using UnityEngine.Networking; + +namespace Rocket.AutoInstaller.Installation +{ + public static class ExtrasInstaller + { + public static IEnumerator InstallRocketFromExtras() + { + CommandWindow.Log("Installing from Extras..."); + + var extrasPath = Path.Combine(ReadWrite.PATH, "Extras"); + if (!Directory.Exists(extrasPath)) + { + CommandWindow.LogError("Extras directory not found"); + yield break; + } + + var moduleZipPath = Path.Combine(extrasPath, "Rocket.Unturned.Module.zip"); + if (!File.Exists(moduleZipPath)) + { + CommandWindow.LogError("Rocket.Unturned.Module.zip not found in Extras"); + yield break; + } + + CommandWindow.Log($"Found module: {moduleZipPath}"); + + var modulesPath = Path.Combine(ReadWrite.PATH, "Modules"); + var targetPath = Path.Combine(modulesPath, "Rocket.Unturned.Module.zip"); + + try + { + File.Copy(moduleZipPath, targetPath, true); + CommandWindow.Log("Copied module to Modules directory"); + } + catch (Exception ex) + { + CommandWindow.LogError($"Failed to copy module: {ex}"); + yield break; + } + + ExtractModule(targetPath, modulesPath); + } + + private static void ExtractModule(string zipPath, string extractPath) + { + try + { + using var archive = ZipFile.OpenRead(zipPath); + var extractDir = Path.Combine(extractPath, "Rocket.Unturned"); + + if (Directory.Exists(extractDir)) + { + Directory.Delete(extractDir, true); + } + Directory.CreateDirectory(extractDir); + foreach (var entry in archive.Entries) + { + if (string.IsNullOrEmpty(entry.Name)) + continue; + + var entryPath = Path.Combine(extractDir, entry.FullName); + var entryDir = Path.GetDirectoryName(entryPath); + + if (!string.IsNullOrEmpty(entryDir) && !Directory.Exists(entryDir)) + { + Directory.CreateDirectory(entryDir); + } + + if (!string.IsNullOrEmpty(entry.Name)) + { + entry.ExtractToFile(entryPath, true); + } + } + + File.Delete(zipPath); + } + catch (Exception ex) + { + CommandWindow.LogError($"Failed to extract: {ex}"); + } + } + } +} diff --git a/Rocket.AutoInstaller/Installation/GenericUriDownloader.cs b/Rocket.AutoInstaller/Installation/GenericUriDownloader.cs new file mode 100644 index 00000000..90d5a619 --- /dev/null +++ b/Rocket.AutoInstaller/Installation/GenericUriDownloader.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections; +using System.IO; +using SDG.Unturned; +using UnityEngine.Networking; + +namespace Rocket.AutoInstaller.Installation +{ + public static class GenericUriDownloader + { + public static bool IsUri(string path) + { + if (string.IsNullOrWhiteSpace(path)) + return false; + + return Uri.TryCreate(path, UriKind.Absolute, out _); + } + + public static IEnumerator DownloadFromUri(string uri, Action onSuccess, Action onError) + { + if (!IsUri(uri)) + { + onError?.Invoke("Invalid URI format."); + yield break; + } + + CommandWindow.Log($"Downloading: {uri}"); + + var request = UnityWebRequest.Get(uri); + request.SetRequestHeader("User-Agent", "RocketModFix"); + request.redirectLimit = 5; + + yield return request.SendWebRequest(); + + if (request.result != UnityWebRequest.Result.Success) + { + onError?.Invoke($"Failed to download from URI: {request.error} (Status: {request.responseCode})"); + yield break; + } + + var data = request.downloadHandler.data; + + onSuccess?.Invoke(data); + } + } +} diff --git a/Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs b/Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs new file mode 100644 index 00000000..bc097dd9 --- /dev/null +++ b/Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections; +using System.Linq; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using SDG.Unturned; +using UnityEngine.Networking; + +namespace Rocket.AutoInstaller.Installation +{ + public static class GitHubActionsDownloader + { + private const string GitHubApiBase = "https://api.github.com"; + private const string GitHubActionsUrlPattern = @"https://github\.com/([^/]+)/([^/]+)/actions/runs/(\d+)"; + + public static bool IsGitHubActionsUrl(string url) + { + if (string.IsNullOrWhiteSpace(url)) + return false; + + return Regex.IsMatch(url, GitHubActionsUrlPattern); + } + + public static IEnumerator DownloadArtifactFromRun(string runUrl, Action? onSuccess, Action onError) + { + if (!IsGitHubActionsUrl(runUrl)) + { + onError?.Invoke("Invalid GitHub Actions run URL format."); + yield break; + } + + var match = Regex.Match(runUrl, GitHubActionsUrlPattern); + if (!match.Success) + { + onError?.Invoke("Could not parse GitHub Actions run URL."); + yield break; + } + + var owner = match.Groups[1].Value; + var repo = match.Groups[2].Value; + var runId = match.Groups[3].Value; + + var artifactsUrl = $"{GitHubApiBase}/repos/{owner}/{repo}/actions/runs/{runId}/artifacts"; + var request = UnityWebRequest.Get(artifactsUrl); + request.SetRequestHeader("User-Agent", "RocketModFix"); + request.SetRequestHeader("Accept", "application/vnd.github.v3+json"); + + yield return request.SendWebRequest(); + + if (request.result != UnityWebRequest.Result.Success) + { + onError?.Invoke($"Failed to fetch artifacts: {request.error} (Status: {request.responseCode})"); + yield break; + } + + var artifactsResponse = request.downloadHandler.text; + var artifacts = JsonConvert.DeserializeObject(artifactsResponse); + + if (artifacts?.Artifacts == null || artifacts.Artifacts.Length == 0) + { + onError?.Invoke("No artifacts found for this run."); + yield break; + } + + var moduleArtifact = artifacts.Artifacts.FirstOrDefault(a => a.Name.Equals("Rocket.Unturned.Module.zip", StringComparison.OrdinalIgnoreCase)); + + if (moduleArtifact == null) + { + moduleArtifact = artifacts.Artifacts.FirstOrDefault(a =>a.Name.ToLowerInvariant().Contains("module")); + } + + if (moduleArtifact == null) + { + onError?.Invoke($"No suitable module artifact found. Available artifacts: {string.Join(", ", artifacts.Artifacts.Select(a => a.Name))}"); + yield break; + } + + var downloadUrl = $"{GitHubApiBase}/repos/{owner}/{repo}/actions/artifacts/{moduleArtifact.Id}/zip"; + var downloadRequest = UnityWebRequest.Get(downloadUrl); + downloadRequest.SetRequestHeader("User-Agent", "RocketModFix"); + downloadRequest.SetRequestHeader("Accept", "application/vnd.github.v3+json"); + + yield return downloadRequest.SendWebRequest(); + + if (downloadRequest.result != UnityWebRequest.Result.Success) + { + onError?.Invoke($"Failed to download artifact: {downloadRequest.error} (Status: {downloadRequest.responseCode})"); + yield break; + } + + var artifactData = downloadRequest.downloadHandler.data; + + onSuccess?.Invoke(artifactData); + } + } +} diff --git a/Rocket.AutoInstaller/Installation/GitHubAsset.cs b/Rocket.AutoInstaller/Installation/GitHubAsset.cs index 95d72ddc..3bee55f0 100644 --- a/Rocket.AutoInstaller/Installation/GitHubAsset.cs +++ b/Rocket.AutoInstaller/Installation/GitHubAsset.cs @@ -1,3 +1,4 @@ +using System; using Newtonsoft.Json; namespace Rocket.AutoInstaller.Installation @@ -19,4 +20,67 @@ public class GitHubAsset [JsonProperty("browser_download_url")] public string BrowserDownloadUrl { get; set; } } + + public class GitHubArtifactsResponse + { + [Newtonsoft.Json.JsonProperty("total_count")] + public int TotalCount { get; set; } + + [Newtonsoft.Json.JsonProperty("artifacts")] + public GitHubArtifact[] Artifacts { get; set; } + } + + public class GitHubArtifact + { + [Newtonsoft.Json.JsonProperty("id")] + public long Id { get; set; } + + [Newtonsoft.Json.JsonProperty("name")] + public string Name { get; set; } + + [Newtonsoft.Json.JsonProperty("size_in_bytes")] + public long SizeInBytes { get; set; } + + [Newtonsoft.Json.JsonProperty("url")] + public string Url { get; set; } + + [Newtonsoft.Json.JsonProperty("archive_download_url")] + public string ArchiveDownloadUrl { get; set; } + + [Newtonsoft.Json.JsonProperty("expired")] + public bool Expired { get; set; } + + [Newtonsoft.Json.JsonProperty("created_at")] + public DateTime CreatedAt { get; set; } + + [Newtonsoft.Json.JsonProperty("updated_at")] + public DateTime UpdatedAt { get; set; } + } + + public class GitHubRelease + { + [JsonProperty("url")] + public string Url { get; set; } + + [JsonProperty("tag_name")] + public string TagName { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("body")] + public string Body { get; set; } + + [JsonProperty("draft")] + public bool Draft { get; set; } + + [JsonProperty("prerelease")] + public bool Prerelease { get; set; } + + [JsonProperty("published_at")] + public DateTime PublishedAt { get; set; } + + [JsonProperty("assets")] + public GitHubAsset[] Assets { get; set; } + } } \ No newline at end of file diff --git a/Rocket.AutoInstaller/Installation/GitHubRelease.cs b/Rocket.AutoInstaller/Installation/GitHubRelease.cs deleted file mode 100644 index ca34f496..00000000 --- a/Rocket.AutoInstaller/Installation/GitHubRelease.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using Newtonsoft.Json; - -namespace Rocket.AutoInstaller.Installation -{ - public class GitHubRelease - { - [JsonProperty("url")] - public string Url { get; set; } - - [JsonProperty("tag_name")] - public string TagName { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("body")] - public string Body { get; set; } - - [JsonProperty("draft")] - public bool Draft { get; set; } - - [JsonProperty("prerelease")] - public bool Prerelease { get; set; } - - [JsonProperty("published_at")] - public DateTime PublishedAt { get; set; } - - [JsonProperty("assets")] - public GitHubAsset[] Assets { get; set; } - } -} \ No newline at end of file diff --git a/Rocket.AutoInstaller/Installation/Installer.cs b/Rocket.AutoInstaller/Installation/Installer.cs index 5dc495aa..aa6aa7f7 100644 --- a/Rocket.AutoInstaller/Installation/Installer.cs +++ b/Rocket.AutoInstaller/Installation/Installer.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Reflection; using Newtonsoft.Json; +using Rocket.AutoInstaller; using SDG.Framework.Modules; using SDG.Unturned; using UnityEngine.Networking; @@ -16,8 +17,44 @@ public class Installer { public static IEnumerator Install(Config config) { - var request = UnityWebRequest.Get( - "https://api.github.com/repos/RocketModFix/RocketModFix/releases"); + if (config.EnableCustomInstall == true && !string.IsNullOrWhiteSpace(config.CustomInstallPath)) + { + CommandWindow.Log("Installing from local path..."); + yield return LocalInstaller.InstallFromLocalPath(config.CustomInstallPath); + yield break; + } + + if (config.AutoInstallRocketFromExtras) + { + CommandWindow.Log("Installing from Extras..."); + yield return ExtrasInstaller.InstallRocketFromExtras(); + yield break; + } + + yield return InstallFromGitHub(config); + } + + public static IEnumerator InstallFromGitHub(Config config) + { + var modulesDirectory = Path.Combine(ReadWrite.PATH, "Modules"); + var releaseCache = new ReleaseCache(modulesDirectory); + + if (releaseCache.IsRocketInstalled()) + { + var cachedEntry = releaseCache.GetCachedEntry(); + if (cachedEntry != null) + { + CommandWindow.Log($"Already installed: {cachedEntry.TagName}"); + yield break; + } + } + + yield return FetchAndInstallLatestRelease(releaseCache, config); + } + + private static IEnumerator FetchAndInstallLatestRelease(ReleaseCache releaseCache, Config config) + { + var request = UnityWebRequest.Get("https://api.github.com/repos/RocketModFix/RocketModFix/releases"); request.SetRequestHeader("User-Agent", "RocketModFix"); request.redirectLimit = 5; @@ -25,8 +62,9 @@ public static IEnumerator Install(Config config) if (request.result != UnityWebRequest.Result.Success) { - CommandWindow.LogError($"Installation Failed: An error occured while installing RocketModFix, response code: {request.responseCode}, error: {request.error}"); - yield break; + var errorMessage = $"Failed to fetch releases: {request.error} (Status: {request.responseCode})"; + CommandWindow.LogError(errorMessage); + throw new Exception(errorMessage); } var responseContent = request.downloadHandler.text; @@ -34,36 +72,52 @@ public static IEnumerator Install(Config config) var latestRelease = releases!.FirstOrDefault(); if (latestRelease == null) { - CommandWindow.LogError("Installation Failed: No Release Found."); - yield break; + CommandWindow.LogError("No release found"); + throw new Exception("No releases found"); } if (string.IsNullOrWhiteSpace(latestRelease.TagName)) { - CommandWindow.LogError("Installation Failed: Release Tag Name doesn't seems to be valid."); - yield break; + CommandWindow.LogError("Invalid release tag"); + throw new Exception("Invalid release tag name"); } var moduleAsset = latestRelease.Assets.FirstOrDefault(IsRocketModFixModule); if (moduleAsset == null) { - CommandWindow.LogError("Installation Failed: Module not found."); + CommandWindow.LogError("Module not found"); + throw new Exception("Module asset not found"); + } + + if (!releaseCache.IsNewerReleaseAvailable(latestRelease.TagName, latestRelease.PublishedAt)) + { + CommandWindow.Log("No newer release available"); yield break; } - CommandWindow.LogWarning($"Preparing to install: " + - $"RocketModFix {latestRelease.TagName} Released: {latestRelease.PublishedAt}"); + CommandWindow.LogWarning($"Installing RocketModFix {latestRelease.TagName} ({latestRelease.PublishedAt:yyyy-MM-dd})"); - request = UnityWebRequest.Get(moduleAsset.BrowserDownloadUrl); - request.SetRequestHeader("User-Agent", "RocketModFix"); - request.redirectLimit = 5; - yield return request.SendWebRequest(); + byte[]? rawData = null; + if (config.EnableRetry) + { + yield return RetryHelper.DownloadWithRetry( + moduleAsset.BrowserDownloadUrl, + data => rawData = data, + error => throw new Exception(error), + maxRetries: 5, + delaySeconds: 5.0f); + } + else + { + yield return RetryHelper.DownloadSingleAttempt( + moduleAsset.BrowserDownloadUrl, + data => rawData = data, + error => throw new Exception(error)); + } - if (request.result != UnityWebRequest.Result.Success) + if (rawData == null) { - CommandWindow.LogError($"Installation Failed: An error occured while getting raw data of module {moduleAsset.Name}, response code: {request.responseCode}, error: {request.error}"); - yield break; + throw new Exception("Failed to download module data"); } - var rawData = request.downloadHandler.data; var releaseEntries = GetReleaseEntries(rawData); byte[]? rocketModuleData = null; List rocketLibraries = []; @@ -84,7 +138,7 @@ public static IEnumerator Install(Config config) if (rocketModuleData == null) { - CommandWindow.LogError($"Installation Failed: {rocketEntryPointFileName} Rocket Entry Point was not found."); + CommandWindow.LogError($"{rocketEntryPointFileName} not found"); yield break; } @@ -100,7 +154,7 @@ public static IEnumerator Install(Config config) x => x.IsAbstract == false && typeof(IModuleNexus).IsAssignableFrom(x)); if (moduleType == null) { - CommandWindow.LogError("Installation Failed: Rocket Module Type cannot be found!"); + CommandWindow.LogError("Rocket module type not found"); yield break; } @@ -108,7 +162,7 @@ public static IEnumerator Install(Config config) { if (Activator.CreateInstance(moduleType) is not IModuleNexus plugin) { - CommandWindow.LogError("Unable to create UnturnedGuard Module!"); + CommandWindow.LogError("Failed to create module"); yield break; } @@ -116,12 +170,21 @@ public static IEnumerator Install(Config config) } catch (Exception ex) { - CommandWindow.LogError("An error occured while creating UnturnedGuard Module! \n" + ex); - yield break; + CommandWindow.LogError($"Error creating module: {ex}"); + throw ex; } - CommandWindow.LogWarning( - $"Successfully installed: RocketModFix v{latestRelease.TagName}"); + var cacheEntry = new CacheEntry + { + TagName = latestRelease.TagName, + Name = latestRelease.Name, + PublishedAt = latestRelease.PublishedAt, + DownloadUrl = moduleAsset.BrowserDownloadUrl, + FileSize = moduleAsset.Size + }; + releaseCache.SaveCacheEntry(cacheEntry); + + CommandWindow.LogWarning($"Installed RocketModFix v{latestRelease.TagName}"); } private static bool IsRocketModFixModule(GitHubAsset asset) @@ -149,7 +212,7 @@ private static List GetReleaseEntries(byte[] assetData) } catch (Exception ex) { - CommandWindow.LogError($"Error while collecting info about release entry: {entry.FullName} \n{ex}"); + CommandWindow.LogError($"Error reading {entry.FullName}: {ex}"); } } return entries; @@ -180,7 +243,7 @@ private static IEnumerable GetLoadableTypes(Assembly assembly) } catch (ReflectionTypeLoadException ex) { - CommandWindow.LogError($"An error occured while getting types for assembly: {assembly} \n" + ex); + CommandWindow.LogError($"Error getting types from {assembly}: {ex}"); return ex.Types.Where(x => x is not null); } } diff --git a/Rocket.AutoInstaller/Installation/LocalInstaller.cs b/Rocket.AutoInstaller/Installation/LocalInstaller.cs new file mode 100644 index 00000000..2f757dec --- /dev/null +++ b/Rocket.AutoInstaller/Installation/LocalInstaller.cs @@ -0,0 +1,275 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Reflection; +using SDG.Framework.Modules; +using SDG.Unturned; + +namespace Rocket.AutoInstaller.Installation +{ + public class LocalInstaller + { + public static IEnumerator InstallFromLocalPath(string localPath) + { + if (!PathValidator.ValidateLocalBuildPath(localPath, out var errorMessage)) + { + CommandWindow.LogError($"Local install failed: {errorMessage}"); + PathValidator.LogValidationResult(localPath, false, errorMessage); + yield break; + } + + PathValidator.LogValidationResult(localPath, true); + CommandWindow.Log($"Installing from: {localPath}"); + + List releaseEntries = []; + + if (GenericUriDownloader.IsUri(localPath)) + { + if (GitHubActionsDownloader.IsGitHubActionsUrl(localPath)) + { + CommandWindow.Log("GitHub Actions URL detected, downloading..."); + yield return DownloadAndProcessGitHubArtifact(localPath, entries => releaseEntries = entries); + } + else + { + CommandWindow.Log("URI detected, downloading..."); + yield return DownloadAndProcessGenericUri(localPath, entries => releaseEntries = entries); + } + } + else + { + try + { + if (File.Exists(localPath) && localPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) + { + var zipData = File.ReadAllBytes(localPath); + releaseEntries = GetReleaseEntries(zipData); + } + else + { + releaseEntries = GetReleaseEntriesFromDirectory(localPath); + } + } + catch (Exception ex) + { + CommandWindow.LogError($"Failed to read module zip: {ex}"); + yield break; + } + } + + byte[]? rocketModuleData = null; + List rocketLibraries = []; + const string rocketEntryPointFileName = "Rocket.Unturned.dll"; + + foreach (var releaseEntry in releaseEntries) + { + if (releaseEntry.Name == rocketEntryPointFileName) + { + rocketModuleData = releaseEntry.Content; + continue; + } + if (releaseEntry.Name != rocketEntryPointFileName && releaseEntry.FileExtension == ".dll") + { + rocketLibraries.Add(releaseEntry.Content); + continue; + } + } + + if (rocketModuleData == null) + { + CommandWindow.LogError($"{rocketEntryPointFileName} not found in zip"); + yield break; + } + + foreach (var rocketLibrary in rocketLibraries) + { + try + { + Assembly.Load(rocketLibrary); + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Failed to load library: {ex}"); + } + } + + var rocketModule = Assembly.Load(rocketModuleData); + var types = GetLoadableTypes(rocketModule); + var moduleType = types.FirstOrDefault(x => !x.IsAbstract && typeof(IModuleNexus).IsAssignableFrom(x)); + + if (moduleType == null) + { + CommandWindow.LogError("Rocket module type not found"); + yield break; + } + + IModuleNexus plugin; + try + { + if (Activator.CreateInstance(moduleType) is not IModuleNexus createdPlugin) + { + CommandWindow.LogError("Failed to create rocket module"); + yield break; + } + plugin = createdPlugin; + } + catch (Exception ex) + { + CommandWindow.LogError($"Error creating rocket module: {ex}"); + yield break; + } + + plugin.initialize(); + CommandWindow.LogWarning($"Installed from local build: {localPath}"); + } + + private static List GetReleaseEntries(byte[] assetData) + { + var entries = new List(); + using var memoryStream = new MemoryStream(assetData); + using var zipArchive = new ZipArchive(memoryStream); + foreach (var entry in zipArchive.Entries) + { + try + { + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(entry.FullName); + var fileExtension = Path.GetExtension(entry.FullName); + var entryDirectoryName = Path.GetDirectoryName(entry.FullName)!; + + using var stream = entry.Open(); + var entryData = stream.CopyToArray(); + + entries.Add(new ReleaseEntry(entry.Name, entry.FullName, fileNameWithoutExtension, fileExtension, + entryDirectoryName, entryData)); + } + catch (Exception ex) + { + CommandWindow.LogError($"Error reading {entry.FullName}: {ex}"); + } + } + return entries; + } + + private static List GetReleaseEntriesFromDirectory(string directoryPath) + { + var entries = new List(); + + var allFiles = Directory.GetFiles(directoryPath, "*", SearchOption.AllDirectories); + + foreach (var filePath in allFiles) + { + try + { + var relativePath = GetRelativePath(directoryPath, filePath); + var fileName = Path.GetFileName(filePath); + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); + var fileExtension = Path.GetExtension(filePath); + var entryDirectoryName = Path.GetDirectoryName(relativePath) ?? string.Empty; + + var fileData = File.ReadAllBytes(filePath); + + entries.Add(new ReleaseEntry(fileName, relativePath, fileNameWithoutExtension, fileExtension, + entryDirectoryName, fileData)); + } + catch (Exception ex) + { + CommandWindow.LogError($"Error reading {filePath}: {ex}"); + } + } + + return entries; + } + + private static IEnumerator DownloadAndProcessGitHubArtifact(string url, Action> onComplete) + { + var entries = new List(); + var downloadSucceeded = false; + var downloadError = string.Empty; + + yield return GitHubActionsDownloader.DownloadArtifactFromRun(url, + artifactData => { + entries = GetReleaseEntries(artifactData); + downloadSucceeded = true; + }, + error => { + downloadError = error; + downloadSucceeded = false; + }); + + if (!downloadSucceeded) + { + CommandWindow.LogError($"GitHub Actions failed: {downloadError}"); + yield break; + } + + onComplete?.Invoke(entries); + } + + private static IEnumerator DownloadAndProcessGenericUri(string uri, Action> onComplete) + { + var entries = new List(); + var downloadSucceeded = false; + var downloadError = string.Empty; + + yield return GenericUriDownloader.DownloadFromUri(uri, + data => { + entries = GetReleaseEntries(data); + downloadSucceeded = true; + }, + error => { + downloadError = error; + downloadSucceeded = false; + }); + + if (!downloadSucceeded) + { + CommandWindow.LogError($"URI download failed: {downloadError}"); + yield break; + } + + onComplete?.Invoke(entries); + } + + private static string GetRelativePath(string basePath, string targetPath) + { + var baseUri = new Uri(basePath.EndsWith(Path.DirectorySeparatorChar.ToString()) ? basePath : basePath + Path.DirectorySeparatorChar); + var targetUri = new Uri(targetPath); + var relativeUri = baseUri.MakeRelativeUri(targetUri); + return Uri.UnescapeDataString(relativeUri.ToString().Replace('/', Path.DirectorySeparatorChar)); + } + + /// + /// Safely returns the set of loadable types from an assembly. + /// Algorithm from StackOverflow answer here: + /// https://stackoverflow.com/questions/7889228/how-to-prevent-reflectiontypeloadexception-when-calling-assembly-gettypes + /// + /// The from which to load types. + /// + /// The set of types from the , or the subset + /// of types that could be loaded if there was any error. + /// + /// + /// Thrown if is . + /// + private static IEnumerable GetLoadableTypes(Assembly assembly) + { + if (assembly == null) + { + throw new ArgumentNullException(nameof(assembly)); + } + + try + { + return assembly.DefinedTypes.Select(x => x.AsType()); + } + catch (ReflectionTypeLoadException ex) + { + CommandWindow.LogError($"Error getting types from {assembly}: {ex}"); + return ex.Types.Where(x => x is not null); + } + } + } +} diff --git a/Rocket.AutoInstaller/Installation/PathValidator.cs b/Rocket.AutoInstaller/Installation/PathValidator.cs new file mode 100644 index 00000000..69165f98 --- /dev/null +++ b/Rocket.AutoInstaller/Installation/PathValidator.cs @@ -0,0 +1,140 @@ +using System; +using System.IO; +using SDG.Unturned; + +namespace Rocket.AutoInstaller.Installation +{ + public static class PathValidator + { + public static bool ValidateLocalBuildPath(string path, out string errorMessage) + { + errorMessage = string.Empty; + + if (string.IsNullOrWhiteSpace(path)) + { + errorMessage = "Path is null or empty."; + return false; + } + + if (GenericUriDownloader.IsUri(path)) + { + return ValidateUri(path, out errorMessage); + } + + if (File.Exists(path) && path.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) + { + return ValidateZipFile(path, out errorMessage); + } + + if (Directory.Exists(path)) + { + return ValidateDirectory(path, out errorMessage); + } + + errorMessage = $"Path does not exist (neither file nor directory): {path}"; + return false; + } + + private static bool ValidateUri(string uri, out string errorMessage) + { + errorMessage = string.Empty; + + if (!Uri.TryCreate(uri, UriKind.Absolute, out var parsedUri)) + { + errorMessage = "Invalid URI format."; + return false; + } + + if (parsedUri.Scheme != "http" && parsedUri.Scheme != "https") + { + errorMessage = "Only HTTP and HTTPS URIs are supported."; + return false; + } + + // Note: We can't validate the actual content without making a network request + // This validation will be done during the download process + return true; + } + + private static bool ValidateZipFile(string zipPath, out string errorMessage) + { + errorMessage = string.Empty; + + try + { + var fileInfo = new FileInfo(zipPath); + if (fileInfo.Length == 0) + { + errorMessage = "Zip file is empty."; + return false; + } + + using var zipArchive = System.IO.Compression.ZipFile.OpenRead(zipPath); + var hasRocketDll = false; + foreach (var entry in zipArchive.Entries) + { + if (entry.Name.Equals("Rocket.Unturned.dll", StringComparison.OrdinalIgnoreCase)) + { + hasRocketDll = true; + break; + } + } + + if (!hasRocketDll) + { + errorMessage = "Rocket.Unturned.dll not found in the zip file."; + return false; + } + } + catch (Exception ex) + { + errorMessage = $"Invalid or corrupted zip file: {ex}"; + return false; + } + + return true; + } + + private static bool ValidateDirectory(string directoryPath, out string errorMessage) + { + errorMessage = string.Empty; + + var rocketDllPath = Path.Combine(directoryPath, "Rocket.Unturned.dll"); + if (File.Exists(rocketDllPath)) + { + return true; + } + + var moduleZipPath = Path.Combine(directoryPath, "Rocket.Unturned.Module.zip"); + if (File.Exists(moduleZipPath)) + { + return ValidateZipFile(moduleZipPath, out errorMessage); + } + + var subdirectories = Directory.GetDirectories(directoryPath, "*", SearchOption.AllDirectories); + foreach (var subdir in subdirectories) + { + var subdirRocketDll = Path.Combine(subdir, "Rocket.Unturned.dll"); + if (File.Exists(subdirRocketDll)) + { + return true; + } + } + + errorMessage = $"Neither Rocket.Unturned.dll nor Rocket.Unturned.Module.zip found in: {directoryPath}"; + return false; + } + + public static void LogValidationResult(string path, bool isValid, string errorMessage = "") + { + if (isValid) + { + CommandWindow.Log($"Path validated: {path}"); + } + else + { + CommandWindow.LogError($"Path validation failed: {errorMessage}"); + } + } + } +} diff --git a/Rocket.AutoInstaller/Installation/ReleaseCache.cs b/Rocket.AutoInstaller/Installation/ReleaseCache.cs new file mode 100644 index 00000000..a0597991 --- /dev/null +++ b/Rocket.AutoInstaller/Installation/ReleaseCache.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Newtonsoft.Json; +using SDG.Unturned; + +namespace Rocket.AutoInstaller.Installation +{ + public class ReleaseCache + { + private const string CacheFileName = "rocket_cache.json"; + private readonly string _cacheFilePath; + private readonly string _modulesDirectory; + + public ReleaseCache(string modulesDirectory) + { + _modulesDirectory = modulesDirectory; + _cacheFilePath = Path.Combine(modulesDirectory, CacheFileName); + } + + public CacheEntry? GetCachedEntry() + { + if (!File.Exists(_cacheFilePath)) + return null; + + try + { + var cacheContent = File.ReadAllText(_cacheFilePath); + var cache = JsonConvert.DeserializeObject(cacheContent); + return cache; + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Cache read failed: {ex}"); + return null; + } + } + + public void SaveCacheEntry(CacheEntry entry) + { + try + { + var cacheContent = JsonConvert.SerializeObject(entry, Formatting.Indented); + File.WriteAllText(_cacheFilePath, cacheContent); + CommandWindow.Log($"Cached: {entry.TagName} ({entry.PublishedAt:yyyy-MM-dd})"); + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Cache save failed: {ex}"); + } + } + + public bool IsNewerReleaseAvailable(string latestTagName, DateTime latestPublishedAt) + { + var cachedEntry = GetCachedEntry(); + if (cachedEntry == null) + { + CommandWindow.Log("No cached release found"); + return true; + } + if (latestPublishedAt > cachedEntry.PublishedAt) + { + CommandWindow.Log($"Newer release: {latestTagName} vs {cachedEntry.TagName}"); + return true; + } + + if (latestPublishedAt == cachedEntry.PublishedAt && latestTagName != cachedEntry.TagName) + { + CommandWindow.Log($"Different tag: {latestTagName} vs {cachedEntry.TagName}"); + return true; + } + + CommandWindow.Log($"No newer release: {cachedEntry.TagName}"); + return false; + } + + public void ClearCache() + { + try + { + if (File.Exists(_cacheFilePath)) + { + File.Delete(_cacheFilePath); + CommandWindow.Log("Cache cleared"); + } + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Cache clear failed: {ex}"); + } + } + + public bool IsRocketInstalled() + { + var rocketFiles = Directory.GetFiles(_modulesDirectory, "Rocket.Unturned.dll", SearchOption.AllDirectories); + return rocketFiles.Any(); + } + } + + public class CacheEntry + { + public string TagName { get; set; } + public string Name { get; set; } + public DateTime PublishedAt { get; set; } + public string DownloadUrl { get; set; } + public long FileSize { get; set; } + public DateTime CachedAt { get; set; } + + public CacheEntry() + { + CachedAt = DateTime.UtcNow; + } + } +} diff --git a/Rocket.AutoInstaller/Installation/RetryHelper.cs b/Rocket.AutoInstaller/Installation/RetryHelper.cs new file mode 100644 index 00000000..47fb55d5 --- /dev/null +++ b/Rocket.AutoInstaller/Installation/RetryHelper.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using SDG.Unturned; +using UnityEngine; + +namespace Rocket.AutoInstaller.Installation +{ + public static class RetryHelper + { + public static IEnumerator DownloadWithRetry( + string url, + Action? onSuccess, + Action? onError, + int maxRetries = 5, + float delaySeconds = 5.0f) + { + for (int attempt = 1; attempt <= maxRetries; attempt++) + { + if (attempt > 1) + { + yield return new WaitForSeconds(delaySeconds); + } + + bool downloadSucceeded = false; + yield return DownloadSingleAttempt(url, + data => { + onSuccess?.Invoke(data); + downloadSucceeded = true; + }, + error => { + onError?.Invoke(error); + downloadSucceeded = false; + }); + + if (downloadSucceeded) + { + yield break; + } + } + + CommandWindow.LogError($"Download failed after {maxRetries} attempts: {url}"); + } + + public static IEnumerator DownloadSingleAttempt( + string url, + Action? onSuccess, + Action? onError) + { + var request = UnityEngine.Networking.UnityWebRequest.Get(url); + request.SetRequestHeader("User-Agent", "RocketModFix"); + request.redirectLimit = 5; + + yield return request.SendWebRequest(); + + if (request.result != UnityEngine.Networking.UnityWebRequest.Result.Success) + { + var errorMessage = $"Download failed: {request.error} (HTTP {request.responseCode})"; + onError?.Invoke(errorMessage); + throw new Exception(errorMessage); + } + + var data = request.downloadHandler.data; + onSuccess?.Invoke(data); + } + } +} diff --git a/Rocket.AutoInstaller/Module.cs b/Rocket.AutoInstaller/Module.cs index f3707bee..12767198 100644 --- a/Rocket.AutoInstaller/Module.cs +++ b/Rocket.AutoInstaller/Module.cs @@ -16,6 +16,8 @@ public class Config public bool? EnableCustomInstall { get; set; } public string? CustomInstallPath { get; set; } public bool BlockIfRocketInstalled { get; set; } + public bool AutoInstallRocketFromExtras { get; set; } + public bool EnableRetry { get; set; } } /// @@ -33,7 +35,7 @@ public void initialize() var assembly = typeof(Module).Assembly; var assemblyName = assembly.GetName(); - CommandWindow.Log($"Loading Rocket.AutoInstaller... {assemblyName.Name} {assemblyName.Version} this could take for a while!"); + CommandWindow.Log($"Loading {assemblyName.Name} {assemblyName.Version}..."); CommandWindow.Log($"Discord Support: {DiscordSupportURL}"); var modulesDirectory = Path.Combine(ReadWrite.PATH, "Modules"); @@ -55,6 +57,8 @@ public void initialize() EnableCustomInstall = false, CustomInstallPath = null, BlockIfRocketInstalled = true, + AutoInstallRocketFromExtras = false, + EnableRetry = true, }; File.WriteAllText(configPath, JsonConvert.SerializeObject(config, Formatting.Indented)); } @@ -62,20 +66,28 @@ public void initialize() if (config.BlockIfRocketInstalled) { const string rocketUnturnedDll = "Rocket.Unturned.dll"; - // TODO: Once we do a caching make sure to ignore the own directory in Module code, cuz it will block the load process (see `BlockIfRocketInstalled`)! - var rocketPath = Path.GetDirectoryName(Directory - .GetFiles(modulesDirectory, rocketUnturnedDll, SearchOption.AllDirectories) - .FirstOrDefault()); + var rocketFiles = Directory.GetFiles(modulesDirectory, rocketUnturnedDll, SearchOption.AllDirectories); + var rocketPath = rocketFiles.FirstOrDefault(); + if (rocketPath != null) { - CommandWindow.Log($"Rocket.Unturned is already installed in the Modules directory: \"{rocketPath}\". Please remove it to prevent potential issues."); - if (config.BlockIfRocketInstalled) + var rocketDirectory = Path.GetDirectoryName(rocketPath); + + if (string.Equals(rocketDirectory, workingDirectory, StringComparison.OrdinalIgnoreCase)) + { + CommandWindow.Log("Ignoring self-directory to prevent blocking"); + } + else { - CommandWindow.Log( - "Installation via Rocket.AutoInstaller has been stopped because Rocket is already installed. " + - "To proceed, either delete Rocket.Unturned from the Modules directory or set `BlockIfRocketInstalled` to `false` in the configuration." - ); - return; + CommandWindow.Log($"Rocket already installed: {rocketDirectory}"); + if (config.BlockIfRocketInstalled) + { + CommandWindow.Log( + "Installation via Rocket.AutoInstaller has been stopped because Rocket is already installed. " + + "To proceed, either delete Rocket.Unturned from the Modules directory or set `BlockIfRocketInstalled` to `false` in the configuration." + ); + return; + } } } } diff --git a/Rocket.AutoInstaller/README.md b/Rocket.AutoInstaller/README.md index 3f77d29c..6e54f99e 100644 --- a/Rocket.AutoInstaller/README.md +++ b/Rocket.AutoInstaller/README.md @@ -1,19 +1,86 @@ # Rocket.AutoInstaller -It's a Module auto-installer (loader/bootstrapper), which installs RocketModFix automatically from GitHub, you can still use a manual way of installation, however, this one is more modern, simple and faster. +Auto-installer for RocketModFix. Downloads and installs the latest version from GitHub, or installs from local builds for development. + +## Quick Start + +Just drop the module in your `Modules` folder and start your server. It will automatically download and install the latest RocketModFix. + +## Configuration + +Edit `config.json` to customize installation behavior: + +```json +{ + "EnableCustomInstall": false, + "CustomInstallPath": "", + "BlockIfRocketInstalled": true, + "AutoInstallRocketFromExtras": false, + "EnableRetry": true +} +``` + +### Options + +**For regular users:** +- `BlockIfRocketInstalled` - Prevent installation if Rocket is already installed +- `EnableRetry` - Enable retry mechanism for failed downloads (5 attempts, 5s delay) + +**For developers:** +- `EnableCustomInstall` - Enable local installation instead of GitHub +- `CustomInstallPath` - Path to your local build (see examples below) +- `AutoInstallRocketFromExtras` - Auto-install from Extras folder + +### Local Installation Examples + +For developers who want to test their own builds without manually copying files every time. The `CustomInstallPath` can point to: + +1. A zip file - Direct path to Rocket.Unturned.Module.zip + ``` + "CustomInstallPath": "C:\\Builds\\Rocket.Unturned.Module.zip" + ``` + +2. An unzipped folder - Directory containing the module files + ``` + "CustomInstallPath": "C:\\Builds\\RocketModFix\\Rocket.Unturned" + ``` + + The folder should contain either: + - Rocket.Unturned.dll directly, or + - Rocket.Unturned.Module.zip file, or + - Rocket.Unturned.dll in any subdirectory + +3. GitHub Actions URL - Direct link to a GitHub Actions run + ``` + "CustomInstallPath": "https://github.com/RocketModFix/RocketModFix/actions/runs/17277595277" + ``` + +4. Generic URI - Any HTTP/HTTPS URL pointing to a zip file + ``` + "CustomInstallPath": "https://example.com/downloads/Rocket.Unturned.Module.zip" + ``` + +## Features + +- Auto-install from GitHub - Downloads latest release automatically +- Local build support - Install from zip files, directories, or URLs +- Smart caching - Only downloads when newer versions are available +- Retry mechanism - Handles network issues with automatic retries +- Extras integration - Auto-install from server's Extras folder +- Safety checks - Prevents conflicts with existing installations ## Plans -If you want to implement one of the plans or have better ideas or ideas to change, feel free to know us about that! - -- [x] Auto-Install from GitHub Releases. -- [ ] Auto-Install Local Build (so, no need to manually install RocketModFix everytime you test/update it, 1 click to build, restart server, and you're testing!). - - [x] Json (or other type of config) Config with Options: - - [x] `EnableCustomInstall`: false/true (default is false). - - [x] `CustomInstallPath`: path to a build of RocketModFix. - - [ ] (Not 100% yet) We can also an option in config (`AutoInstallRocketFromExtras`) to make auto installation of Rocket (LDM) from Extras. - - [ ] Once we do a caching make sure to ignore the own directory in Module code, cuz it will block the load process (see `BlockIfRocketInstalled`)! -- [ ] Caching. - - [ ] Check if GitHub release is newer than current cached version and ONLY then install new version, also use Retry (5 seconds, 5 attempts or so) in case of GitHub's down or problems with internet. - - [ ] For safe usage without Internet Connection. -- [x] ([Details](https://github.com/RocketModFix/RocketModFix/issues/119)) Block installation if Rocket already installed (`BlockIfRocketInstalled` in config). \ No newline at end of file +If you want to implement one of the plans or have better ideas, feel free to let us know! + +- [x] Auto-Install from GitHub Releases +- [x] Auto-Install Local Build (no need to manually install RocketModFix every time you test/update it, 1 click to build, restart server, and you're testing!) + - [x] Json config with options: + - [x] `EnableCustomInstall`: false/true (default is false) + - [x] `CustomInstallPath`: path to a build of RocketModFix + - [x] `AutoInstallRocketFromExtras`: false/true (default is false) - Auto-install Rocket (LDM) from Extras + - [x] Fixed self-directory exclusion in Module code to prevent blocking the load process (see `BlockIfRocketInstalled`)! +- [x] Caching + - [x] Check if GitHub release is newer than current cached version and ONLY then install new version, also use Retry (5 seconds, 5 attempts or so) in case of GitHub's down or problems with internet + - [x] For safe usage without Internet Connection +- [x] ([Details](https://github.com/RocketModFix/RocketModFix/issues/119)) Block installation if Rocket already installed (`BlockIfRocketInstalled` in config) \ No newline at end of file diff --git a/Rocket.AutoInstaller/config.json b/Rocket.AutoInstaller/config.json index 961e1cc7..8dbd80f7 100644 --- a/Rocket.AutoInstaller/config.json +++ b/Rocket.AutoInstaller/config.json @@ -1,5 +1,7 @@ { "EnableCustomInstall": false, "CustomInstallPath": "", - "BlockIfRocketInstalled": true + "BlockIfRocketInstalled": true, + "AutoInstallRocketFromExtras": false, + "EnableRetry": true } \ No newline at end of file From 3ed0d95ad6889d92999d06408eb10bfe0ad7d561 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 13 Sep 2025 20:42:41 +0300 Subject: [PATCH 11/42] Fix gh artifacts are x2 zipped --- .github/workflows/RocketModFix.yaml | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index 12fa6c86..bfa4b900 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -62,12 +62,6 @@ jobs: nuget_push: false github_token: ${{ secrets.PAT }} - - name: Install zip - run: sudo apt-get install zip - - - name: Zip Rocket.AutoInstaller artifacts - run: "cd ./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller && zip -qq -r ./Rocket.AutoInstaller.zip *" - - name: Build Rocket.Unturned.Module uses: ./.github/actions/project-build id: unturned-module-build @@ -77,23 +71,26 @@ jobs: nuget_push: false github_token: ${{ secrets.PAT }} - - name: Zip Rocket.Unturned artifacts - run: "cd ./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned && zip -qq -r ./Rocket.Unturned.Module.zip *" - - name: Upload Rocket.AutoInstaller uses: actions/upload-artifact@v4 with: - name: Rocket.AutoInstaller.zip - path: "./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller/Rocket.AutoInstaller.zip" + name: Rocket.AutoInstaller + path: "./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller/" if-no-files-found: error - name: Upload Rocket.Unturned.Module uses: actions/upload-artifact@v4 with: - name: Rocket.Unturned.Module.zip - path: "./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned/Rocket.Unturned.Module.zip" + name: Rocket.Unturned.Module + path: "./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned/" if-no-files-found: error + - name: Zip Rocket.AutoInstaller artifacts + run: "cd ./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller && zip -qq -r ./Rocket.AutoInstaller.zip *" + + - name: Zip Rocket.Unturned artifacts + run: "cd ./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned && zip -qq -r ./Rocket.Unturned.Module.zip *" + - name: Create Release if: github.event_name == 'create' && github.event.ref_type == 'tag' uses: ncipollo/release-action@v1.20.0 From 5e378e92ab4f4eb818465ee6bb42eee07e11795d Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 13 Sep 2025 21:40:24 +0300 Subject: [PATCH 12/42] Remove support of custom download from gh actions cause need authentication for that --- .github/workflows/RocketModFix.yaml | 2 +- .../Installation/GitHubActionsDownloader.cs | 96 ------------------- .../Installation/GitHubAsset.cs | 38 +------- .../Installation/LocalInstaller.cs | 36 +------ Rocket.AutoInstaller/README.md | 12 +-- 5 files changed, 8 insertions(+), 176 deletions(-) delete mode 100644 Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index bfa4b900..256124cf 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -77,7 +77,7 @@ jobs: name: Rocket.AutoInstaller path: "./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller/" if-no-files-found: error - + - name: Upload Rocket.Unturned.Module uses: actions/upload-artifact@v4 with: diff --git a/Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs b/Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs deleted file mode 100644 index bc097dd9..00000000 --- a/Rocket.AutoInstaller/Installation/GitHubActionsDownloader.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections; -using System.Linq; -using System.Text.RegularExpressions; -using Newtonsoft.Json; -using SDG.Unturned; -using UnityEngine.Networking; - -namespace Rocket.AutoInstaller.Installation -{ - public static class GitHubActionsDownloader - { - private const string GitHubApiBase = "https://api.github.com"; - private const string GitHubActionsUrlPattern = @"https://github\.com/([^/]+)/([^/]+)/actions/runs/(\d+)"; - - public static bool IsGitHubActionsUrl(string url) - { - if (string.IsNullOrWhiteSpace(url)) - return false; - - return Regex.IsMatch(url, GitHubActionsUrlPattern); - } - - public static IEnumerator DownloadArtifactFromRun(string runUrl, Action? onSuccess, Action onError) - { - if (!IsGitHubActionsUrl(runUrl)) - { - onError?.Invoke("Invalid GitHub Actions run URL format."); - yield break; - } - - var match = Regex.Match(runUrl, GitHubActionsUrlPattern); - if (!match.Success) - { - onError?.Invoke("Could not parse GitHub Actions run URL."); - yield break; - } - - var owner = match.Groups[1].Value; - var repo = match.Groups[2].Value; - var runId = match.Groups[3].Value; - - var artifactsUrl = $"{GitHubApiBase}/repos/{owner}/{repo}/actions/runs/{runId}/artifacts"; - var request = UnityWebRequest.Get(artifactsUrl); - request.SetRequestHeader("User-Agent", "RocketModFix"); - request.SetRequestHeader("Accept", "application/vnd.github.v3+json"); - - yield return request.SendWebRequest(); - - if (request.result != UnityWebRequest.Result.Success) - { - onError?.Invoke($"Failed to fetch artifacts: {request.error} (Status: {request.responseCode})"); - yield break; - } - - var artifactsResponse = request.downloadHandler.text; - var artifacts = JsonConvert.DeserializeObject(artifactsResponse); - - if (artifacts?.Artifacts == null || artifacts.Artifacts.Length == 0) - { - onError?.Invoke("No artifacts found for this run."); - yield break; - } - - var moduleArtifact = artifacts.Artifacts.FirstOrDefault(a => a.Name.Equals("Rocket.Unturned.Module.zip", StringComparison.OrdinalIgnoreCase)); - - if (moduleArtifact == null) - { - moduleArtifact = artifacts.Artifacts.FirstOrDefault(a =>a.Name.ToLowerInvariant().Contains("module")); - } - - if (moduleArtifact == null) - { - onError?.Invoke($"No suitable module artifact found. Available artifacts: {string.Join(", ", artifacts.Artifacts.Select(a => a.Name))}"); - yield break; - } - - var downloadUrl = $"{GitHubApiBase}/repos/{owner}/{repo}/actions/artifacts/{moduleArtifact.Id}/zip"; - var downloadRequest = UnityWebRequest.Get(downloadUrl); - downloadRequest.SetRequestHeader("User-Agent", "RocketModFix"); - downloadRequest.SetRequestHeader("Accept", "application/vnd.github.v3+json"); - - yield return downloadRequest.SendWebRequest(); - - if (downloadRequest.result != UnityWebRequest.Result.Success) - { - onError?.Invoke($"Failed to download artifact: {downloadRequest.error} (Status: {downloadRequest.responseCode})"); - yield break; - } - - var artifactData = downloadRequest.downloadHandler.data; - - onSuccess?.Invoke(artifactData); - } - } -} diff --git a/Rocket.AutoInstaller/Installation/GitHubAsset.cs b/Rocket.AutoInstaller/Installation/GitHubAsset.cs index 3bee55f0..1b8239f0 100644 --- a/Rocket.AutoInstaller/Installation/GitHubAsset.cs +++ b/Rocket.AutoInstaller/Installation/GitHubAsset.cs @@ -21,43 +21,7 @@ public class GitHubAsset public string BrowserDownloadUrl { get; set; } } - public class GitHubArtifactsResponse - { - [Newtonsoft.Json.JsonProperty("total_count")] - public int TotalCount { get; set; } - - [Newtonsoft.Json.JsonProperty("artifacts")] - public GitHubArtifact[] Artifacts { get; set; } - } - - public class GitHubArtifact - { - [Newtonsoft.Json.JsonProperty("id")] - public long Id { get; set; } - - [Newtonsoft.Json.JsonProperty("name")] - public string Name { get; set; } - - [Newtonsoft.Json.JsonProperty("size_in_bytes")] - public long SizeInBytes { get; set; } - - [Newtonsoft.Json.JsonProperty("url")] - public string Url { get; set; } - - [Newtonsoft.Json.JsonProperty("archive_download_url")] - public string ArchiveDownloadUrl { get; set; } - - [Newtonsoft.Json.JsonProperty("expired")] - public bool Expired { get; set; } - - [Newtonsoft.Json.JsonProperty("created_at")] - public DateTime CreatedAt { get; set; } - - [Newtonsoft.Json.JsonProperty("updated_at")] - public DateTime UpdatedAt { get; set; } - } - - public class GitHubRelease + public class GitHubRelease { [JsonProperty("url")] public string Url { get; set; } diff --git a/Rocket.AutoInstaller/Installation/LocalInstaller.cs b/Rocket.AutoInstaller/Installation/LocalInstaller.cs index 2f757dec..c20c71b9 100644 --- a/Rocket.AutoInstaller/Installation/LocalInstaller.cs +++ b/Rocket.AutoInstaller/Installation/LocalInstaller.cs @@ -28,16 +28,7 @@ public static IEnumerator InstallFromLocalPath(string localPath) if (GenericUriDownloader.IsUri(localPath)) { - if (GitHubActionsDownloader.IsGitHubActionsUrl(localPath)) - { - CommandWindow.Log("GitHub Actions URL detected, downloading..."); - yield return DownloadAndProcessGitHubArtifact(localPath, entries => releaseEntries = entries); - } - else - { - CommandWindow.Log("URI detected, downloading..."); - yield return DownloadAndProcessGenericUri(localPath, entries => releaseEntries = entries); - } + yield return DownloadAndProcessGenericUri(localPath, entries => releaseEntries = entries); } else { @@ -183,31 +174,6 @@ private static List GetReleaseEntriesFromDirectory(string director return entries; } - private static IEnumerator DownloadAndProcessGitHubArtifact(string url, Action> onComplete) - { - var entries = new List(); - var downloadSucceeded = false; - var downloadError = string.Empty; - - yield return GitHubActionsDownloader.DownloadArtifactFromRun(url, - artifactData => { - entries = GetReleaseEntries(artifactData); - downloadSucceeded = true; - }, - error => { - downloadError = error; - downloadSucceeded = false; - }); - - if (!downloadSucceeded) - { - CommandWindow.LogError($"GitHub Actions failed: {downloadError}"); - yield break; - } - - onComplete?.Invoke(entries); - } - private static IEnumerator DownloadAndProcessGenericUri(string uri, Action> onComplete) { var entries = new List(); diff --git a/Rocket.AutoInstaller/README.md b/Rocket.AutoInstaller/README.md index 6e54f99e..7b3bfcc5 100644 --- a/Rocket.AutoInstaller/README.md +++ b/Rocket.AutoInstaller/README.md @@ -44,22 +44,20 @@ For developers who want to test their own builds without manually copying files ``` "CustomInstallPath": "C:\\Builds\\RocketModFix\\Rocket.Unturned" ``` - + The folder should contain either: - Rocket.Unturned.dll directly, or - Rocket.Unturned.Module.zip file, or - Rocket.Unturned.dll in any subdirectory -3. GitHub Actions URL - Direct link to a GitHub Actions run - ``` - "CustomInstallPath": "https://github.com/RocketModFix/RocketModFix/actions/runs/17277595277" - ``` - -4. Generic URI - Any HTTP/HTTPS URL pointing to a zip file +3. Direct URI - Any HTTP/HTTPS URL pointing to a zip file ``` "CustomInstallPath": "https://example.com/downloads/Rocket.Unturned.Module.zip" ``` + **Note:** GitHub Actions artifacts are currently not supported cause require authentication and aren't suitable for public downloads. + See [GitHub issue #51](https://github.com/actions/upload-artifact/issues/51) for details. + ## Features - Auto-install from GitHub - Downloads latest release automatically From b16711ea46aaea78559eeb5079b7c8d70b54a03a Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 14 Sep 2025 13:47:48 +0300 Subject: [PATCH 13/42] Rocket.AutoInstaller: cache installed .zip from gh releases then reuse it while same version --- .../{RetryHelper.cs => DownloadHelper.cs} | 31 ++++-- .../Installation/ExtrasInstaller.cs | 2 - .../Installation/GenericUriDownloader.cs | 46 -------- .../Installation/Installer.cs | 102 +++++++++++------ .../Installation/LocalInstaller.cs | 27 +++-- .../Installation/PathValidator.cs | 18 +-- .../Installation/ReleaseCache.cs | 104 +++++++++++++++++- Rocket.AutoInstaller/Module.cs | 2 + Rocket.AutoInstaller/README.md | 15 +-- Rocket.AutoInstaller/config.json | 3 +- 10 files changed, 215 insertions(+), 135 deletions(-) rename Rocket.AutoInstaller/Installation/{RetryHelper.cs => DownloadHelper.cs} (69%) delete mode 100644 Rocket.AutoInstaller/Installation/GenericUriDownloader.cs diff --git a/Rocket.AutoInstaller/Installation/RetryHelper.cs b/Rocket.AutoInstaller/Installation/DownloadHelper.cs similarity index 69% rename from Rocket.AutoInstaller/Installation/RetryHelper.cs rename to Rocket.AutoInstaller/Installation/DownloadHelper.cs index 47fb55d5..c8192299 100644 --- a/Rocket.AutoInstaller/Installation/RetryHelper.cs +++ b/Rocket.AutoInstaller/Installation/DownloadHelper.cs @@ -1,20 +1,37 @@ using System; using System.Collections; -using System.Collections.Generic; using SDG.Unturned; using UnityEngine; +using UnityEngine.Networking; namespace Rocket.AutoInstaller.Installation { - public static class RetryHelper + public static class DownloadHelper { - public static IEnumerator DownloadWithRetry( + public static bool IsUri(string path) + { + if (string.IsNullOrWhiteSpace(path)) + return false; + + return Uri.TryCreate(path, UriKind.Absolute, out _); + } + + public static IEnumerator Download( string url, Action? onSuccess, Action? onError, - int maxRetries = 5, + Config config, float delaySeconds = 5.0f) { + if (!IsUri(url)) + { + onError?.Invoke("Invalid URI format."); + yield break; + } + + CommandWindow.Log($"Downloading: {url}"); + + var maxRetries = config.EnableRetry ? 5 : 1; for (int attempt = 1; attempt <= maxRetries; attempt++) { if (attempt > 1) @@ -42,18 +59,18 @@ public static IEnumerator DownloadWithRetry( CommandWindow.LogError($"Download failed after {maxRetries} attempts: {url}"); } - public static IEnumerator DownloadSingleAttempt( + private static IEnumerator DownloadSingleAttempt( string url, Action? onSuccess, Action? onError) { - var request = UnityEngine.Networking.UnityWebRequest.Get(url); + var request = UnityWebRequest.Get(url); request.SetRequestHeader("User-Agent", "RocketModFix"); request.redirectLimit = 5; yield return request.SendWebRequest(); - if (request.result != UnityEngine.Networking.UnityWebRequest.Result.Success) + if (request.result != UnityWebRequest.Result.Success) { var errorMessage = $"Download failed: {request.error} (HTTP {request.responseCode})"; onError?.Invoke(errorMessage); diff --git a/Rocket.AutoInstaller/Installation/ExtrasInstaller.cs b/Rocket.AutoInstaller/Installation/ExtrasInstaller.cs index 88188fd1..3745a37d 100644 --- a/Rocket.AutoInstaller/Installation/ExtrasInstaller.cs +++ b/Rocket.AutoInstaller/Installation/ExtrasInstaller.cs @@ -2,9 +2,7 @@ using System.Collections; using System.IO; using System.IO.Compression; -using System.Linq; using SDG.Unturned; -using UnityEngine.Networking; namespace Rocket.AutoInstaller.Installation { diff --git a/Rocket.AutoInstaller/Installation/GenericUriDownloader.cs b/Rocket.AutoInstaller/Installation/GenericUriDownloader.cs deleted file mode 100644 index 90d5a619..00000000 --- a/Rocket.AutoInstaller/Installation/GenericUriDownloader.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections; -using System.IO; -using SDG.Unturned; -using UnityEngine.Networking; - -namespace Rocket.AutoInstaller.Installation -{ - public static class GenericUriDownloader - { - public static bool IsUri(string path) - { - if (string.IsNullOrWhiteSpace(path)) - return false; - - return Uri.TryCreate(path, UriKind.Absolute, out _); - } - - public static IEnumerator DownloadFromUri(string uri, Action onSuccess, Action onError) - { - if (!IsUri(uri)) - { - onError?.Invoke("Invalid URI format."); - yield break; - } - - CommandWindow.Log($"Downloading: {uri}"); - - var request = UnityWebRequest.Get(uri); - request.SetRequestHeader("User-Agent", "RocketModFix"); - request.redirectLimit = 5; - - yield return request.SendWebRequest(); - - if (request.result != UnityWebRequest.Result.Success) - { - onError?.Invoke($"Failed to download from URI: {request.error} (Status: {request.responseCode})"); - yield break; - } - - var data = request.downloadHandler.data; - - onSuccess?.Invoke(data); - } - } -} diff --git a/Rocket.AutoInstaller/Installation/Installer.cs b/Rocket.AutoInstaller/Installation/Installer.cs index aa6aa7f7..e75e4ad5 100644 --- a/Rocket.AutoInstaller/Installation/Installer.cs +++ b/Rocket.AutoInstaller/Installation/Installer.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Reflection; using Newtonsoft.Json; -using Rocket.AutoInstaller; using SDG.Framework.Modules; using SDG.Unturned; using UnityEngine.Networking; @@ -20,7 +19,7 @@ public static IEnumerator Install(Config config) if (config.EnableCustomInstall == true && !string.IsNullOrWhiteSpace(config.CustomInstallPath)) { CommandWindow.Log("Installing from local path..."); - yield return LocalInstaller.InstallFromLocalPath(config.CustomInstallPath); + yield return LocalInstaller.Install(config.CustomInstallPath!, config); yield break; } @@ -31,24 +30,9 @@ public static IEnumerator Install(Config config) yield break; } - yield return InstallFromGitHub(config); - } - - public static IEnumerator InstallFromGitHub(Config config) - { var modulesDirectory = Path.Combine(ReadWrite.PATH, "Modules"); var releaseCache = new ReleaseCache(modulesDirectory); - if (releaseCache.IsRocketInstalled()) - { - var cachedEntry = releaseCache.GetCachedEntry(); - if (cachedEntry != null) - { - CommandWindow.Log($"Already installed: {cachedEntry.TagName}"); - yield break; - } - } - yield return FetchAndInstallLatestRelease(releaseCache, config); } @@ -64,6 +48,33 @@ private static IEnumerator FetchAndInstallLatestRelease(ReleaseCache releaseCach { var errorMessage = $"Failed to fetch releases: {request.error} (Status: {request.responseCode})"; CommandWindow.LogError(errorMessage); + + if (config.EnableCaching) + { + var cachedEntry = releaseCache.GetCachedEntry(); + if (cachedEntry != null && releaseCache.IsFileCached(cachedEntry.TagName)) + { + CommandWindow.LogWarning("Using cached version due to network error"); + var cachedData = releaseCache.LoadCachedFile(cachedEntry.TagName); + if (cachedData != null) + { + var mockRelease = new GitHubRelease + { + TagName = cachedEntry.TagName, + Name = cachedEntry.Name, + PublishedAt = cachedEntry.PublishedAt + }; + var mockAsset = new GitHubAsset + { + BrowserDownloadUrl = cachedEntry.DownloadUrl, + Size = cachedEntry.FileSize + }; + yield return ProcessModuleData(cachedData, mockRelease, mockAsset, releaseCache); + yield break; + } + } + } + throw new Exception(errorMessage); } @@ -87,37 +98,56 @@ private static IEnumerator FetchAndInstallLatestRelease(ReleaseCache releaseCach throw new Exception("Module asset not found"); } + if (config.EnableCaching && releaseCache.IsFileCached(latestRelease.TagName)) + { + CommandWindow.Log($"Using cached version: {latestRelease.TagName}"); + var cachedData = releaseCache.LoadCachedFile(latestRelease.TagName); + if (cachedData != null) + { + yield return ProcessModuleData(cachedData, latestRelease, moduleAsset, releaseCache); + yield break; + } + } + if (!releaseCache.IsNewerReleaseAvailable(latestRelease.TagName, latestRelease.PublishedAt)) { - CommandWindow.Log("No newer release available"); + var cachedEntry = releaseCache.GetCachedEntry(); + if (cachedEntry != null) + { + CommandWindow.Log($"Already up to date: {cachedEntry.TagName}"); + } + else + { + CommandWindow.Log($"Already up to date: {latestRelease.TagName}"); + } yield break; } CommandWindow.LogWarning($"Installing RocketModFix {latestRelease.TagName} ({latestRelease.PublishedAt:yyyy-MM-dd})"); byte[]? rawData = null; - if (config.EnableRetry) - { - yield return RetryHelper.DownloadWithRetry( - moduleAsset.BrowserDownloadUrl, - data => rawData = data, - error => throw new Exception(error), - maxRetries: 5, - delaySeconds: 5.0f); - } - else - { - yield return RetryHelper.DownloadSingleAttempt( - moduleAsset.BrowserDownloadUrl, - data => rawData = data, - error => throw new Exception(error)); - } + yield return DownloadHelper.Download( + moduleAsset.BrowserDownloadUrl, + data => rawData = data, + error => throw new Exception(error), + config, + delaySeconds: 5.0f); if (rawData == null) { throw new Exception("Failed to download module data"); } + if (config.EnableCaching) + { + releaseCache.SaveCachedFile(latestRelease.TagName, rawData); + } + + yield return ProcessModuleData(rawData, latestRelease, moduleAsset, releaseCache); + } + + private static IEnumerator ProcessModuleData(byte[] rawData, GitHubRelease latestRelease, GitHubAsset moduleAsset, ReleaseCache releaseCache) + { var releaseEntries = GetReleaseEntries(rawData); byte[]? rocketModuleData = null; List rocketLibraries = []; @@ -150,8 +180,7 @@ private static IEnumerator FetchAndInstallLatestRelease(ReleaseCache releaseCach var rocketModule = Assembly.Load(rocketModuleData); var types = GetLoadableTypes(rocketModule); - var moduleType = types.FirstOrDefault( - x => x.IsAbstract == false && typeof(IModuleNexus).IsAssignableFrom(x)); + var moduleType = types.FirstOrDefault(x => !x.IsAbstract && typeof(IModuleNexus).IsAssignableFrom(x)); if (moduleType == null) { CommandWindow.LogError("Rocket module type not found"); @@ -191,6 +220,7 @@ private static bool IsRocketModFixModule(GitHubAsset asset) { return asset.Name.Equals("Rocket.Unturned.Module.zip", StringComparison.Ordinal); } + private static List GetReleaseEntries(byte[] assetData) { var entries = new List(); diff --git a/Rocket.AutoInstaller/Installation/LocalInstaller.cs b/Rocket.AutoInstaller/Installation/LocalInstaller.cs index c20c71b9..e728a123 100644 --- a/Rocket.AutoInstaller/Installation/LocalInstaller.cs +++ b/Rocket.AutoInstaller/Installation/LocalInstaller.cs @@ -12,36 +12,34 @@ namespace Rocket.AutoInstaller.Installation { public class LocalInstaller { - public static IEnumerator InstallFromLocalPath(string localPath) + public static IEnumerator Install(string path, Config config) { - if (!PathValidator.ValidateLocalBuildPath(localPath, out var errorMessage)) + if (!PathValidator.ValidatePath(path, out var errorMessage)) { CommandWindow.LogError($"Local install failed: {errorMessage}"); - PathValidator.LogValidationResult(localPath, false, errorMessage); yield break; } - PathValidator.LogValidationResult(localPath, true); - CommandWindow.Log($"Installing from: {localPath}"); + CommandWindow.Log($"Installing from: {path}"); List releaseEntries = []; - if (GenericUriDownloader.IsUri(localPath)) + if (DownloadHelper.IsUri(path)) { - yield return DownloadAndProcessGenericUri(localPath, entries => releaseEntries = entries); + yield return DownloadAndProcessGenericUri(path, entries => releaseEntries = entries, config); } else { try { - if (File.Exists(localPath) && localPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) + if (File.Exists(path) && path.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) { - var zipData = File.ReadAllBytes(localPath); + var zipData = File.ReadAllBytes(path); releaseEntries = GetReleaseEntries(zipData); } else { - releaseEntries = GetReleaseEntriesFromDirectory(localPath); + releaseEntries = GetReleaseEntriesFromDirectory(path); } } catch (Exception ex) @@ -114,7 +112,7 @@ public static IEnumerator InstallFromLocalPath(string localPath) } plugin.initialize(); - CommandWindow.LogWarning($"Installed from local build: {localPath}"); + CommandWindow.LogWarning($"Installed from local build: {path}"); } private static List GetReleaseEntries(byte[] assetData) @@ -174,13 +172,13 @@ private static List GetReleaseEntriesFromDirectory(string director return entries; } - private static IEnumerator DownloadAndProcessGenericUri(string uri, Action> onComplete) + private static IEnumerator DownloadAndProcessGenericUri(string uri, Action> onComplete, Config config) { var entries = new List(); var downloadSucceeded = false; var downloadError = string.Empty; - yield return GenericUriDownloader.DownloadFromUri(uri, + yield return DownloadHelper.Download(uri, data => { entries = GetReleaseEntries(data); downloadSucceeded = true; @@ -188,7 +186,8 @@ private static IEnumerator DownloadAndProcessGenericUri(string uri, Action { downloadError = error; downloadSucceeded = false; - }); + }, + config); if (!downloadSucceeded) { diff --git a/Rocket.AutoInstaller/Installation/PathValidator.cs b/Rocket.AutoInstaller/Installation/PathValidator.cs index 69165f98..ff0a0479 100644 --- a/Rocket.AutoInstaller/Installation/PathValidator.cs +++ b/Rocket.AutoInstaller/Installation/PathValidator.cs @@ -6,7 +6,7 @@ namespace Rocket.AutoInstaller.Installation { public static class PathValidator { - public static bool ValidateLocalBuildPath(string path, out string errorMessage) + public static bool ValidatePath(string path, out string errorMessage) { errorMessage = string.Empty; @@ -16,7 +16,7 @@ public static bool ValidateLocalBuildPath(string path, out string errorMessage) return false; } - if (GenericUriDownloader.IsUri(path)) + if (DownloadHelper.IsUri(path)) { return ValidateUri(path, out errorMessage); } @@ -31,7 +31,7 @@ public static bool ValidateLocalBuildPath(string path, out string errorMessage) return ValidateDirectory(path, out errorMessage); } - errorMessage = $"Path does not exist (neither file nor directory): {path}"; + errorMessage = $"Path does not exist (neither file, directory, nor valid URL): {path}"; return false; } @@ -124,17 +124,5 @@ private static bool ValidateDirectory(string directoryPath, out string errorMess errorMessage = $"Neither Rocket.Unturned.dll nor Rocket.Unturned.Module.zip found in: {directoryPath}"; return false; } - - public static void LogValidationResult(string path, bool isValid, string errorMessage = "") - { - if (isValid) - { - CommandWindow.Log($"Path validated: {path}"); - } - else - { - CommandWindow.LogError($"Path validation failed: {errorMessage}"); - } - } } } diff --git a/Rocket.AutoInstaller/Installation/ReleaseCache.cs b/Rocket.AutoInstaller/Installation/ReleaseCache.cs index a0597991..a7b74752 100644 --- a/Rocket.AutoInstaller/Installation/ReleaseCache.cs +++ b/Rocket.AutoInstaller/Installation/ReleaseCache.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; @@ -10,13 +9,45 @@ namespace Rocket.AutoInstaller.Installation public class ReleaseCache { private const string CacheFileName = "rocket_cache.json"; + private const string CacheDirectoryName = "cache"; private readonly string _cacheFilePath; private readonly string _modulesDirectory; + private readonly string _cacheDirectory; public ReleaseCache(string modulesDirectory) { _modulesDirectory = modulesDirectory; - _cacheFilePath = Path.Combine(modulesDirectory, CacheFileName); + + var autoInstallerDirectory = FindAutoInstallerDirectory(modulesDirectory); + if (autoInstallerDirectory == null) + { + throw new Exception("Rocket.AutoInstaller module directory not found"); + } + + _cacheFilePath = Path.Combine(autoInstallerDirectory, CacheFileName); + _cacheDirectory = Path.Combine(autoInstallerDirectory, CacheDirectoryName); + + if (!Directory.Exists(_cacheDirectory)) + { + Directory.CreateDirectory(_cacheDirectory); + } + } + + private static string? FindAutoInstallerDirectory(string modulesDirectory) + { + try + { + var autoInstallerFiles = Directory.GetFiles(modulesDirectory, "Rocket.AutoInstaller.dll", SearchOption.AllDirectories); + if (autoInstallerFiles.Length > 0) + { + return Path.GetDirectoryName(autoInstallerFiles[0]); + } + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Failed to find Rocket.AutoInstaller directory: {ex}"); + } + return null; } public CacheEntry? GetCachedEntry() @@ -82,8 +113,8 @@ public void ClearCache() if (File.Exists(_cacheFilePath)) { File.Delete(_cacheFilePath); - CommandWindow.Log("Cache cleared"); } + ClearCachedFiles(); } catch (Exception ex) { @@ -96,6 +127,71 @@ public bool IsRocketInstalled() var rocketFiles = Directory.GetFiles(_modulesDirectory, "Rocket.Unturned.dll", SearchOption.AllDirectories); return rocketFiles.Any(); } + + public string GetCachedFilePath(string tagName) + { + var fileName = $"Rocket.Unturned.Module.{tagName}.zip"; + return Path.Combine(_cacheDirectory, fileName); + } + + public bool IsFileCached(string tagName) + { + var cachedFilePath = GetCachedFilePath(tagName); + return File.Exists(cachedFilePath); + } + + public void SaveCachedFile(string tagName, byte[] fileData) + { + try + { + var cachedFilePath = GetCachedFilePath(tagName); + File.WriteAllBytes(cachedFilePath, fileData); + CommandWindow.Log($"Cached file: {Path.GetFileName(cachedFilePath)}"); + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Failed to cache file: {ex}"); + } + } + + public byte[]? LoadCachedFile(string tagName) + { + try + { + var cachedFilePath = GetCachedFilePath(tagName); + if (File.Exists(cachedFilePath)) + { + var fileData = File.ReadAllBytes(cachedFilePath); + CommandWindow.Log($"Loaded from cache: {Path.GetFileName(cachedFilePath)}"); + return fileData; + } + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Failed to load cached file: {ex}"); + } + return null; + } + + public void ClearCachedFiles() + { + try + { + if (Directory.Exists(_cacheDirectory)) + { + var files = Directory.GetFiles(_cacheDirectory, "*.zip"); + foreach (var file in files) + { + File.Delete(file); + } + CommandWindow.Log($"Cleared {files.Length} cached files"); + } + } + catch (Exception ex) + { + CommandWindow.LogWarning($"Failed to clear cached files: {ex}"); + } + } } public class CacheEntry @@ -104,7 +200,7 @@ public class CacheEntry public string Name { get; set; } public DateTime PublishedAt { get; set; } public string DownloadUrl { get; set; } - public long FileSize { get; set; } + public int FileSize { get; set; } public DateTime CachedAt { get; set; } public CacheEntry() diff --git a/Rocket.AutoInstaller/Module.cs b/Rocket.AutoInstaller/Module.cs index 12767198..68e467aa 100644 --- a/Rocket.AutoInstaller/Module.cs +++ b/Rocket.AutoInstaller/Module.cs @@ -18,6 +18,7 @@ public class Config public bool BlockIfRocketInstalled { get; set; } public bool AutoInstallRocketFromExtras { get; set; } public bool EnableRetry { get; set; } + public bool EnableCaching { get; set; } } /// @@ -59,6 +60,7 @@ public void initialize() BlockIfRocketInstalled = true, AutoInstallRocketFromExtras = false, EnableRetry = true, + EnableCaching = true, }; File.WriteAllText(configPath, JsonConvert.SerializeObject(config, Formatting.Indented)); } diff --git a/Rocket.AutoInstaller/README.md b/Rocket.AutoInstaller/README.md index 7b3bfcc5..8232587b 100644 --- a/Rocket.AutoInstaller/README.md +++ b/Rocket.AutoInstaller/README.md @@ -6,6 +6,8 @@ Auto-installer for RocketModFix. Downloads and installs the latest version from Just drop the module in your `Modules` folder and start your server. It will automatically download and install the latest RocketModFix. +**Important:** Before using the auto-installer, remove any manually installed `Rocket.Unturned` from your `Modules` directory to avoid conflicts. + ## Configuration Edit `config.json` to customize installation behavior: @@ -16,7 +18,8 @@ Edit `config.json` to customize installation behavior: "CustomInstallPath": "", "BlockIfRocketInstalled": true, "AutoInstallRocketFromExtras": false, - "EnableRetry": true + "EnableRetry": true, + "EnableCaching": true } ``` @@ -25,6 +28,7 @@ Edit `config.json` to customize installation behavior: **For regular users:** - `BlockIfRocketInstalled` - Prevent installation if Rocket is already installed - `EnableRetry` - Enable retry mechanism for failed downloads (5 attempts, 5s delay) +- `EnableCaching` - Enable file caching for faster startup and offline support **For developers:** - `EnableCustomInstall` - Enable local installation instead of GitHub @@ -58,15 +62,6 @@ For developers who want to test their own builds without manually copying files **Note:** GitHub Actions artifacts are currently not supported cause require authentication and aren't suitable for public downloads. See [GitHub issue #51](https://github.com/actions/upload-artifact/issues/51) for details. -## Features - -- Auto-install from GitHub - Downloads latest release automatically -- Local build support - Install from zip files, directories, or URLs -- Smart caching - Only downloads when newer versions are available -- Retry mechanism - Handles network issues with automatic retries -- Extras integration - Auto-install from server's Extras folder -- Safety checks - Prevents conflicts with existing installations - ## Plans If you want to implement one of the plans or have better ideas, feel free to let us know! diff --git a/Rocket.AutoInstaller/config.json b/Rocket.AutoInstaller/config.json index 8dbd80f7..ed6995db 100644 --- a/Rocket.AutoInstaller/config.json +++ b/Rocket.AutoInstaller/config.json @@ -3,5 +3,6 @@ "CustomInstallPath": "", "BlockIfRocketInstalled": true, "AutoInstallRocketFromExtras": false, - "EnableRetry": true + "EnableRetry": true, + "EnableCaching": true } \ No newline at end of file From 20179116cdad1236e50f444b008490ba208ae4a6 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 14 Sep 2025 13:52:54 +0300 Subject: [PATCH 14/42] Bump Unturned redist --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index 10902fba..07054174 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All From 3d8b43415804e5f9b9c5b32d0b6c2d75d3e26ede Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 14 Sep 2025 13:53:24 +0300 Subject: [PATCH 15/42] Bump Unturned redist --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index 07054174..12968e7b 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All From d98933de20cf91f226472324a1e6de12b1070085 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 09:27:28 +0000 Subject: [PATCH 16/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.25.8.2 to 3.25.8.3 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.25.8.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 0dfa9eda..cf99f2f5 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 9b96ef1e..9d3111d3 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 6dd13776..a2a39bcd 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From ee21d149f3f517bad4fe50b5b93e11821fadde0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 09:30:18 +0000 Subject: [PATCH 17/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.25.8.3 to 3.25.9 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.25.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index cf99f2f5..8893af0b 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 9d3111d3..1675e875 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index a2a39bcd..e598fd2a 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From 8f87adfcf9ac2be642f78e78de9a9b65f0bce6d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 09:30:36 +0000 Subject: [PATCH 18/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.25.9 to 3.25.9.1 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.25.9.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 8893af0b..ab637b8e 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 1675e875..edc83743 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index e598fd2a..f5d771fe 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From e795ba3e66fd2d0eed42c8f74fd91323b9851efd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 11:02:49 +0000 Subject: [PATCH 19/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.25.9.1 to 3.25.9.2 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.25.9.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index ab637b8e..d864ad4f 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index edc83743..867e6eb6 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index f5d771fe..21d17f52 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From 99ae5764144dda1de6f97c9f8468507c756e4bfb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 09:49:17 +0000 Subject: [PATCH 20/42] github-actions(deps): bump actions/upload-artifact from 4 to 5 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/RocketModFix.yaml | 4 ++-- .github/workflows/compatibility-check.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index 256124cf..c7144d06 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -72,14 +72,14 @@ jobs: github_token: ${{ secrets.PAT }} - name: Upload Rocket.AutoInstaller - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: Rocket.AutoInstaller path: "./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller/" if-no-files-found: error - name: Upload Rocket.Unturned.Module - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: Rocket.Unturned.Module path: "./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned/" diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index 27163b0f..aa6ce6fe 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -91,7 +91,7 @@ jobs: --suppression-output-file ./generated-api-suppressions.xml - name: Upload generated suppression file - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: generated-api-suppressions path: ./generated-api-suppressions.xml From 76fd12a0d0a2edfa8eef012427732ad4b83fc3c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 09:26:28 +0000 Subject: [PATCH 21/42] github-actions(deps): bump actions/checkout from 5 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/Rocket.API.yaml | 4 ++-- .github/workflows/Rocket.Core.yaml | 4 ++-- .github/workflows/Rocket.Unturned.yaml | 4 ++-- .github/workflows/RocketModFix.yaml | 4 ++-- .github/workflows/compatibility-check.yaml | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/Rocket.API.yaml b/.github/workflows/Rocket.API.yaml index 36a822bf..06ad8c54 100644 --- a/.github/workflows/Rocket.API.yaml +++ b/.github/workflows/Rocket.API.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -41,7 +41,7 @@ jobs: needs: Compatibility-Check steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/Rocket.Core.yaml b/.github/workflows/Rocket.Core.yaml index 1c8304cd..7abd2970 100644 --- a/.github/workflows/Rocket.Core.yaml +++ b/.github/workflows/Rocket.Core.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -41,7 +41,7 @@ jobs: needs: Compatibility-Check steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/Rocket.Unturned.yaml b/.github/workflows/Rocket.Unturned.yaml index c738a556..b788c1e7 100644 --- a/.github/workflows/Rocket.Unturned.yaml +++ b/.github/workflows/Rocket.Unturned.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -41,7 +41,7 @@ jobs: needs: Compatibility-Check steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index c7144d06..e5b687bf 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -44,7 +44,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index aa6ce6fe..0e9c152f 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -16,10 +16,10 @@ jobs: steps: - name: Checkout current fork - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Checkout original repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: repository: SmartlyDressedGames/Legally-Distinct-Missile path: original-repo From 1b086f76f82c22966e4d208db700513583a98622 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:21:21 +0000 Subject: [PATCH 22/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.25.9.2 to 3.25.10.1 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.25.10.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.25.10.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index d864ad4f..80bb0ed2 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 867e6eb6..0600755e 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 21d17f52..50e4ec39 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From 421c98cba3ef9a9da1806440951eebac2ea24b56 Mon Sep 17 00:00:00 2001 From: Nelson Sexton Date: Mon, 20 Oct 2025 12:36:57 -0600 Subject: [PATCH 23/42] Handle assemblies with null version. Thanks to @Senior-S and @DanielWillett in issue #84! --- .../Plugins/RocketPluginManager.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs b/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs index 403d641f..d8398720 100644 --- a/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs +++ b/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs @@ -45,18 +45,31 @@ private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) try { AssemblyName requestedName = new AssemblyName(args.Name); - var bestMatch = libraries.FirstOrDefault(lib => string.Equals(lib.Key.Name, requestedName.Name) && lib.Key.Version >= requestedName.Version); + var bestMatch = libraries.Where(lib => string.Equals(lib.Key.Name, requestedName.Name)).OrderByDescending(lib => lib.Key.Version).FirstOrDefault(); if (!string.IsNullOrEmpty(bestMatch.Value)) { + // https://github.com/SmartlyDressedGames/Legally-Distinct-Missile/issues/84 + if (requestedName.Version != null) + { + if (bestMatch.Key.Version == null) + { + Logging.Logger.LogWarning($"Rocket best match for dependency {requestedName} has no configued version: {bestMatch.Key} at {bestMatch.Value}"); + } + else if (bestMatch.Key.Version < requestedName.Version) + { + Logging.Logger.LogWarning($"Rocket best match for dependency {requestedName} version is older than requested: {bestMatch.Key} at {bestMatch.Value}"); + } + } + return Assembly.Load(File.ReadAllBytes(bestMatch.Value)); } } catch (Exception ex) { - Logging.Logger.LogException(ex, "Caught exception resolving dependency: " + args.Name); + Logging.Logger.LogException(ex, "Rocket caught exception resolving dependency: " + args.Name); } - Logging.Logger.LogError("Could not find dependency: " + args.Name); + Logging.Logger.LogError("Rocket could not find dependency: " + args.Name); return null; } @@ -84,6 +97,11 @@ private void loadPlugins() libraries.Add(pair.Key,pair.Value); } + foreach (KeyValuePair pair in libraries) + { + Logging.Logger.Log($"Rocket dependency registered: {pair.Key} at {pair.Value}"); + } + pluginAssemblies = LoadAssembliesFromDirectory(Environment.PluginsDirectory); List pluginImplemenations = RocketHelper.GetTypesFromInterface(pluginAssemblies, "IRocketPlugin"); foreach (Type pluginType in pluginImplemenations) From 51c9f188f4c47b05828ecc477071e58a5df87e59 Mon Sep 17 00:00:00 2001 From: Nelson Sexton Date: Thu, 23 Oct 2025 10:15:00 -0600 Subject: [PATCH 24/42] Revise assembly versioning to first prefer exact match (thanks @Paradox304!) --- Rocket/Rocket.Core/Plugins/RocketPluginManager.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs b/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs index d8398720..c9ec8b40 100644 --- a/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs +++ b/Rocket/Rocket.Core/Plugins/RocketPluginManager.cs @@ -45,7 +45,15 @@ private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) try { AssemblyName requestedName = new AssemblyName(args.Name); - var bestMatch = libraries.Where(lib => string.Equals(lib.Key.Name, requestedName.Name)).OrderByDescending(lib => lib.Key.Version).FirstOrDefault(); + var matchesByName = libraries.Where(lib => string.Equals(lib.Key.Name, requestedName.Name)); + + // Prefer exactly-matching version if possible. + var bestMatch = matchesByName.FirstOrDefault(lib => lib.Key.Version == requestedName.Version); + if (string.IsNullOrEmpty(bestMatch.Value)) + { + // Otherwise, fallback to highest version. + bestMatch = matchesByName.OrderByDescending(lib => lib.Key.Version).FirstOrDefault(); + } if (!string.IsNullOrEmpty(bestMatch.Value)) { // https://github.com/SmartlyDressedGames/Legally-Distinct-Missile/issues/84 From f96bb0f9d3226971c8f839101f33ef6fc4312ee1 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 6 Dec 2025 12:49:26 +0200 Subject: [PATCH 25/42] Bump UnityEngine redist package --- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 80bb0ed2..1093aec2 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -13,7 +13,7 @@ - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 0600755e..3003506d 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -7,7 +7,7 @@ - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 50e4ec39..9a27c5b9 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -18,7 +18,7 @@ - + All From b9a1352d03387370782120317ba4e2e43c5f7c3f Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 6 Dec 2025 15:29:39 +0200 Subject: [PATCH 26/42] Add AutoInstaller to .sln --- Rocket.Unturned.sln | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Rocket.Unturned.sln b/Rocket.Unturned.sln index 7f7d2278..dcce1a2e 100644 --- a/Rocket.Unturned.sln +++ b/Rocket.Unturned.sln @@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Core", "Rocket\Rocke EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.API", "Rocket\Rocket.API\Rocket.API.csproj", "{FB0FDFB9-D500-4E0F-9467-CA404E64C1E0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.AutoInstaller", "Rocket.AutoInstaller\Rocket.AutoInstaller.csproj", "{F7B14393-5418-4D51-B342-5EC2A51FC62B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -101,6 +103,24 @@ Global {FB0FDFB9-D500-4E0F-9467-CA404E64C1E0}.Release|x64.Build.0 = Release|Any CPU {FB0FDFB9-D500-4E0F-9467-CA404E64C1E0}.Release|x86.ActiveCfg = Release|Any CPU {FB0FDFB9-D500-4E0F-9467-CA404E64C1E0}.Release|x86.Build.0 = Release|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Debug|x64.ActiveCfg = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Debug|x64.Build.0 = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Debug|x86.ActiveCfg = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Debug|x86.Build.0 = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Local|Any CPU.ActiveCfg = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Local|Any CPU.Build.0 = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Local|x64.ActiveCfg = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Local|x64.Build.0 = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Local|x86.ActiveCfg = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Local|x86.Build.0 = Debug|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Release|Any CPU.Build.0 = Release|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Release|x64.ActiveCfg = Release|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Release|x64.Build.0 = Release|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Release|x86.ActiveCfg = Release|Any CPU + {F7B14393-5418-4D51-B342-5EC2A51FC62B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 02b7b72030f4f738afab231dd972f8722cfce035 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 6 Dec 2025 15:33:22 +0200 Subject: [PATCH 27/42] Bump redists and runtimelibs --- .../System.IO.Compression.FileSystem.dll | Bin 18432 -> 18432 bytes .../RuntimeLibs/System.IO.Compression.dll | Bin 114688 -> 115712 bytes .../Rocket.AutoInstaller.csproj | 10 ++-------- .../System.IO.Compression.FileSystem.dll | Bin 18432 -> 18432 bytes .../RuntimeLibs/System.IO.Compression.dll | Bin 114688 -> 115712 bytes Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- .../Rocket.Core.Tests.csproj | 4 ++-- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 9 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Rocket.AutoInstaller/Module/RuntimeLibs/System.IO.Compression.FileSystem.dll b/Rocket.AutoInstaller/Module/RuntimeLibs/System.IO.Compression.FileSystem.dll index 59e95a23ba7a55f9df95d1b9a8394079f46880e4..50b74f814eb9842193525501ee9031a53bf1c70c 100644 GIT binary patch delta 5112 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 delta 4679 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⩔Bn1sNVyZuk<9~9# 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 E0b#g0dH?_b literal 114688 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þ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 y+NY - + All - + All - - - Module\RuntimeLibs\System.IO.Compression.dll - - - Always diff --git a/Rocket.Unturned/Module/RuntimeLibs/System.IO.Compression.FileSystem.dll b/Rocket.Unturned/Module/RuntimeLibs/System.IO.Compression.FileSystem.dll index 59e95a23ba7a55f9df95d1b9a8394079f46880e4..50b74f814eb9842193525501ee9031a53bf1c70c 100644 GIT binary patch delta 5112 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 delta 4679 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⩔Bn1sNVyZuk<9~9# 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 E0b#g0dH?_b literal 114688 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þ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 y+NY - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 3003506d..a90f9577 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -7,7 +7,7 @@ - + All diff --git a/Rocket/Rocket.Core.Tests/Rocket.Core.Tests.csproj b/Rocket/Rocket.Core.Tests/Rocket.Core.Tests.csproj index b3c5be20..df54900d 100644 --- a/Rocket/Rocket.Core.Tests/Rocket.Core.Tests.csproj +++ b/Rocket/Rocket.Core.Tests/Rocket.Core.Tests.csproj @@ -12,10 +12,10 @@ - + All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 9a27c5b9..9b299a7e 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -18,7 +18,7 @@ - + All From 2ef5880c8a36f1784725042719c0b8a8ea0d9ea1 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 6 Dec 2025 17:51:16 +0200 Subject: [PATCH 28/42] Update obsolete redist url --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d8906769..3d6c0dca 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,9 @@ See here details [how to contribute][contributing]. ### Redist -[![RocketModFix.Unturned.Redist][badge_RocketModFix.Unturned.Redist]][nuget_package_RocketModFix.Unturned.Redist] +[![RocketModFix.Unturned.Redist.Client][badge_RocketModFix.Unturned.Redist.Client]][nuget_package_RocketModFix.Unturned.Redist.Client] + +[![RocketModFix.Unturned.Redist.Server][badge_RocketModFix.Unturned.Redist.Server]][nuget_package_RocketModFix.Unturned.Redist.Server] [![RocketModFix.UnityEngine.Redist][badge_RocketModFix.UnityEngine.Redist]][nuget_package_RocketModFix.UnityEngine.Redist] @@ -141,8 +143,10 @@ On the 2nd of June 2020 fr34kyn01535 requested the fork be rebranded to help dis [openmod_github_repository]: https://github.com/openmod/openmod [ldm_github_repository]: https://github.com/SmartlyDressedGames/Legally-Distinct-Missile -[nuget_package_RocketModFix.Unturned.Redist]: https://www.nuget.org/packages/RocketModFix.Unturned.Redist -[badge_RocketModFix.Unturned.Redist]: https://img.shields.io/nuget/v/RocketModFix.Unturned.Redist?label=RocketModFix.Unturned.Redist&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FRocketModFix.Unturned.Redist +[nuget_package_RocketModFix.Unturned.Redist.Client]: https://www.nuget.org/packages/RocketModFix.Unturned.Redist.Client +[badge_RocketModFix.Unturned.Redist.Client]: https://img.shields.io/nuget/v/RocketModFix.Unturned.Redist.Client?label=RocketModFix.Unturned.Redist.Client&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FRocketModFix.Unturned.Redist.Client +[nuget_package_RocketModFix.Unturned.Redist.Server]: https://www.nuget.org/packages/RocketModFix.Unturned.Redist.Server +[badge_RocketModFix.Unturned.Redist.Server]: https://img.shields.io/nuget/v/RocketModFix.Unturned.Redist.Server?label=RocketModFix.Unturned.Redist.Server&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FRocketModFix.Unturned.Redist.Server [nuget_package_RocketModFix.UnityEngine.Redist]: https://www.nuget.org/packages/RocketModFix.UnityEngine.Redist [badge_RocketModFix.UnityEngine.Redist]: https://img.shields.io/nuget/v/RocketModFix.UnityEngine.Redist?label=RocketModFix.UnityEngine.Redist&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FRocketModFix.UnityEngine.Redist [nuget_package_RocketModFix.Rocket.API]: https://www.nuget.org/packages/RocketModFix.Rocket.API @@ -150,4 +154,4 @@ On the 2nd of June 2020 fr34kyn01535 requested the fork be rebranded to help dis [nuget_package_RocketModFix.Rocket.Core]: https://www.nuget.org/packages/RocketModFix.Rocket.Core [badge_RocketModFix.Rocket.Core]: https://img.shields.io/nuget/v/RocketModFix.Rocket.Core?label=RocketModFix.Rocket.Core&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FRocketModFix.Rocket.Core [nuget_package_RocketModFix.Rocket.Unturned]: https://www.nuget.org/packages/RocketModFix.Rocket.Unturned -[badge_RocketModFix.Rocket.Unturned]: https://img.shields.io/nuget/v/RocketModFix.Rocket.Unturned?label=RocketModFix.Rocket.Unturned&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FRocketModFix.Rocket.Unturned \ No newline at end of file +[badge_RocketModFix.Rocket.Unturned]: https://img.shields.io/nuget/v/RocketModFix.Rocket.Unturned?label=RocketModFix.Rocket.Unturned&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FRocketModFix.Rocket.Unturned From d4938681d000f7d01942135159093e66249a918c Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 7 Dec 2025 08:54:43 +0200 Subject: [PATCH 29/42] Remove --skip-duplicate --- .github/actions/nuget-pack/action.yaml | 2 +- .github/actions/project-build-windows/action.yaml | 4 ++-- .github/actions/project-build/action.yaml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/nuget-pack/action.yaml b/.github/actions/nuget-pack/action.yaml index a139a899..66a0030a 100644 --- a/.github/actions/nuget-pack/action.yaml +++ b/.github/actions/nuget-pack/action.yaml @@ -19,6 +19,6 @@ runs: shell: bash - name: Push to NuGet (Release) run: if ${{ inputs.nuget_push == 'true' }}; then - dotnet nuget push *.nupkg --skip-duplicate --api-key ${{ inputs.nuget_key }} --source https://api.nuget.org/v3/index.json; + dotnet nuget push *.nupkg --api-key ${{ inputs.nuget_key }} --source https://api.nuget.org/v3/index.json; fi shell: bash \ No newline at end of file diff --git a/.github/actions/project-build-windows/action.yaml b/.github/actions/project-build-windows/action.yaml index 979fbb3b..f8c69807 100644 --- a/.github/actions/project-build-windows/action.yaml +++ b/.github/actions/project-build-windows/action.yaml @@ -84,7 +84,7 @@ runs: if: | inputs.nuget_push == 'true' && (github.event_name == 'push' || github.event_name == 'create' && github.event.ref_type == 'tag') - run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.github_token }} --skip-duplicate --source https://nuget.pkg.github.com/RocketModFix/index.json; + run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.github_token }} --source https://nuget.pkg.github.com/RocketModFix/index.json; shell: bash # Push to NuGet on each tag, but only if the tag is not a pre-release version @@ -92,5 +92,5 @@ runs: if: | inputs.nuget_push == 'true' && steps.check-prerelease.outputs.is_prerelease == 'false' && github.event_name == 'create' && github.event.ref_type == 'tag' - run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.nuget_key }} --skip-duplicate --source https://api.nuget.org/v3/index.json; + run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.nuget_key }} --source https://api.nuget.org/v3/index.json; shell: bash diff --git a/.github/actions/project-build/action.yaml b/.github/actions/project-build/action.yaml index d6ceb878..9813f6a6 100644 --- a/.github/actions/project-build/action.yaml +++ b/.github/actions/project-build/action.yaml @@ -108,7 +108,7 @@ runs: if: | inputs.nuget_push == 'true' && (github.event_name == 'push' || github.event_name == 'create' && github.event.ref_type == 'tag') - run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.github_token }} --skip-duplicate --source https://nuget.pkg.github.com/RocketModFix/index.json; + run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.github_token }} --source https://nuget.pkg.github.com/RocketModFix/index.json; shell: bash # Push to NuGet on each tag, but only if the tag is not a pre-release version @@ -116,5 +116,5 @@ runs: if: | inputs.nuget_push == 'true' && steps.check-prerelease.outputs.is_prerelease == 'false' && github.event_name == 'create' && github.event.ref_type == 'tag' - run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.nuget_key }} --skip-duplicate --source https://api.nuget.org/v3/index.json; + run: dotnet nuget push ${{ inputs.project_path }}/bin/Release/*.nupkg --api-key ${{ inputs.nuget_key }} --source https://api.nuget.org/v3/index.json; shell: bash \ No newline at end of file From 03fa746b03a3a1c71e8b59b649be058c3fa0c6b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:25:22 +0000 Subject: [PATCH 30/42] github-actions(deps): bump actions/upload-artifact from 5 to 6 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/RocketModFix.yaml | 4 ++-- .github/workflows/compatibility-check.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index e5b687bf..49a234b0 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -72,14 +72,14 @@ jobs: github_token: ${{ secrets.PAT }} - name: Upload Rocket.AutoInstaller - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: Rocket.AutoInstaller path: "./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller/" if-no-files-found: error - name: Upload Rocket.Unturned.Module - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: Rocket.Unturned.Module path: "./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned/" diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index 0e9c152f..36c60374 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -91,7 +91,7 @@ jobs: --suppression-output-file ./generated-api-suppressions.xml - name: Upload generated suppression file - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: generated-api-suppressions path: ./generated-api-suppressions.xml From 098beb1c1e4651788fa3b03ba0c9406bb029961b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 09:46:37 +0000 Subject: [PATCH 31/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.25.10.1 to 3.26.1.1 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.1.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.1.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index 5400632c..b5ed2486 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 97a7cf4c..78ed32e2 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index a90f9577..39d799db 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 9b299a7e..4d624f1e 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From 18411d7ff3fa3bab0f529f417a73980a0948841b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 09:10:36 +0000 Subject: [PATCH 32/42] github-actions(deps): bump actions/upload-artifact from 6 to 7 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/RocketModFix.yaml | 4 ++-- .github/workflows/compatibility-check.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index 49a234b0..71e875fa 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -72,14 +72,14 @@ jobs: github_token: ${{ secrets.PAT }} - name: Upload Rocket.AutoInstaller - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: Rocket.AutoInstaller path: "./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller/" if-no-files-found: error - name: Upload Rocket.Unturned.Module - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: Rocket.Unturned.Module path: "./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned/" diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index 36c60374..172e6fa9 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -91,7 +91,7 @@ jobs: --suppression-output-file ./generated-api-suppressions.xml - name: Upload generated suppression file - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: generated-api-suppressions path: ./generated-api-suppressions.xml From 846f84bdbf3dc81a3434455ec622fd13a5cc21bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:16:56 +0000 Subject: [PATCH 33/42] github-actions(deps): bump ncipollo/release-action from 1.20.0 to 1.21.0 Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.20.0 to 1.21.0. - [Release notes](https://github.com/ncipollo/release-action/releases) - [Commits](https://github.com/ncipollo/release-action/compare/v1.20.0...v1.21.0) --- updated-dependencies: - dependency-name: ncipollo/release-action dependency-version: 1.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/RocketModFix.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index 49a234b0..88620724 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -93,7 +93,7 @@ jobs: - name: Create Release if: github.event_name == 'create' && github.event.ref_type == 'tag' - uses: ncipollo/release-action@v1.20.0 + uses: ncipollo/release-action@v1.21.0 with: name: RocketModFix Release v${{ steps.auto-installer-build.outputs.version }} tag: ${{ steps.auto-installer-build.outputs.version }} From ad6aa870a39404cefe82d4b48c5b26c32e706ffb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 09:16:21 +0000 Subject: [PATCH 34/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.26.1.1 to 3.26.3.2 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index b5ed2486..e8134952 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 78ed32e2..30abe7da 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 39d799db..126d960f 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 4d624f1e..69c46ce4 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From ac5d4dbae672c3bc53d88bf878e9d836098d7747 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sat, 13 Jun 2026 12:31:00 +0300 Subject: [PATCH 35/42] ci: replace personal PAT with built-in GITHUB_TOKEN Switch all workflows from the account-bound secrets.PAT to the repository-scoped secrets.GITHUB_TOKEN, and grant the minimal job-level permissions the token needs: - Rocket.API/Core/Unturned build jobs: packages: write (publish to GitHub Packages) + contents: read. - RocketModFix build job: contents: write (create GitHub Release via ncipollo/release-action). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/Rocket.API.yaml | 5 ++++- .github/workflows/Rocket.Core.yaml | 5 ++++- .github/workflows/Rocket.Unturned.yaml | 5 ++++- .github/workflows/RocketModFix.yaml | 8 +++++--- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Rocket.API.yaml b/.github/workflows/Rocket.API.yaml index 06ad8c54..c7850c79 100644 --- a/.github/workflows/Rocket.API.yaml +++ b/.github/workflows/Rocket.API.yaml @@ -39,6 +39,9 @@ jobs: name: "Rocket.API Build" runs-on: ubuntu-latest needs: Compatibility-Check + permissions: + contents: read + packages: write steps: - uses: actions/checkout@v6 @@ -54,6 +57,6 @@ jobs: id: project-build with: project_path: Rocket/Rocket.API - github_token: ${{ secrets.PAT }} + github_token: ${{ secrets.GITHUB_TOKEN }} nuget_key: ${{ secrets.NUGET_DEPLOY_KEY }} nuget_push: true \ No newline at end of file diff --git a/.github/workflows/Rocket.Core.yaml b/.github/workflows/Rocket.Core.yaml index 7abd2970..3ba086aa 100644 --- a/.github/workflows/Rocket.Core.yaml +++ b/.github/workflows/Rocket.Core.yaml @@ -39,6 +39,9 @@ jobs: name: "Rocket.Core Build" runs-on: ubuntu-latest needs: Compatibility-Check + permissions: + contents: read + packages: write steps: - uses: actions/checkout@v6 @@ -54,6 +57,6 @@ jobs: id: project-build with: project_path: Rocket/Rocket.Core - github_token: ${{ secrets.PAT }} + github_token: ${{ secrets.GITHUB_TOKEN }} nuget_key: ${{ secrets.NUGET_DEPLOY_KEY }} nuget_push: true \ No newline at end of file diff --git a/.github/workflows/Rocket.Unturned.yaml b/.github/workflows/Rocket.Unturned.yaml index b788c1e7..7ef947ab 100644 --- a/.github/workflows/Rocket.Unturned.yaml +++ b/.github/workflows/Rocket.Unturned.yaml @@ -39,6 +39,9 @@ jobs: name: "Rocket.Unturned Build" runs-on: ubuntu-latest needs: Compatibility-Check + permissions: + contents: read + packages: write steps: - uses: actions/checkout@v6 @@ -54,6 +57,6 @@ jobs: id: project-build with: project_path: Rocket.Unturned - github_token: ${{ secrets.PAT }} + github_token: ${{ secrets.GITHUB_TOKEN }} nuget_key: ${{ secrets.NUGET_DEPLOY_KEY }} nuget_push: true \ No newline at end of file diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index 0fb379ed..10765ba3 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -41,6 +41,8 @@ jobs: Build: runs-on: ubuntu-latest needs: Compatibility-Check + permissions: + contents: write steps: - name: Checkout code @@ -60,7 +62,7 @@ jobs: project_path: Rocket.AutoInstaller nuget_key: ${{ secrets.NUGET_DEPLOY_KEY }} nuget_push: false - github_token: ${{ secrets.PAT }} + github_token: ${{ secrets.GITHUB_TOKEN }} - name: Build Rocket.Unturned.Module uses: ./.github/actions/project-build @@ -69,7 +71,7 @@ jobs: project_path: Rocket.Unturned nuget_key: ${{ secrets.NUGET_DEPLOY_KEY }} nuget_push: false - github_token: ${{ secrets.PAT }} + github_token: ${{ secrets.GITHUB_TOKEN }} - name: Upload Rocket.AutoInstaller uses: actions/upload-artifact@v7 @@ -100,7 +102,7 @@ jobs: artifacts: | ./Rocket.AutoInstaller/bin/Release/net461/linux-x64/Rocket.AutoInstaller/Rocket.AutoInstaller.zip ./Rocket.Unturned/bin/Release/net461/linux-x64/Rocket.Unturned/Rocket.Unturned.Module.zip - token: ${{ secrets.PAT }} + token: ${{ secrets.GITHUB_TOKEN }} prerelease: ${{ steps.auto-installer-build.outputs.is_prerelease }} allowUpdates: true draft: true \ No newline at end of file From 269b24a44c365f66fce994222ecc70dc044cadd8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2026 09:10:10 +0000 Subject: [PATCH 36/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.26.3.2 to 3.26.3.3 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index e8134952..3d21ad8e 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 30abe7da..cd105f15 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 126d960f..b3a6f710 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 69c46ce4..13eb8377 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From c62997af460ab6d474ad8b1d6c86144240fc8486 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 09:04:59 +0000 Subject: [PATCH 37/42] github-actions(deps): bump actions/checkout from 6 to 7 Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/Rocket.API.yaml | 4 ++-- .github/workflows/Rocket.Core.yaml | 4 ++-- .github/workflows/Rocket.Unturned.yaml | 4 ++-- .github/workflows/RocketModFix.yaml | 4 ++-- .github/workflows/compatibility-check.yaml | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/Rocket.API.yaml b/.github/workflows/Rocket.API.yaml index c7850c79..d2de1a0a 100644 --- a/.github/workflows/Rocket.API.yaml +++ b/.github/workflows/Rocket.API.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -44,7 +44,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 diff --git a/.github/workflows/Rocket.Core.yaml b/.github/workflows/Rocket.Core.yaml index 3ba086aa..b183e898 100644 --- a/.github/workflows/Rocket.Core.yaml +++ b/.github/workflows/Rocket.Core.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -44,7 +44,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 diff --git a/.github/workflows/Rocket.Unturned.yaml b/.github/workflows/Rocket.Unturned.yaml index 7ef947ab..30425fa1 100644 --- a/.github/workflows/Rocket.Unturned.yaml +++ b/.github/workflows/Rocket.Unturned.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -44,7 +44,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index 10765ba3..b2681b5b 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -46,7 +46,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index 172e6fa9..b047e8e0 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -16,10 +16,10 @@ jobs: steps: - name: Checkout current fork - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Checkout original repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: SmartlyDressedGames/Legally-Distinct-Missile path: original-repo From 2802f68d5c582a1fc5813f8074313cf49889e022 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:07:07 +0000 Subject: [PATCH 38/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.26.3.3 to 3.26.3.4 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.4 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index 3d21ad8e..9f4e3d5b 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index cd105f15..57d94b2a 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index b3a6f710..3277e1ac 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 13eb8377..f211bb62 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From 870f9308b3ceda59242053a73118be3fbf990071 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Jul 2026 09:05:21 +0000 Subject: [PATCH 39/42] github-actions(deps): bump actions/setup-dotnet from 5 to 6 Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 5 to 6. - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](https://github.com/actions/setup-dotnet/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/Rocket.API.yaml | 4 ++-- .github/workflows/Rocket.Core.yaml | 4 ++-- .github/workflows/Rocket.Unturned.yaml | 4 ++-- .github/workflows/RocketModFix.yaml | 4 ++-- .github/workflows/compatibility-check.yaml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/Rocket.API.yaml b/.github/workflows/Rocket.API.yaml index d2de1a0a..e2a27852 100644 --- a/.github/workflows/Rocket.API.yaml +++ b/.github/workflows/Rocket.API.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x @@ -48,7 +48,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/Rocket.Core.yaml b/.github/workflows/Rocket.Core.yaml index b183e898..76529bd6 100644 --- a/.github/workflows/Rocket.Core.yaml +++ b/.github/workflows/Rocket.Core.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x @@ -48,7 +48,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/Rocket.Unturned.yaml b/.github/workflows/Rocket.Unturned.yaml index 30425fa1..150bb376 100644 --- a/.github/workflows/Rocket.Unturned.yaml +++ b/.github/workflows/Rocket.Unturned.yaml @@ -25,7 +25,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x @@ -48,7 +48,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/RocketModFix.yaml b/.github/workflows/RocketModFix.yaml index b2681b5b..1509d32c 100644 --- a/.github/workflows/RocketModFix.yaml +++ b/.github/workflows/RocketModFix.yaml @@ -28,7 +28,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x @@ -50,7 +50,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 name: Setup .NET with: dotnet-version: 8.x diff --git a/.github/workflows/compatibility-check.yaml b/.github/workflows/compatibility-check.yaml index b047e8e0..ac5fef7e 100644 --- a/.github/workflows/compatibility-check.yaml +++ b/.github/workflows/compatibility-check.yaml @@ -25,7 +25,7 @@ jobs: path: original-repo - name: Setup dotnet - uses: actions/setup-dotnet@v5 + uses: actions/setup-dotnet@v6 with: dotnet-version: 8.x From caf36ed64ccc2a862c64add2cddc2b63d02ead33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 09:07:08 +0000 Subject: [PATCH 40/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.26.3.4 to 3.26.3.6 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.6 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index 9f4e3d5b..c0f50818 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 57d94b2a..156e7525 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index 3277e1ac..c31aabf9 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index f211bb62..5e57bec0 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From 4d5b78ab3c4c87a68fa65c504616e27be9501be9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 09:07:26 +0000 Subject: [PATCH 41/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.26.3.6 to 3.26.3.7 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.7 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index c0f50818..3d14f977 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index 156e7525..b38d3e17 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index c31aabf9..c3f8b59f 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 5e57bec0..88d121bf 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All From 02e261e921cf464d5bc66030f55ec80e19c477b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:06:30 +0000 Subject: [PATCH 42/42] nuget: Bump RocketModFix.Unturned.Redist.Server from 3.26.3.7 to 3.26.3.11 --- updated-dependencies: - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.11 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: RocketModFix.Unturned.Redist.Server dependency-version: 3.26.3.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Rocket.AutoInstaller/Rocket.AutoInstaller.csproj | 2 +- Rocket.Unturned/Rocket.Unturned.csproj | 2 +- Rocket/Rocket.API/Rocket.API.csproj | 2 +- Rocket/Rocket.Core/Rocket.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj index 3d14f977..7e310061 100644 --- a/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj +++ b/Rocket.AutoInstaller/Rocket.AutoInstaller.csproj @@ -15,7 +15,7 @@ All - + All diff --git a/Rocket.Unturned/Rocket.Unturned.csproj b/Rocket.Unturned/Rocket.Unturned.csproj index b38d3e17..e41c4b17 100644 --- a/Rocket.Unturned/Rocket.Unturned.csproj +++ b/Rocket.Unturned/Rocket.Unturned.csproj @@ -16,7 +16,7 @@ All - + All diff --git a/Rocket/Rocket.API/Rocket.API.csproj b/Rocket/Rocket.API/Rocket.API.csproj index c3f8b59f..b4b5196a 100644 --- a/Rocket/Rocket.API/Rocket.API.csproj +++ b/Rocket/Rocket.API/Rocket.API.csproj @@ -10,7 +10,7 @@ All - + All diff --git a/Rocket/Rocket.Core/Rocket.Core.csproj b/Rocket/Rocket.Core/Rocket.Core.csproj index 88d121bf..2d8ace35 100644 --- a/Rocket/Rocket.Core/Rocket.Core.csproj +++ b/Rocket/Rocket.Core/Rocket.Core.csproj @@ -21,7 +21,7 @@ All - + All