ci: modernize workflow to .NET 9.0 and enable auto-prerelease
This commit is contained in:
+22
-12
@@ -9,18 +9,17 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Funktioniert auf GitHub (windows-latest) und Gitea Runners mit entsprechendem Label
|
||||
runs-on: ${{ github.server_url == 'https://github.com' && 'windows-latest' || 'windows' }}
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore gregCore.csproj
|
||||
@@ -28,18 +27,29 @@ jobs:
|
||||
- name: Build gregCore
|
||||
run: dotnet build gregCore.csproj -c Release -p:CI=true
|
||||
|
||||
- name: Package Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Create Artifacts
|
||||
shell: pwsh
|
||||
run: |
|
||||
./gregScripts/Build-Release.ps1
|
||||
$outDir = "publish"
|
||||
New-Item -ItemType Directory -Path $outDir -Force
|
||||
Copy-Item "bin/Release/net6.0/gregCore.dll" $outDir/
|
||||
if (Test-Path "bin/Release/net6.0/gregCore.pdb") { Copy-Item "bin/Release/net6.0/gregCore.pdb" $outDir/ }
|
||||
# Zip it
|
||||
Compress-Archive -Path "$outDir/*" -DestinationPath "$outDir/gregCore-v1.0.0.30-pre.zip"
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gregCore-binaries
|
||||
path: publish/*.dll
|
||||
|
||||
- name: Create Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: latest
|
||||
name: gregCore Latest Build
|
||||
prerelease: true
|
||||
files: publish/*.zip
|
||||
body_path: CHANGELOG.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace greg.Harmony;
|
||||
|
||||
/// <summary>
|
||||
/// Patches the Unity Application version to ensure it is correctly reported to MelonLoader and other mods,
|
||||
/// as it is not properly configured in the game's Unity build.
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(Application), "version", MethodType.Getter)]
|
||||
public static class GregGameVersionPatch
|
||||
{
|
||||
private const string GameVersion = "1.0.45.5";
|
||||
|
||||
public static bool Prefix(ref string __result)
|
||||
{
|
||||
__result = GameVersion;
|
||||
return false; // Skip the original getter
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MelonLoader;
|
||||
using MelonLoader.Utils;
|
||||
|
||||
namespace greg.Core.Plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Utility for recursive dependency resolution across mod directories.
|
||||
/// </summary>
|
||||
public static class gregDependencyResolver
|
||||
{
|
||||
private static readonly HashSet<string> _foundAssemblies = new(StringComparer.OrdinalIgnoreCase);
|
||||
private static bool _scanComplete;
|
||||
private static readonly object _lock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the specified dependencies are present in the filesystem.
|
||||
/// Supports deep recursive searching in StreamingAssets and standard Mods folder.
|
||||
/// </summary>
|
||||
/// <param name="logger">Logger for reporting missing dependencies.</param>
|
||||
/// <param name="modName">Name of the mod requesting the check.</param>
|
||||
/// <param name="required">List of required DLL filenames (without extension).</param>
|
||||
/// <param name="optional">List of optional DLL filenames (without extension).</param>
|
||||
/// <returns>True if all required dependencies are found; otherwise, false.</returns>
|
||||
public static bool CheckDependencies(MelonLogger.Instance logger, string modName, string[] required, string[] optional = null)
|
||||
{
|
||||
EnsureScan(logger);
|
||||
|
||||
bool allMet = true;
|
||||
var missingRequired = new List<string>();
|
||||
|
||||
if (required != null)
|
||||
{
|
||||
foreach (var req in required)
|
||||
{
|
||||
if (!_foundAssemblies.Contains(req))
|
||||
{
|
||||
allMet = false;
|
||||
missingRequired.Add(req);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!allMet)
|
||||
{
|
||||
logger.Error($"[{modName}] CRITICAL: Missing required dependencies: {string.Join(", ", missingRequired)}");
|
||||
logger.Error($"[{modName}] This mod will be disabled to prevent crashes.");
|
||||
}
|
||||
|
||||
if (optional != null)
|
||||
{
|
||||
foreach (var opt in optional)
|
||||
{
|
||||
if (!_foundAssemblies.Contains(opt))
|
||||
{
|
||||
logger.Warning($"[{modName}] Optional dependency '{opt}' not found. Some features may be unavailable.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allMet;
|
||||
}
|
||||
|
||||
private static void EnsureScan(MelonLogger.Instance logger)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_scanComplete) return;
|
||||
|
||||
var roots = new List<string>
|
||||
{
|
||||
MelonEnvironment.ModsDirectory,
|
||||
Path.Combine(MelonEnvironment.GameRootDirectory, "Data Center_Data", "StreamingAssets", "mods")
|
||||
};
|
||||
|
||||
foreach (var root in roots)
|
||||
{
|
||||
if (Directory.Exists(root))
|
||||
{
|
||||
ScanDirectoryRecursive(root, 0, 12);
|
||||
}
|
||||
}
|
||||
|
||||
_scanComplete = true;
|
||||
logger.Msg($"[gregCore] Dependency scan complete. Found {_foundAssemblies.Count} unique assemblies in mods directories.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ScanDirectoryRecursive(string path, int currentDepth, int maxDepth)
|
||||
{
|
||||
if (currentDepth > maxDepth) return;
|
||||
|
||||
try
|
||||
{
|
||||
// Scan files in current directory
|
||||
foreach (var file in Directory.GetFiles(path, "*.dll"))
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(file);
|
||||
_foundAssemblies.Add(name);
|
||||
}
|
||||
|
||||
// Recurse into subdirectories
|
||||
foreach (var dir in Directory.GetDirectories(path))
|
||||
{
|
||||
ScanDirectoryRecursive(dir, currentDepth + 1, maxDepth);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore access errors
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using MelonLoader;
|
||||
|
||||
namespace greg.Core.Plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Unified base class for all gregCore ecosystem mods and plugins.
|
||||
/// Handles automatic dependency resolution and lifecycle management.
|
||||
/// </summary>
|
||||
public abstract class gregModBase : MelonMod
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the list of required assembly/DLL names (without extension).
|
||||
/// If any are missing, the mod will not initialize.
|
||||
/// </summary>
|
||||
public virtual string[] RequiredDependencies => Array.Empty<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of optional assembly/DLL names (without extension).
|
||||
/// If missing, a warning is logged but the mod still initializes.
|
||||
/// </summary>
|
||||
public virtual string[] OptionalDependencies => Array.Empty<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the dependency check failed.
|
||||
/// If true, all lifeycle methods (Update, GUI, etc.) are short-circuited.
|
||||
/// </summary>
|
||||
protected bool IsDependencySearchFailed { get; private set; }
|
||||
|
||||
public sealed override void OnInitializeMelon()
|
||||
{
|
||||
if (!gregDependencyResolver.CheckDependencies(LoggerInstance, MelonAssembly.Assembly.GetName().Name, RequiredDependencies, OptionalDependencies))
|
||||
{
|
||||
IsDependencySearchFailed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
OnInitializeMod();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerInstance.Error($"Unhandled exception during OnInitializeMod: {ex.Message}");
|
||||
IsDependencySearchFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Actual initialization logic for the mod. Called only if dependencies are satisfied.
|
||||
/// </summary>
|
||||
public virtual void OnInitializeMod() { }
|
||||
|
||||
public override void OnUpdate() { if (!IsDependencySearchFailed) OnUpdateMod(); }
|
||||
public virtual void OnUpdateMod() { }
|
||||
|
||||
public override void OnFixedUpdate() { if (!IsDependencySearchFailed) OnFixedUpdateMod(); }
|
||||
public virtual void OnFixedUpdateMod() { }
|
||||
|
||||
public override void OnLateUpdate() { if (!IsDependencySearchFailed) OnLateUpdateMod(); }
|
||||
public virtual void OnLateUpdateMod() { }
|
||||
|
||||
public override void OnGUI() { if (!IsDependencySearchFailed) OnGuiMod(); }
|
||||
public virtual void OnGuiMod() { }
|
||||
|
||||
public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (!IsDependencySearchFailed) OnSceneLoadedMod(buildIndex, sceneName); }
|
||||
public virtual void OnSceneLoadedMod(int buildIndex, string sceneName) { }
|
||||
|
||||
public override void OnApplicationQuit() { if (!IsDependencySearchFailed) OnApplicationQuitMod(); }
|
||||
public virtual void OnApplicationQuitMod() { }
|
||||
}
|
||||
@@ -4,10 +4,15 @@ using MelonLoader;
|
||||
namespace greg.Core.Plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for gregCore standalone plugins.
|
||||
/// Base class for gregCore standalone plugins (extensions).
|
||||
/// </summary>
|
||||
public abstract class gregPluginBase : MelonMod
|
||||
public abstract class gregPluginBase : gregModBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension plugins always require gregCore to function.
|
||||
/// </summary>
|
||||
public override string[] RequiredDependencies => new[] { "gregCore" };
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin's unique identifier.
|
||||
/// </summary>
|
||||
@@ -31,7 +36,7 @@ public abstract class gregPluginBase : MelonMod
|
||||
/// <summary>
|
||||
/// Registers the plugin with the central framework registry.
|
||||
/// </summary>
|
||||
public override void OnInitializeMelon()
|
||||
public override void OnInitializeMod()
|
||||
{
|
||||
gregRegistry.RegisterPlugin(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user