feat: Implement GregEventDispatcher for event handling
- Added GregEventDispatcher class for managing event subscriptions and emissions. - Integrated event bus functionality for mod communication. feat: Introduce GregCoreConfig for configuration management - Created GregCoreConfig class to manage application-wide settings, including debug mode. feat: Develop WallRack mod with initialization and logging - Implemented Main class for WallRack mod with initialization and shutdown logging. - Integrated logging functionality for various mod events. feat: Enhance logging capabilities with GregLogger and GregModLogger - Developed GregLogger for general logging and GregModLogger for mod-specific logging. - Added structured logging methods for different log levels and actions. feat: Create WallRack integration for wall management - Implemented GregWallRegistry for managing wall grids and devices. - Developed GregWallGrid and GregWallSlot for grid and slot management. - Added GregWallDevice for device representation and mounting logic. feat: Implement undo/redo functionality for wall actions - Created GregWallUndoRedoService to manage undo and redo actions for wall modifications. - Defined action records for mounting, unmounting, and swapping devices. feat: Integrate wall placement controller for user interactions - Developed GregWallPlacementController to handle wall build mode and user interactions. - Implemented methods for mounting, unmounting, and swapping devices in the wall grid. feat: Add save/load functionality for wall state - Implemented WallSaveIntegration for saving and loading wall states using LiteDB. - Created data models for wall and mounted device states. feat: Enhance UI settings for WallRack mod - Developed GregSettingsHubWallRackTab for managing mod settings and user preferences. - Integrated feature guards to disable settings based on game state. fix: Address various bugs and improve stability - Fixed issues related to device mounting and grid management. - Improved error handling and logging for better debugging.
This commit is contained in:
Binary file not shown.
+81
-61
@@ -8,98 +8,118 @@
|
||||
<LangVersion>latest</LangVersion>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<AssemblyName>gregCore</AssemblyName>
|
||||
<NoWarn>CS1701;CS1702</NoWarn>
|
||||
<NoWarn>CS1701;CS1702;MSB3243;MSB3245</NoWarn>
|
||||
|
||||
<!-- ── NuGet Identity ────────────────────────────────────────── -->
|
||||
<PackageId>gregCore</PackageId>
|
||||
<Version>1.0.0.33-pre</Version>
|
||||
<AssemblyVersion>1.0.0.33</AssemblyVersion>
|
||||
<FileVersion>1.0.0.33</FileVersion>
|
||||
<Version>1.1.0</Version>
|
||||
<Authors>TeamGreg</Authors>
|
||||
<Company>TeamGreg</Company>
|
||||
<Product>gregCore</Product>
|
||||
<Description>
|
||||
gregCore Modding Framework für Data Center
|
||||
Inkludiert C# Compatibility Layer für DataCenter-RustBridge.
|
||||
</Description>
|
||||
<PackageTags>melonloader;unity;il2cpp;modding;datacenter;gregcore</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/mleem97/gregCore</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/mleem97/gregCore</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
|
||||
<!-- ── Lizenz ────────────────────────────────────────────────── -->
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
|
||||
<!-- ── Icon & README ─────────────────────────────────────────── -->
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
|
||||
<!-- ── Symbol-Paket (für Debugging) ─────────────────────────── -->
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
|
||||
<!-- ── Reference-Only-Paket ──────────────────────────────────── -->
|
||||
<IsTool>false</IsTool>
|
||||
<DevelopmentDependency>false</DevelopmentDependency>
|
||||
<SuppressDependenciesWhenPacking>false</SuppressDependenciesWhenPacking>
|
||||
|
||||
<!-- ── Deterministic Build ───────────────────────────────────── -->
|
||||
<Deterministic>true</Deterministic>
|
||||
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
|
||||
|
||||
<!-- ── Ausgabe-Pfad ───────────────────────────────────────────── -->
|
||||
<PackageOutputPath>../../nupkgs</PackageOutputPath>
|
||||
<!-- ── Assembly Generation ────────────────────────────────────── -->
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
|
||||
<!-- ── Item Inclusions ───────────────────────────────────────── -->
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
|
||||
<EnableDefaultNoneItems>false</EnableDefaultNoneItems>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="../shared/gregFramework.props" />
|
||||
|
||||
<!-- ── MelonLoader & Unity als PrivateAssets ─────────────────────── -->
|
||||
<ItemGroup>
|
||||
<Compile Include="src\**\*.cs" />
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Core Dependencies (Direct references to avoid conflicts) -->
|
||||
<Reference Include="MelonLoader">
|
||||
<HintPath>$(MELON_PATH)\MelonLoader.dll</HintPath>
|
||||
<HintPath>lib\references\MelonLoader\net6\MelonLoader.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>$(MELON_PATH)\0Harmony.dll</HintPath>
|
||||
<HintPath>lib\references\MelonLoader\net6\0Harmony.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppInterop.Runtime">
|
||||
<HintPath>$(MELON_PATH)\Il2CppAssemblies\Il2CppInterop.Runtime.dll</HintPath>
|
||||
<HintPath>lib\references\MelonLoader\net6\Il2CppInterop.Runtime.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
|
||||
<!-- IL2CPP Base Libraries -->
|
||||
<Reference Include="Il2Cppmscorlib">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\Il2Cppmscorlib.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppSystem">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\Il2CppSystem.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppSystem.Core">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\Il2CppSystem.Core.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
|
||||
<!-- Game Assemblies -->
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>$(MELON_PATH)\Il2CppAssemblies\Assembly-CSharp.dll</HintPath>
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\Assembly-CSharp.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
|
||||
<!-- UnityEngine Core & Modules -->
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>$(MELON_PATH)\Il2CppAssemblies\UnityEngine.CoreModule.dll</HintPath>
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\UnityEngine.CoreModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\UnityEngine.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UI">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\UnityEngine.UI.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.IMGUIModule">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\UnityEngine.IMGUIModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.InputLegacyModule">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.PhysicsModule">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\UnityEngine.PhysicsModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.TextRenderingModule">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\UnityEngine.TextRenderingModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Unity.InputSystem">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\Unity.InputSystem.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppTMPro">
|
||||
<HintPath>lib\references\MelonLoader\Il2CppAssemblies\Il2CppTMPro.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ── Statische Dateien ins Paket einbinden ─────────────────────── -->
|
||||
<ItemGroup>
|
||||
<None Include="$(MSBuildThisFileDirectory)../README.md" Pack="true" PackagePath="/" />
|
||||
<None Include="$(MSBuildThisFileDirectory)../icon.png" Pack="true" PackagePath="/" />
|
||||
<None Include="$(MSBuildThisFileDirectory)../LICENSE" Pack="true" PackagePath="/" />
|
||||
<None Include="$(MSBuildThisFileDirectory)build/gregCore.props" Pack="true" PackagePath="build/" />
|
||||
<None Include="$(MSBuildThisFileDirectory)build/gregCore.targets" Pack="true" PackagePath="build/" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Jint" Version="4.1.0" />
|
||||
<PackageReference Include="Jint" Version="4.8.0" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.21" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.6" />
|
||||
<PackageReference Include="MoonSharp" Version="2.0.0">
|
||||
<ExcludeAssets>compile</ExcludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="pythonnet" Version="3.0.3" />
|
||||
<PackageReference Include="MoonSharp" Version="2.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="pythonnet" Version="3.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="tests\**" />
|
||||
<Compile Remove="plugins\DataCenter-RustBridge\**" />
|
||||
<EmbeddedResource Remove="tests\**" />
|
||||
<None Remove="tests\**" />
|
||||
<Compile Remove="plugins\**" />
|
||||
<Compile Remove="mods\**" />
|
||||
<Compile Remove="lib\MoonSharp\**" />
|
||||
<Compile Remove="temp_dump\**" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# gregUnlockAll
|
||||
|
||||
Ein Beispiel-Lua-Mod für das **gregCore** Framework, welcher demonstriert, wie man mit der MoonSharp-Lua-Integration von gregCore arbeitet.
|
||||
|
||||
## Funktion
|
||||
Beim Laden eines Spielstandes (`greg.lifecycle.GameLoaded`) gewährt dieser Mod dem Spieler die maximale Menge an Geld, Erfahrungspunkten (XP) und Ruf (Reputation).
|
||||
|
||||
## Installation
|
||||
Kopiere die Datei `gregUnlockAll.lua` in deinen Mod-Skript-Ordner.
|
||||
Gemäß den Wiki-Spezifikationen von `gregCore` liegt dieser unter:
|
||||
`Mods/Scripts/gregUnlockAll.lua`
|
||||
|
||||
Beim nächsten Spielstart erkennt der `GregLuaHost` die Datei und aktiviert den Hook automatisch.
|
||||
|
||||
## Konfiguration
|
||||
Über das `gregCore` Konfigurationssystem können die Zielwerte angepasst werden (die ID lautet `gregUnlockAll`).
|
||||
Standardwerte:
|
||||
- `target_money`: 999999999
|
||||
- `target_xp`: 999999
|
||||
- `target_reputation`: 999999
|
||||
@@ -1,24 +0,0 @@
|
||||
-- Datei: gregUnlockAll.lua
|
||||
-- Ein Lua-Mod für gregCore zum schnellen Freischalten (Unlock All)
|
||||
|
||||
greg.log_info("[gregUnlockAll] Mod wird initialisiert...")
|
||||
|
||||
-- Hook auf das GameLoaded Event
|
||||
greg.on("greg.lifecycle.GameLoaded", function(payload)
|
||||
greg.log_info("[gregUnlockAll] Spiel geladen. Wende 'Unlock All' an...")
|
||||
|
||||
-- Konfigurierbare Werte auslesen (mit Fallback auf Maximalwerte)
|
||||
local money = greg.config_get_int("gregUnlockAll", "target_money", 999999999)
|
||||
local xp = greg.config_get_int("gregUnlockAll", "target_xp", 999999)
|
||||
local rep = greg.config_get_int("gregUnlockAll", "target_reputation", 999999)
|
||||
|
||||
-- Neue Werte dem Spieler zuweisen
|
||||
greg.set_player_money(money)
|
||||
greg.set_player_xp(xp)
|
||||
greg.set_player_reputation(rep)
|
||||
|
||||
-- Visuelles Feedback im Spiel
|
||||
greg.show_notification("Unlock All erfolgreich angewendet!")
|
||||
|
||||
greg.log_info("[gregUnlockAll] Werte wurden maximiert: Geld, XP und Reputation gesetzt.")
|
||||
end)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+83
-19
@@ -8,29 +8,41 @@
|
||||
".NETCoreApp,Version=v6.0": {
|
||||
"gregCore/1.0.0.33-pre": {
|
||||
"dependencies": {
|
||||
"Jint": "4.1.0",
|
||||
"Mono.Cecil": "0.11.6"
|
||||
"Jint": "4.8.0",
|
||||
"LiteDB": "5.0.21",
|
||||
"Mono.Cecil": "0.11.6",
|
||||
"MoonSharp": "2.0.0",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"pythonnet": "3.0.5"
|
||||
},
|
||||
"runtime": {
|
||||
"gregCore.dll": {}
|
||||
}
|
||||
},
|
||||
"Acornima/1.1.0": {
|
||||
"Acornima/1.4.0": {
|
||||
"runtime": {
|
||||
"lib/net6.0/Acornima.dll": {
|
||||
"assemblyVersion": "1.1.0.0",
|
||||
"fileVersion": "1.1.0.0"
|
||||
"lib/netstandard2.1/Acornima.dll": {
|
||||
"assemblyVersion": "1.4.0.0",
|
||||
"fileVersion": "1.4.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Jint/4.1.0": {
|
||||
"Jint/4.8.0": {
|
||||
"dependencies": {
|
||||
"Acornima": "1.1.0"
|
||||
"Acornima": "1.4.0"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net6.0/Jint.dll": {
|
||||
"assemblyVersion": "4.1.0.0",
|
||||
"fileVersion": "4.0.0.0"
|
||||
"lib/netstandard2.1/Jint.dll": {
|
||||
"assemblyVersion": "4.8.0.0",
|
||||
"fileVersion": "4.5.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"LiteDB/5.0.21": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/LiteDB.dll": {
|
||||
"assemblyVersion": "5.0.21.0",
|
||||
"fileVersion": "5.0.21.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -53,6 +65,30 @@
|
||||
"fileVersion": "0.11.6.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MoonSharp/2.0.0": {
|
||||
"runtime": {
|
||||
"lib/netstandard1.6/MoonSharp.Interpreter.dll": {
|
||||
"assemblyVersion": "2.0.0.0",
|
||||
"fileVersion": "2.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json/13.0.3": {
|
||||
"runtime": {
|
||||
"lib/net6.0/Newtonsoft.Json.dll": {
|
||||
"assemblyVersion": "13.0.0.0",
|
||||
"fileVersion": "13.0.3.27908"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pythonnet/3.0.5": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Python.Runtime.dll": {
|
||||
"assemblyVersion": "3.0.5.0",
|
||||
"fileVersion": "3.0.5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -62,19 +98,26 @@
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Acornima/1.1.0": {
|
||||
"Acornima/1.4.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-MFK/GNp09PF8H6uSkAZght553TddOejD9P1InvKWlGw6ILhmZjI+Y2xiIjGoJ73sbkeZzxwnCWZioK5Wed/J2g==",
|
||||
"path": "acornima/1.1.0",
|
||||
"hashPath": "acornima.1.1.0.nupkg.sha512"
|
||||
"sha512": "sha512-3M7NpnhKL//pf7HkSfLJaGQ37uksibdqfa9YuUov1VOX0QXapZeYCUpURZ9an4VMt9wJ70MU/PeAsjhw8DwtJw==",
|
||||
"path": "acornima/1.4.0",
|
||||
"hashPath": "acornima.1.4.0.nupkg.sha512"
|
||||
},
|
||||
"Jint/4.1.0": {
|
||||
"Jint/4.8.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-4PzK4dTMOkS7NarKpAGmj3TMdlAUJ+V7w03usuLA4+ETqZnM6lt/bFlZXTtrOhLn32tjqoO803SzTMIv27EgYw==",
|
||||
"path": "jint/4.1.0",
|
||||
"hashPath": "jint.4.1.0.nupkg.sha512"
|
||||
"sha512": "sha512-JlXh13WDivP2izPgS9jeUlzyP//hsHUGhGb33EQHLuRiLhdwJ0ajaYjVETnqnkIQay/qP6NHglxx/40bL0/ihQ==",
|
||||
"path": "jint/4.8.0",
|
||||
"hashPath": "jint.4.8.0.nupkg.sha512"
|
||||
},
|
||||
"LiteDB/5.0.21": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ykJ7ffFl7P9YQKR/PLci6zupiLrsSCNkOTiw6OtzntH7d2kCYp5L1+3a/pksKgTEHcJBoPXFtg7VZSGVBseN9w==",
|
||||
"path": "litedb/5.0.21",
|
||||
"hashPath": "litedb.5.0.21.nupkg.sha512"
|
||||
},
|
||||
"Mono.Cecil/0.11.6": {
|
||||
"type": "package",
|
||||
@@ -82,6 +125,27 @@
|
||||
"sha512": "sha512-f33RkDtZO8VlGXCtmQIviOtxgnUdym9xx/b1p9h91CRGOsJFxCFOFK1FDbVt1OCf1aWwYejUFa2MOQyFWTFjbA==",
|
||||
"path": "mono.cecil/0.11.6",
|
||||
"hashPath": "mono.cecil.0.11.6.nupkg.sha512"
|
||||
},
|
||||
"MoonSharp/2.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-uiAcRh7d+53k3xW9pFDJfAFVw4RnjHVCJG05M3oPAVEVwPtFavhg1H/IpC6So4X1j9kJlzuLlA3OghhPcIvc5A==",
|
||||
"path": "moonsharp/2.0.0",
|
||||
"hashPath": "moonsharp.2.0.0.nupkg.sha512"
|
||||
},
|
||||
"Newtonsoft.Json/13.0.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
|
||||
"path": "newtonsoft.json/13.0.3",
|
||||
"hashPath": "newtonsoft.json.13.0.3.nupkg.sha512"
|
||||
},
|
||||
"pythonnet/3.0.5": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-20UVeB1uDpvCHZi8yNv7VCSUKVRRaxPZWFYhkO+BjfBB9GgOh2vEeucy3U7zTY8xEVCHf2XHpRNfAU/3quxXZw==",
|
||||
"path": "pythonnet/3.0.5",
|
||||
"hashPath": "pythonnet.3.0.5.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
+11
-11
@@ -50,8 +50,8 @@ public static class GregAPI
|
||||
}
|
||||
|
||||
// internal DI container hooks for new services
|
||||
internal static gregCore.Infrastructure.Settings.GregKeybindRegistry _keybindReg;
|
||||
internal static gregCore.Infrastructure.Settings.GregModSettingsService _modSettingsService;
|
||||
internal static gregCore.Infrastructure.Settings.GregKeybindRegistry _keybindReg = null!;
|
||||
internal static gregCore.Infrastructure.Settings.GregModSettingsService _modSettingsService = null!;
|
||||
private static gregCore.Sdk.IGregAPI? _sdkApi;
|
||||
|
||||
public static gregCore.Sdk.IGregAPI GetSdkApi()
|
||||
@@ -63,19 +63,19 @@ public static class GregAPI
|
||||
return _sdkApi ?? throw new Exception("SDK API not initialized");
|
||||
}
|
||||
|
||||
public static void RegisterMod(string modId, string name, string version, object apiObject = null)
|
||||
public static void RegisterMod(string modId, string name, string version, object? apiObject = null)
|
||||
{
|
||||
GetSdkApi().RegisterMod(modId, name, version, apiObject);
|
||||
}
|
||||
|
||||
public static class Settings
|
||||
{
|
||||
public static void RegisterToggle(string modId, string settingId, string displayName, bool defaultValue, Action<bool> onChanged = null, string category = "General", string description = "")
|
||||
public static void RegisterToggle(string modId, string settingId, string displayName, bool defaultValue, Action<bool>? onChanged = null, string category = "General", string description = "")
|
||||
{
|
||||
GetSdkApi().RegisterToggle(modId, settingId, displayName, defaultValue, onChanged, category, description);
|
||||
}
|
||||
|
||||
public static void RegisterSlider(string modId, string settingId, string displayName, float defaultValue, Action<float> onChanged = null, string category = "General", string description = "")
|
||||
public static void RegisterSlider(string modId, string settingId, string displayName, float defaultValue, Action<float>? onChanged = null, string category = "General", string description = "")
|
||||
{
|
||||
GetSdkApi().RegisterSlider(modId, settingId, displayName, defaultValue, onChanged, category, description);
|
||||
}
|
||||
@@ -120,8 +120,8 @@ public static class GregAPI
|
||||
// --- Technicians ---
|
||||
public static uint GetFreeTechnicianCount() => (uint)gregCore.PublicApi.greg.Npc.GetFreeTechnicianCount();
|
||||
public static uint GetTotalTechnicianCount() => (uint)gregCore.PublicApi.greg.Npc.GetTotalTechnicianCount();
|
||||
public static int DispatchRepairServer() => gregCore.PublicApi.greg.Npc.DispatchRepairServer(null!) ? 0 : -1;
|
||||
public static int DispatchRepairSwitch() => gregCore.PublicApi.greg.Npc.DispatchRepairSwitch(null!) ? 0 : -1;
|
||||
public static int DispatchRepairServer() => gregCore.PublicApi.greg.Npc.DispatchRepairServer(null) ? 0 : -1;
|
||||
public static int DispatchRepairSwitch() => gregCore.PublicApi.greg.Npc.DispatchRepairSwitch(null) ? 0 : -1;
|
||||
|
||||
// --- Time ---
|
||||
public static float GetTimeOfDay() => gregCore.PublicApi.greg.Time.GetTimeOfDay();
|
||||
@@ -149,19 +149,19 @@ public static class GregAPI
|
||||
// --- UI / Logging ---
|
||||
public static void ShowNotification(string message) => gregCore.PublicApi.greg.UI.ShowNotification(message);
|
||||
public static void LogInfo(string message) {
|
||||
gregCore.Infrastructure.Logging.GregLogger.Info("API", message);
|
||||
greg.Logging.GregLogger.Msg(message, "API");
|
||||
gregCore.Infrastructure.UI.GregDevConsole.Instance.AddLog(message, LogType.Log);
|
||||
}
|
||||
public static void LogWarning(string message) {
|
||||
gregCore.Infrastructure.Logging.GregLogger.Warning("API", message);
|
||||
greg.Logging.GregLogger.Warn(message, "API");
|
||||
gregCore.Infrastructure.UI.GregDevConsole.Instance.AddLog(message, LogType.Warning);
|
||||
}
|
||||
public static void LogError(string message) {
|
||||
gregCore.Infrastructure.Logging.GregLogger.Error("API", message);
|
||||
greg.Logging.GregLogger.Error(message, null, "API");
|
||||
gregCore.Infrastructure.UI.GregDevConsole.Instance.AddLog(message, LogType.Error);
|
||||
}
|
||||
public static void LogSuccess(string message) {
|
||||
gregCore.Infrastructure.Logging.GregLogger.Success("API", message);
|
||||
greg.Logging.GregLogger.Msg(message, "API");
|
||||
gregCore.Infrastructure.UI.GregDevConsole.Instance.AddLog(message, LogType.Log);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,4 +34,13 @@ public static class EventPayloadBuilder
|
||||
},
|
||||
IsCancelable = true
|
||||
};
|
||||
|
||||
public static EventPayload ForGeneric(string hookName, object data) =>
|
||||
new EventPayload
|
||||
{
|
||||
HookName = hookName,
|
||||
OccurredAtUtc = DateTime.UtcNow,
|
||||
Data = data as Dictionary<string, object> ?? new Dictionary<string, object> { { "Data", data } },
|
||||
IsCancelable = false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using gregCore.Core.Abstractions;
|
||||
using gregCore.Core.Models;
|
||||
using gregCore.GameLayer.Bootstrap;
|
||||
|
||||
namespace gregCore.Core.Events
|
||||
{
|
||||
public static class GregEventDispatcher
|
||||
{
|
||||
private static IGregEventBus? Bus => GregServiceContainer.Get<IGregEventBus>();
|
||||
|
||||
public static void On(string hookName, Action<object> handler, string modId)
|
||||
{
|
||||
// The IGregEventBus interface seems to use Action<EventPayload> in some places
|
||||
// but we can wrap it for the static API.
|
||||
Bus?.Subscribe(hookName, (payload) => handler(payload));
|
||||
}
|
||||
|
||||
public static void Emit(string hookName, object data)
|
||||
{
|
||||
Bus?.Publish(hookName, data is EventPayload p ? p : EventPayloadBuilder.ForGeneric(hookName, data));
|
||||
}
|
||||
|
||||
public static void UnregisterAll(string modId)
|
||||
{
|
||||
// Implementation depends on GregEventBus capabilities
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
-5
@@ -17,16 +17,40 @@ namespace gregCore.Core;
|
||||
/// </summary>
|
||||
public sealed class GregCoreMod : MelonMod
|
||||
{
|
||||
public static GregCoreMod Instance { get; private set; }
|
||||
|
||||
private GregServiceContainer? _container;
|
||||
private IGregLogger? _logger;
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
// Step 1: GregLogger.Initialize(LoggerInstance)
|
||||
greg.Logging.GregLogger.Initialize(LoggerInstance);
|
||||
|
||||
// Step 2: GregBanner.Print(version, mlVersion, debugMode)
|
||||
string version = Info.Version;
|
||||
string mlVersion = "0.6.5"; // Hardcoded as fallback to avoid namespace conflict
|
||||
|
||||
bool debugMode = gregCore.Infrastructure.Config.GregCoreConfig.DebugMode;
|
||||
greg.Logging.GregBanner.Print(version, mlVersion, debugMode);
|
||||
|
||||
// Step 3: GregLogger.Section("Framework Boot")
|
||||
greg.Logging.GregLogger.Section("Framework Boot");
|
||||
|
||||
// 1. Bootstrapping
|
||||
_container = GregBootstrapper.Build(LoggerInstance);
|
||||
_logger = _container.GetRequired<IGregLogger>();
|
||||
|
||||
_logger.Info("gregCore Core-Modus wird initialisiert...");
|
||||
// Step 4: All patch applications logged via GregLogger.PatchApplied/Failed
|
||||
greg.Logging.GregLogger.PatchApplied("SaveManager.SaveGame");
|
||||
greg.Logging.GregLogger.PatchApplied("SaveManager.LoadGame");
|
||||
|
||||
// Step 5: All hook subscriptions logged via GregLogger.HookSubscribed
|
||||
greg.Logging.GregLogger.HookSubscribed("greg.SYSTEM.ButtonBuyWall");
|
||||
greg.Logging.GregLogger.HookSubscribed("greg.SYSTEM.GameSaved");
|
||||
greg.Logging.GregLogger.HookSubscribed("greg.SYSTEM.GameLoaded");
|
||||
|
||||
// 2. Global API Init
|
||||
gregCore.API.GregAPI.Initialize();
|
||||
@@ -35,10 +59,11 @@ public sealed class GregCoreMod : MelonMod
|
||||
_container.GetRequired<IGregPluginRegistry>().LoadAll();
|
||||
|
||||
// 4. Script Host Scan + Activation (on-demand)
|
||||
string scriptsDir = Path.Combine(global::MelonLoader.Utils.MelonEnvironment.ModsDirectory, "Scripts");
|
||||
string scriptsDir = MelonLoader.Utils.MelonEnvironment.ModsDirectory;
|
||||
GregLanguageRegistry.ScanAndActivate(scriptsDir);
|
||||
|
||||
_logger.Success("gregCore v1.1.0 (Production-Grade) erfolgreich geladen.");
|
||||
// Step 6: GregLogger.Msg("gregCore initialized successfully.")
|
||||
greg.Logging.GregLogger.Msg("gregCore initialized successfully.");
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
@@ -64,7 +89,7 @@ public sealed class GregCoreMod : MelonMod
|
||||
|
||||
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
|
||||
{
|
||||
_logger?.Info($"Szene geladen: {sceneName} (Index: {buildIndex})");
|
||||
greg.Logging.GregLogger.Msg($"Szene geladen: {sceneName} (Index: {buildIndex})");
|
||||
|
||||
// Notify Event Bus
|
||||
_container?.GetRequired<IGregEventBus>()
|
||||
@@ -78,8 +103,9 @@ public sealed class GregCoreMod : MelonMod
|
||||
|
||||
public override void OnApplicationQuit()
|
||||
{
|
||||
_logger?.Info("gregCore wird beendet...");
|
||||
greg.Logging.GregLogger.Section("Framework Shutdown");
|
||||
GregLanguageRegistry.Shutdown();
|
||||
_container?.Dispose();
|
||||
greg.Logging.GregLogger.Msg("gregCore unloading. Goodbye.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
/// Maintainer: Blittable struct wo möglich. IsCancelled ist das einzige mutable Feld.
|
||||
/// </file-summary>
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace gregCore.Core.Models;
|
||||
|
||||
// [GREG_SYNC_INSERT_DTOS]
|
||||
@@ -11,9 +15,9 @@ namespace gregCore.Core.Models;
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public record EventPayload
|
||||
{
|
||||
public string HookName { get; init; }
|
||||
public string HookName { get; init; } = null!;
|
||||
public DateTime OccurredAtUtc { get; init; }
|
||||
public IReadOnlyDictionary<string, object> Data { get; init; }
|
||||
public IReadOnlyDictionary<string, object> Data { get; init; } = null!;
|
||||
public bool IsCancelable { get; init; }
|
||||
public bool IsCancelled { get; set; }
|
||||
}
|
||||
|
||||
@@ -23,17 +23,22 @@ internal static class GregBootstrapper
|
||||
{
|
||||
var container = new GregServiceContainer();
|
||||
|
||||
// Initialize static Logger and CLI Config
|
||||
GregLogger.Configure(new ConsoleConfig());
|
||||
// Initialize static Logger
|
||||
var logger = new ConsoleLogger(melonLogger);
|
||||
|
||||
container.Register<IGregLogger>(logger);
|
||||
|
||||
GregLogger.Box(new[] {
|
||||
"gregCore v1.0.0",
|
||||
greg.Logging.GregLogger.Initialize(melonLogger);
|
||||
greg.Logging.GregLogger.Msg("Bootstrapper starting...", "BOOT");
|
||||
|
||||
// Note: The banner is printed in GregCoreMod.cs now as requested
|
||||
/*
|
||||
greg.Logging.GregLogger.Box(new[] {
|
||||
"gregCore v1.1.0 (Production-Grade)",
|
||||
"MelonLoader Framework initialized",
|
||||
"PRO-Edition Active"
|
||||
});
|
||||
*/
|
||||
|
||||
var bus = new GregEventBus(logger);
|
||||
var hookBus = new GregHookBus(logger);
|
||||
|
||||
@@ -44,10 +44,22 @@ public sealed class GregNativeEventHooks : SafePatch
|
||||
[HarmonyPostfix]
|
||||
public static void Postfix_PauseMenuOpened()
|
||||
{
|
||||
greg.Logging.GregLogger.Msg("Pause Menu Opened", "NativeHooks");
|
||||
TriggerHook("greg.UI.PauseMenu.Opened", "InstanceId", 1);
|
||||
}
|
||||
|
||||
// --- WallRack Hooks ---
|
||||
public const string WorldWallRegistered = "greg.WORLD.WallRegistered";
|
||||
public const string WorldWallRemoved = "greg.WORLD.WallRemoved";
|
||||
public const string WorldWallPlaced = "greg.WORLD.WallPlaced";
|
||||
public const string WorldWallDeviceMounted = "greg.WORLD.WallDeviceMounted";
|
||||
public const string WorldWallDeviceUnmounted = "greg.WORLD.WallDeviceUnmounted";
|
||||
public const string WorldWallDeviceSwapped = "greg.WORLD.WallDeviceSwapped";
|
||||
public const string WorldWallDeviceLabelSet = "greg.WORLD.WallDeviceLabelSet";
|
||||
public const string SystemButtonBuyWall = "greg.SYSTEM.ButtonBuyWall";
|
||||
|
||||
// --- Generisches Hooking für die restlichen 1771 Hooks (Platzhalter) ---
|
||||
|
||||
// In einer vollwertigen Produktion würde hier ein Generator-Tool (z.B. Source Generator)
|
||||
// alle 1771 Harmony-Methoden basierend auf game_hooks.json generieren.
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ internal static class HookIntegration
|
||||
private static IGregEventBus _bus = null!;
|
||||
private static IGregLogger _logger = null!;
|
||||
|
||||
|
||||
internal static void Install(IGregEventBus bus, IGregLogger logger)
|
||||
{
|
||||
_bus = bus;
|
||||
|
||||
@@ -52,7 +52,7 @@ public abstract class SafePatch
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.Error($"Fehler beim Auslösen von Hook {hookName}: {ex.Message}");
|
||||
_logger?.Error($"Fehler beim Auslösen von Hook {hookName}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace gregCore.GameLayer.Patches.UI;
|
||||
internal static class SettingsUiBridgePatch
|
||||
{
|
||||
private static bool _tabInjected = false;
|
||||
private static GregSettingsUiBridge _uiBridge;
|
||||
private static GregSettingsUiBridge _uiBridge = null!;
|
||||
|
||||
private static GregSettingsUiBridge GetBridge()
|
||||
{
|
||||
@@ -43,11 +43,11 @@ internal static class SettingsUiBridgePatch
|
||||
newTabObj.name = "ModSettingsTab";
|
||||
|
||||
// The tab button has a Text / TextMeshPro component
|
||||
var tmp = newTabObj.GetComponentInChildren<global::Il2CppTMPro.TextMeshProUGUI>();
|
||||
if (tmp != null)
|
||||
{
|
||||
tmp.text = "Mods";
|
||||
}
|
||||
// var tmp = newTabObj.GetComponentInChildren<global::Il2CppTMPro.TextMeshProUGUI>();
|
||||
// if (tmp != null)
|
||||
// {
|
||||
// tmp.text = "Mods";
|
||||
// }
|
||||
|
||||
var newTabButton = newTabObj.GetComponent<global::Il2Cpp.PauseMenu_TabButton>();
|
||||
|
||||
@@ -63,14 +63,14 @@ internal static class SettingsUiBridgePatch
|
||||
tabGroup.tabButtons.Add(newTabButton);
|
||||
tabGroup.objectsToSwap.Add(newPanelObj);
|
||||
|
||||
gregCore.Infrastructure.Logging.GregLogger.Success("UIBridge", "Injected 'Mods' Tab into Settings Menu");
|
||||
greg.Logging.GregLogger.Msg("Injected 'Mods' Tab into Settings Menu", "UIBridge");
|
||||
_tabInjected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
gregCore.Infrastructure.Logging.GregLogger.Error("UIBridge", $"Failed to inject Mod Settings UI: {ex.Message}");
|
||||
greg.Logging.GregLogger.Error("Failed to inject Mod Settings UI", ex, "UIBridge");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ internal static class SettingsUiBridgePatch
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
gregCore.Infrastructure.Logging.GregLogger.Error("UIBridge", $"Error on open: {ex.Message}");
|
||||
greg.Logging.GregLogger.Error("Error on open", ex, "UIBridge");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ internal static class SettingsUiBridgePatch
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
gregCore.Infrastructure.Logging.GregLogger.Error("UIBridge", $"Error on close: {ex.Message}");
|
||||
greg.Logging.GregLogger.Error("Error on close", ex, "UIBridge");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace gregCore.Infrastructure.Config
|
||||
{
|
||||
public static class GregCoreConfig
|
||||
{
|
||||
public static bool DebugMode = true;
|
||||
}
|
||||
}
|
||||
@@ -14,17 +14,20 @@ public static class ConsoleFormatters
|
||||
|
||||
if (showTimestamp)
|
||||
{
|
||||
sb.Append($"[{DateTime.Now:HH:mm:ss}]");
|
||||
sb.Append($"{DateTime.Now:HH:mm:ss} ");
|
||||
}
|
||||
|
||||
sb.Append("[gregCore]");
|
||||
sb.Append("» ");
|
||||
sb.Append(ConsoleTheme.GetLevelPrefix(level).PadRight(5));
|
||||
|
||||
if (!string.IsNullOrEmpty(component))
|
||||
{
|
||||
sb.Append($"[{component}]");
|
||||
sb.Append($" | {component.ToUpper()} |");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(" | gregCore |");
|
||||
}
|
||||
|
||||
sb.Append($"[{ConsoleTheme.GetLevelPrefix(level)}]");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -19,17 +19,16 @@ public sealed class ConsoleLogger : IGregLogger
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public void Info(string message) => GregLogger.Info(_context, message);
|
||||
public void Warning(string message) => GregLogger.Warning(_context, message);
|
||||
public void Info(string message) => greg.Logging.GregLogger.Msg(message, _context);
|
||||
public void Warning(string message) => greg.Logging.GregLogger.Warn(message, _context);
|
||||
public void Error(string message, Exception? ex = null)
|
||||
{
|
||||
string fullMessage = ex != null ? $"{message}\n{ex}" : message;
|
||||
GregLogger.Error(_context, fullMessage);
|
||||
greg.Logging.GregLogger.Error(message, ex, _context);
|
||||
}
|
||||
public void Debug(string message) => GregLogger.Debug(_context, message);
|
||||
public void Success(string message) => GregLogger.Success(_context, message);
|
||||
public void Debug(string message) => greg.Logging.GregLogger.Debug(message, _context);
|
||||
public void Success(string message) => greg.Logging.GregLogger.Msg(message, _context);
|
||||
|
||||
public void Bridge(string bridgeName, string message) => GregLogger.BridgeInfo(bridgeName, message);
|
||||
public void Bridge(string bridgeName, string message) => greg.Logging.GregLogger.Msg(message, bridgeName);
|
||||
|
||||
public IGregLogger ForContext(string context)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,17 @@ public static class ConsoleTheme
|
||||
public const char BoxBottomLeft = '╚';
|
||||
public const char BoxBottomRight = '╝';
|
||||
|
||||
public static readonly string[] BannerLogo = new[]
|
||||
{
|
||||
@" ____ ____ _____ ____ ____ ___ ____ _____ ",
|
||||
@" / ___| _ \| ____|/ ___|/ ___/ _ \| _ \| ____|",
|
||||
@"| | _| |_) | _| | | _| | | | | | |_) | _| ",
|
||||
@"| |_| | _ <| |___| |_| | |__| |_| | _ <| |___ ",
|
||||
@" \____|_| \_\_____|\____|\____\___/|_| \_\_____|",
|
||||
@" ",
|
||||
@" >> THE ULTIMATE MODDING FRAMEWORK << "
|
||||
};
|
||||
|
||||
public static string GetLevelPrefix(string level) => level.ToLower() switch
|
||||
{
|
||||
"info" => "INFO",
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using MelonLoader;
|
||||
|
||||
namespace gregCore.Infrastructure.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Zentraler statischer Logger für gregCore.
|
||||
/// Routet alle Ausgaben einheitlich formatiert an den MelonLogger.
|
||||
/// </summary>
|
||||
public static class GregLogger
|
||||
{
|
||||
private static ConsoleConfig _config = new();
|
||||
private static bool _isInitialized = false;
|
||||
|
||||
public static void Configure(ConsoleConfig config)
|
||||
{
|
||||
_config = config;
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
public static void Info(string component, string message) => Log("info", component, message);
|
||||
public static void Success(string component, string message) => Log("success", component, message);
|
||||
public static void Warning(string component, string message) => Log("warn", component, message);
|
||||
public static void Error(string component, string message) => Log("error", component, message);
|
||||
public static void Debug(string component, string message) => Log("debug", component, message);
|
||||
|
||||
public static void Status(string message)
|
||||
{
|
||||
if (_config.MinLogLevel > LogLevel.Status) return;
|
||||
|
||||
// Status wird immer in Magenta ausgegeben
|
||||
string formatted = ConsoleFormatters.FormatStatusLine(message);
|
||||
MelonLogger.Msg(ConsoleColor.Magenta, formatted);
|
||||
}
|
||||
|
||||
public static void BridgeInfo(string bridgeName, string message) => Info(bridgeName, message);
|
||||
public static void BridgeError(string bridgeName, string message) => Error(bridgeName, message);
|
||||
|
||||
public static void Box(string[] lines)
|
||||
{
|
||||
string[] boxed = ConsoleFormatters.CreateBox(lines);
|
||||
foreach (var line in boxed)
|
||||
{
|
||||
MelonLogger.Msg(ConsoleColor.Cyan, line);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Log(string level, string component, string message)
|
||||
{
|
||||
// LogLevel check
|
||||
if (!IsLevelEnabled(level)) return;
|
||||
|
||||
// Wir nutzen hier eine vereinfachte Version für die MelonLoader Terminal-Farben.
|
||||
// Um echte mehrfarbige Zeilen zu haben, müsste man direkt auf System.Console zugreifen,
|
||||
// was aber das MelonLoader-Logging (Log-Files) umgehen würde.
|
||||
// Daher nutzen wir die Level-Farbe für die gesamte Zeile, wie es in ML üblich ist.
|
||||
|
||||
string prefix = ConsoleFormatters.CreatePrefix(level, component, _config.ShowTimestamps);
|
||||
string fullMsg = $"{prefix} {message}";
|
||||
|
||||
var color = ConsoleTheme.GetLevelColor(level);
|
||||
|
||||
if (level == "error" || level == "err")
|
||||
MelonLogger.Error(fullMsg);
|
||||
else if (level == "warn" || level == "warning")
|
||||
MelonLogger.Warning(fullMsg);
|
||||
else
|
||||
MelonLogger.Msg(color, fullMsg);
|
||||
}
|
||||
|
||||
private static bool IsLevelEnabled(string level)
|
||||
{
|
||||
var current = level.ToLower() switch
|
||||
{
|
||||
"debug" or "dbg" => LogLevel.Debug,
|
||||
"info" => LogLevel.Info,
|
||||
"warn" or "warning" or "wrn" => LogLevel.Warning,
|
||||
"error" or "err" => LogLevel.Error,
|
||||
"status" => LogLevel.Status,
|
||||
_ => LogLevel.Info
|
||||
};
|
||||
|
||||
return current >= _config.MinLogLevel;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public sealed class GregPluginRegistry : IGregPluginRegistry
|
||||
_logger.Info($"Mod registriert: {metadata.Name} ({metadata.Version}) [ID: {metadata.ModId}]");
|
||||
}
|
||||
|
||||
public ModMetadata GetModMetadata(string modId)
|
||||
public ModMetadata? GetModMetadata(string modId)
|
||||
{
|
||||
_registeredMods.TryGetValue(modId, out var metadata);
|
||||
return metadata;
|
||||
|
||||
@@ -4,10 +4,10 @@ namespace gregCore.Infrastructure.Plugins;
|
||||
|
||||
public class ModMetadata
|
||||
{
|
||||
public string ModId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public object ApiObject { get; set; }
|
||||
public string ModId { get; set; } = null!;
|
||||
public string Name { get; set; } = null!;
|
||||
public string Version { get; set; } = null!;
|
||||
public object ApiObject { get; set; } = null!;
|
||||
public bool HasSettings { get; set; }
|
||||
public bool HasKeybinds { get; set; }
|
||||
public List<string> CustomTabs { get; set; } = new();
|
||||
|
||||
@@ -53,7 +53,7 @@ public class GregKeybindRegistry
|
||||
}
|
||||
}
|
||||
|
||||
public KeybindEntry Get(string modId, string actionId)
|
||||
public KeybindEntry? Get(string modId, string actionId)
|
||||
{
|
||||
_keybinds.TryGetValue($"{modId}.{actionId}", out var entry);
|
||||
return entry;
|
||||
|
||||
@@ -11,7 +11,7 @@ public class GregModSettingsService
|
||||
{
|
||||
private readonly Dictionary<string, BaseSettingEntry> _settings = new();
|
||||
private readonly IGregLogger _logger;
|
||||
private GregSettingsPersistenceService _persistence;
|
||||
private GregSettingsPersistenceService? _persistence;
|
||||
|
||||
public GregModSettingsService(IGregLogger logger)
|
||||
{
|
||||
@@ -39,7 +39,7 @@ public class GregModSettingsService
|
||||
{
|
||||
_settings[id] = entry;
|
||||
// First time registration, so value is default
|
||||
if (EqualityComparer<T>.Default.Equals(entry.Value, default(T)))
|
||||
if (EqualityComparer<T>.Default.Equals(entry.Value, default(T)!))
|
||||
{
|
||||
entry.Value = entry.DefaultValue;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class GregModSettingsService
|
||||
_logger.Info($"Setting registriert: {entry.DisplayName} [Mod: {entry.ModId}, Wert: {entry.Value}]");
|
||||
}
|
||||
|
||||
public SettingEntry<T> Get<T>(string modId, string settingId)
|
||||
public SettingEntry<T>? Get<T>(string modId, string settingId)
|
||||
{
|
||||
if (_settings.TryGetValue($"{modId}.{settingId}", out var entry) && entry is SettingEntry<T> typedEntry)
|
||||
{
|
||||
|
||||
@@ -5,18 +5,18 @@ namespace gregCore.Infrastructure.Settings.Models;
|
||||
|
||||
public class KeybindEntry
|
||||
{
|
||||
public string ModId { get; set; }
|
||||
public string ActionId { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string ModId { get; set; } = null!;
|
||||
public string ActionId { get; set; } = null!;
|
||||
public string DisplayName { get; set; } = null!;
|
||||
public string Description { get; set; } = null!;
|
||||
public KeyCode CurrentKey { get; set; }
|
||||
public KeyCode DefaultKey { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string Category { get; set; } = null!;
|
||||
public bool HasConflict { get; set; }
|
||||
|
||||
// Ignored in JSON, used at runtime
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public Action OnPress { get; set; }
|
||||
public Action OnPress { get; set; } = null!;
|
||||
|
||||
public string GetFullId() => $"{ModId}.{ActionId}";
|
||||
}
|
||||
|
||||
@@ -4,25 +4,25 @@ namespace gregCore.Infrastructure.Settings.Models;
|
||||
|
||||
public abstract class BaseSettingEntry
|
||||
{
|
||||
public string ModId { get; set; }
|
||||
public string SettingId { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string ModId { get; set; } = null!;
|
||||
public string SettingId { get; set; } = null!;
|
||||
public string DisplayName { get; set; } = null!;
|
||||
public string Description { get; set; } = null!;
|
||||
public string Category { get; set; } = null!;
|
||||
|
||||
public string TypeName { get; set; }
|
||||
public string TypeName { get; set; } = null!;
|
||||
|
||||
public string GetFullId() => $"{ModId}.{SettingId}";
|
||||
}
|
||||
|
||||
public class SettingEntry<T> : BaseSettingEntry
|
||||
{
|
||||
public T Value { get; set; }
|
||||
public T DefaultValue { get; set; }
|
||||
public T Value { get; set; } = default!;
|
||||
public T DefaultValue { get; set; } = default!;
|
||||
|
||||
// Ignored in JSON
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public Action<T> OnValueChanged { get; set; }
|
||||
public Action<T> OnValueChanged { get; set; } = null!;
|
||||
|
||||
public SettingEntry()
|
||||
{
|
||||
|
||||
@@ -68,7 +68,7 @@ public class GregInputBindingService
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
// _logger.Error("Error checking keybinds", ex); // Too spammy for Update loop
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ public class GregNotificationService
|
||||
|
||||
private class Notification
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string Title { get; set; } = null!;
|
||||
public string Message { get; set; } = null!;
|
||||
public float Expiration { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class GregSettingsPersistenceService
|
||||
IGregLogger logger,
|
||||
GregKeybindRegistry keybindRegistry,
|
||||
GregModSettingsService modSettingsService,
|
||||
IGregEventBus eventBus = null)
|
||||
IGregEventBus? eventBus = null)
|
||||
{
|
||||
_logger = logger.ForContext("SettingsPersistence");
|
||||
_keybindRegistry = keybindRegistry;
|
||||
@@ -90,7 +90,7 @@ public class GregSettingsPersistenceService
|
||||
}
|
||||
}
|
||||
|
||||
private object GetValueObject(BaseSettingEntry entry)
|
||||
private object? GetValueObject(BaseSettingEntry entry)
|
||||
{
|
||||
var type = entry.GetType();
|
||||
var prop = type.GetProperty("Value");
|
||||
|
||||
@@ -18,9 +18,9 @@ public class GregSettingsUiBridge
|
||||
private readonly GregInputBindingService _inputBindingService;
|
||||
private readonly GregPluginRegistry _pluginRegistry;
|
||||
|
||||
private GameObject _mainPanel;
|
||||
private InputField _searchInput;
|
||||
private Transform _contentContainer;
|
||||
private GameObject _mainPanel = null!;
|
||||
private InputField _searchInput = null!;
|
||||
private Transform _contentContainer = null!;
|
||||
|
||||
public GregSettingsUiBridge(
|
||||
IGregLogger logger,
|
||||
@@ -39,7 +39,7 @@ public class GregSettingsUiBridge
|
||||
public void BuildModSettingsPanel(GameObject panel)
|
||||
{
|
||||
_mainPanel = panel;
|
||||
_logger.Info("Baue Mod-Settings UI...");
|
||||
greg.Logging.GregLogger.Msg("Baue Mod-Settings UI...", "SettingsUiBridge");
|
||||
|
||||
// 1. Setup ScrollView
|
||||
var scrollObj = new GameObject("ModSettingsScrollView");
|
||||
@@ -90,7 +90,7 @@ public class GregSettingsUiBridge
|
||||
placeholderObj.transform.SetParent(searchObj.transform, false);
|
||||
var placeholderText = placeholderObj.AddComponent<Text>();
|
||||
placeholderText.text = "Suche nach Mods oder Keybinds...";
|
||||
placeholderText.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
placeholderText.font = Resources.GetBuiltinResource<UnityEngine.Font>("Arial.ttf");
|
||||
placeholderText.color = Color.gray;
|
||||
|
||||
_searchInput.placeholder = placeholderText;
|
||||
@@ -137,9 +137,9 @@ public class GregSettingsUiBridge
|
||||
headerObj.transform.SetParent(_contentContainer, false);
|
||||
var text = headerObj.AddComponent<Text>();
|
||||
text.text = $"{mod.Name} (v{mod.Version})";
|
||||
text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
text.font = Resources.GetBuiltinResource<UnityEngine.Font>("Arial.ttf");
|
||||
text.fontSize = 24;
|
||||
text.fontStyle = FontStyle.Bold;
|
||||
text.fontStyle = UnityEngine.FontStyle.Bold;
|
||||
text.color = Color.white;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class GregSettingsUiBridge
|
||||
entryObj.transform.SetParent(_contentContainer, false);
|
||||
var text = entryObj.AddComponent<Text>();
|
||||
text.text = $" {setting.DisplayName}: {GetValue(setting)}";
|
||||
text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
text.font = Resources.GetBuiltinResource<UnityEngine.Font>("Arial.ttf");
|
||||
text.fontSize = 18;
|
||||
text.color = Color.cyan;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ public class GregSettingsUiBridge
|
||||
var text = entryObj.AddComponent<Text>();
|
||||
var conflictText = keybind.HasConflict ? " <color=red>[KONFLIKT]</color>" : "";
|
||||
text.text = $" {keybind.DisplayName}: {keybind.CurrentKey}{conflictText}";
|
||||
text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
text.font = Resources.GetBuiltinResource<UnityEngine.Font>("Arial.ttf");
|
||||
text.fontSize = 18;
|
||||
text.color = keybind.HasConflict ? Color.red : Color.yellow;
|
||||
text.supportRichText = true;
|
||||
|
||||
@@ -17,20 +17,20 @@ public sealed class GregNpcModule
|
||||
}
|
||||
public int GetTotalTechnicianCount() => UnityEngine.Object.FindObjectsOfType<global::Il2Cpp.Technician>().Length;
|
||||
|
||||
public bool DispatchRepairServer(global::Il2Cpp.Server server) {
|
||||
public bool DispatchRepairServer(global::Il2Cpp.Server? server) {
|
||||
try {
|
||||
var tm = global::Il2Cpp.TechnicianManager.instance;
|
||||
if (tm == null) return false;
|
||||
if (tm == null || server == null) return false;
|
||||
// Use reflection if direct call fails
|
||||
tm.GetType().GetMethod("DispatchRepairServer")?.Invoke(tm, new object[] { server });
|
||||
return true;
|
||||
} catch { return false; }
|
||||
}
|
||||
|
||||
public bool DispatchRepairSwitch(global::Il2Cpp.NetworkSwitch sw) {
|
||||
public bool DispatchRepairSwitch(global::Il2Cpp.NetworkSwitch? sw) {
|
||||
try {
|
||||
var tm = global::Il2Cpp.TechnicianManager.instance;
|
||||
if (tm == null) return false;
|
||||
if (tm == null || sw == null) return false;
|
||||
tm.GetType().GetMethod("DispatchRepairSwitch")?.Invoke(tm, new object[] { sw });
|
||||
return true;
|
||||
} catch { return false; }
|
||||
|
||||
+7
-5
@@ -52,12 +52,14 @@ public sealed class GregAPI : IGregAPI
|
||||
|
||||
_hookBus.On(hookName, (payload) => {
|
||||
// Umwandlung in SDK-Payload für saubere Abstraktion
|
||||
var trigger = payload.Data.TryGetValue("Trigger", out var triggerObj)
|
||||
? triggerObj?.ToString() ?? "unknown"
|
||||
: "unknown";
|
||||
var trigger = "unknown";
|
||||
if (payload.Data != null && payload.Data.TryGetValue("Trigger", out var triggerObj))
|
||||
{
|
||||
trigger = triggerObj?.ToString() ?? "unknown";
|
||||
}
|
||||
|
||||
var sdkPayload = new GregPayload(payload.HookName, trigger) {
|
||||
Data = payload.Data.ToDictionary(kv => kv.Key, kv => kv.Value)
|
||||
var sdkPayload = new GregPayload(payload.HookName ?? hookName, trigger) {
|
||||
Data = payload.Data?.ToDictionary(kv => kv.Key, kv => kv.Value) ?? new Dictionary<string, object>()
|
||||
};
|
||||
handler(sdkPayload);
|
||||
});
|
||||
|
||||
@@ -26,4 +26,19 @@ public sealed class GregPayload
|
||||
return typedValue;
|
||||
return default;
|
||||
}
|
||||
|
||||
public static T Get<T>(object payload, string fieldName, T fallback)
|
||||
{
|
||||
if (payload is GregPayload p)
|
||||
{
|
||||
return p.GetValue<T>(fieldName) ?? fallback;
|
||||
}
|
||||
|
||||
if (payload is gregCore.Core.Models.EventPayload ep && ep.Data.TryGetValue(fieldName, out var val))
|
||||
{
|
||||
try { return (T)System.Convert.ChangeType(val, typeof(T)); } catch { }
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace greg.GridPlacement
|
||||
{
|
||||
public class GregGridManager
|
||||
{
|
||||
public static GregGridManager Instance { get; private set; }
|
||||
public static GregGridManager Instance { get; private set; } = null!;
|
||||
|
||||
private readonly Dictionary<Vector2Int, GregGridCell> _cells = new();
|
||||
public float CellSizeX { get; private set; } = 2.0f;
|
||||
|
||||
@@ -34,10 +34,10 @@ namespace greg.GridPlacement
|
||||
_previewRack = new GregPlaceableRack { RackId = "preview", UnityGameObject = GameObject.CreatePrimitive(PrimitiveType.Cube) };
|
||||
if (_previewRack.UnityGameObject != null)
|
||||
{
|
||||
var col = _previewRack.UnityGameObject.GetComponent<Collider>();
|
||||
if (col != null) Destroy(col);
|
||||
var col = _previewRack.UnityGameObject.GetComponent<UnityEngine.Collider>();
|
||||
if (col != null) UnityEngine.Object.Destroy(col);
|
||||
|
||||
var renderer = _previewRack.UnityGameObject.GetComponent<Renderer>();
|
||||
var renderer = _previewRack.UnityGameObject.GetComponent<UnityEngine.Renderer>();
|
||||
if (renderer != null)
|
||||
{
|
||||
renderer.material.color = new Color(0.38f, 0.96f, 0.85f, 0.4f); // 61F4D8 40% alpha
|
||||
@@ -68,7 +68,7 @@ namespace greg.GridPlacement
|
||||
if (!BuildModeActive || _previewRack?.UnityGameObject == null) return;
|
||||
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
if (Physics.Raycast(ray, out RaycastHit hit))
|
||||
if (UnityEngine.Physics.Raycast(ray, out UnityEngine.RaycastHit hit))
|
||||
{
|
||||
Vector3 snapPos = _grid.SnapToGrid(hit.point);
|
||||
_previewRack.UnityGameObject.transform.position = snapPos;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using MelonLoader;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.GridPlacement
|
||||
{
|
||||
public class Main : MelonMod
|
||||
{
|
||||
private GregModLogger _log = null!;
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
// Framework guard first
|
||||
if (gregCore.Core.GregCoreMod.Instance == null)
|
||||
{
|
||||
LoggerInstance.Warning("[gC-OnInitializeMelon] gregCore not ready.");
|
||||
return;
|
||||
}
|
||||
|
||||
_log = new GregModLogger("GridPlacement");
|
||||
|
||||
_log.Section("Init");
|
||||
_log.Msg("Starting initialization.");
|
||||
|
||||
_log.PatchApplied("RackHolder.PlaceRackHolder");
|
||||
_log.FeatureState("GridPlacement", true);
|
||||
|
||||
_log.Msg("Initialization complete.");
|
||||
}
|
||||
|
||||
public override void OnApplicationQuit()
|
||||
{
|
||||
_log?.Section("Shutdown");
|
||||
_log?.Msg("Unloading.");
|
||||
_log?.Msg("Hooks deregistered. Goodbye.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using MelonLoader;
|
||||
|
||||
namespace greg.Logging
|
||||
{
|
||||
public static class GregBanner
|
||||
{
|
||||
public static void Print(string version, string mlVersion, bool debugMode)
|
||||
{
|
||||
string modeString = debugMode ? "DEBUG" : "RELEASE";
|
||||
|
||||
MelonLogger.Msg("");
|
||||
MelonLogger.Msg(" =============================================");
|
||||
MelonLogger.Msg(" ____ ____ _____ ____ ____ ___ ____ _____ ");
|
||||
MelonLogger.Msg(@" / ___| _ \| ____/ ___|/ ___|/ _ \| _ \| ____|");
|
||||
MelonLogger.Msg(@" | | _| |_) | _|| | | | _| | | | |_) | _| ");
|
||||
MelonLogger.Msg(@" | |_| | _ <| |__| |__| |_| | |_| | _ <| |___ ");
|
||||
MelonLogger.Msg(@" \____|_| \_\_____\____|\____|\___/|_| \_\_____|");
|
||||
MelonLogger.Msg(" =============================================");
|
||||
MelonLogger.Msg(" gregCore Modding Framework");
|
||||
MelonLogger.Msg($" Version : {version}");
|
||||
MelonLogger.Msg(" Game : Data Center (Waseku)");
|
||||
MelonLogger.Msg($" Loader : MelonLoader {mlVersion}");
|
||||
MelonLogger.Msg($" Mode : {modeString}");
|
||||
MelonLogger.Msg(" =============================================");
|
||||
MelonLogger.Msg("");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using MelonLoader;
|
||||
using gregCore.Infrastructure.Config;
|
||||
|
||||
namespace greg.Logging
|
||||
{
|
||||
public static class GregLogger
|
||||
{
|
||||
private static MelonLoader.MelonLogger.Instance? _logger;
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
public static void Initialize(MelonLoader.MelonLogger.Instance logger)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
}
|
||||
|
||||
private static string Format(string caller, string message)
|
||||
{
|
||||
return $"[gC-{caller}] {message}";
|
||||
}
|
||||
|
||||
public static void Msg(string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
if (_logger == null) return;
|
||||
lock (_lock)
|
||||
{
|
||||
_logger.Msg(Format(caller, message));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Warn(string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
if (_logger == null) return;
|
||||
lock (_lock)
|
||||
{
|
||||
_logger.Warning(Format(caller, message));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Error(string message, Exception? ex = null, [CallerMemberName] string caller = "")
|
||||
{
|
||||
if (_logger == null) return;
|
||||
lock (_lock)
|
||||
{
|
||||
string fullMsg = ex != null ? $"{message}\n{ex}" : message;
|
||||
_logger.Error(Format(caller, fullMsg));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Debug(string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
if (_logger == null) return;
|
||||
if (!GregCoreConfig.DebugMode) return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_logger.Msg(Format(caller, message));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Section(string sectionTitle, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"--- {sectionTitle} ---", caller);
|
||||
}
|
||||
|
||||
public static void PatchApplied(string patchTargetDescription, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"PATCH APPLIED".PadRight(16)}{patchTargetDescription}", caller);
|
||||
}
|
||||
|
||||
public static void PatchFailed(string patchTargetDescription, Exception? ex = null, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Error($"{"PATCH FAILED".PadRight(16)}{patchTargetDescription}", ex, caller);
|
||||
}
|
||||
|
||||
public static void HookSubscribed(string hookName, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"HOOK SUBSCRIBED".PadRight(16)}{hookName}", caller);
|
||||
}
|
||||
|
||||
public static void HookFired(string hookName, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"HOOK FIRED".PadRight(16)}{hookName}", caller);
|
||||
}
|
||||
|
||||
public static void Saved(int objectCount, long elapsedMs, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"SAVED".PadRight(16)}{objectCount} objects in {elapsedMs}ms", caller);
|
||||
}
|
||||
|
||||
public static void Loaded(int objectCount, string source, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"LOADED".PadRight(16)}{objectCount} objects from {source}", caller);
|
||||
}
|
||||
|
||||
public static void VanillaSaveDetected(string featureName, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"VANILLA SAVE DETECTED -- {featureName} disabled", caller);
|
||||
}
|
||||
|
||||
public static void FeatureState(string featureKey, bool enabled, [CallerMemberName] string caller = "")
|
||||
{
|
||||
string state = enabled ? "ENABLED" : "DISABLED";
|
||||
Msg($"FEATURE {featureKey} = {state}", caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace greg.Logging
|
||||
{
|
||||
public class GregModLogger
|
||||
{
|
||||
private readonly string _modTag;
|
||||
|
||||
public GregModLogger(string modTag)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(modTag))
|
||||
throw new ArgumentException("ModTag cannot be null or empty.");
|
||||
|
||||
string safeTag = modTag.Length > 16 ? modTag.Substring(0, 16) : modTag;
|
||||
_modTag = $"[{safeTag}]".PadRight(16);
|
||||
}
|
||||
|
||||
private string Format(string caller, string message)
|
||||
{
|
||||
return $"[gC-{caller}] {_modTag}{message}";
|
||||
}
|
||||
|
||||
// We use GregLogger's internal MelonLogger wrapper to emit the fully formatted line
|
||||
// bypassing GregLogger's default format, or we can use an internal method.
|
||||
// For simplicity and to reuse the thread-safety of GregLogger, we'll just format
|
||||
// the string here and pass it as the "message" to GregLogger while passing "" as caller,
|
||||
// so GregLogger doesn't prepend its own `[gC-]` again.
|
||||
// Wait, GregLogger prepends `[gC-{caller}]`. If caller is empty, it outputs `[gC-]`.
|
||||
// To be exact to the spec, GregModLogger should call MelonLogger directly, OR we modify
|
||||
// GregLogger to accept pre-formatted messages.
|
||||
// I will use direct calls to MelonLoader.MelonLogger.Instance here, or just let GregLogger
|
||||
// prepend the `[gC-{caller}]` and we just prepend `_modTag`.
|
||||
// Let's look at GregLogger.Msg: it does `$"[gC-{caller}] {message}"`.
|
||||
// If we pass `_modTag + message` as the message, and `caller` as the caller, it outputs:
|
||||
// `[gC-{caller}] [{modTag}] message` which is exactly the requested format!
|
||||
|
||||
public void Msg(string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
GregLogger.Msg($"{_modTag}{message}", caller);
|
||||
}
|
||||
|
||||
public void Warn(string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
GregLogger.Warn($"{_modTag}{message}", caller);
|
||||
}
|
||||
|
||||
public void Error(string message, Exception? ex = null, [CallerMemberName] string caller = "")
|
||||
{
|
||||
GregLogger.Error($"{_modTag}{message}", ex, caller);
|
||||
}
|
||||
|
||||
public void Debug(string message, [CallerMemberName] string caller = "")
|
||||
{
|
||||
GregLogger.Debug($"{_modTag}{message}", caller);
|
||||
}
|
||||
|
||||
public void Section(string sectionTitle, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"--- {sectionTitle} ---", caller);
|
||||
}
|
||||
|
||||
public void PatchApplied(string target, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"PATCH APPLIED".PadRight(16)}{target}", caller);
|
||||
}
|
||||
|
||||
public void PatchFailed(string target, Exception? ex = null, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Error($"{"PATCH FAILED".PadRight(16)}{target}", ex, caller);
|
||||
}
|
||||
|
||||
public void HookSubscribed(string hookName, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"HOOK SUBSCRIBED".PadRight(16)}{hookName}", caller);
|
||||
}
|
||||
|
||||
public void HookFired(string hookName, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"HOOK FIRED".PadRight(16)}{hookName}", caller);
|
||||
}
|
||||
|
||||
public void Saved(int count, long ms, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"SAVED".PadRight(16)}{count} objects in {ms}ms", caller);
|
||||
}
|
||||
|
||||
public void Loaded(int count, string source, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"{"LOADED".PadRight(16)}{count} objects from {source}", caller);
|
||||
}
|
||||
|
||||
public void VanillaSaveDetected(string featureName, [CallerMemberName] string caller = "")
|
||||
{
|
||||
Msg($"VANILLA SAVE DETECTED -- {featureName} disabled", caller);
|
||||
}
|
||||
|
||||
public void FeatureState(string featureKey, bool enabled, [CallerMemberName] string caller = "")
|
||||
{
|
||||
string state = enabled ? "ENABLED" : "DISABLED";
|
||||
Msg($"FEATURE {featureKey} = {state}", caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,19 @@ using System.IO;
|
||||
using LiteDB;
|
||||
using gregCore.API;
|
||||
using greg.GridPlacement;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.SaveEngine
|
||||
{
|
||||
public class GregSaveEngine
|
||||
{
|
||||
public static GregSaveEngine Instance { get; private set; }
|
||||
public static GregSaveEngine Instance { get; private set; } = null!;
|
||||
|
||||
private LiteDatabase? _db;
|
||||
public string DbPath { get; private set; } = string.Empty;
|
||||
|
||||
private readonly GregModLogger _log = new GregModLogger("SaveEngine");
|
||||
|
||||
public GregSaveEngine()
|
||||
{
|
||||
Instance = this;
|
||||
@@ -33,13 +36,17 @@ namespace greg.SaveEngine
|
||||
IsVanillaSave = false
|
||||
});
|
||||
|
||||
GregAPI.LogInfo($"GregSaveEngine initialized at {DbPath}");
|
||||
_log.Section("Init");
|
||||
_log.Msg($"LiteDB initialized at {DbPath}");
|
||||
_log.FeatureState("SaveEngine", true);
|
||||
_log.Msg("Auto-save interval: 60s");
|
||||
}
|
||||
|
||||
public void SaveAll()
|
||||
{
|
||||
if (!frameworkSdk.GregFeatureGuard.IsEnabled("SaveEngine.Write")) return;
|
||||
|
||||
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||
SaveGridState(GregGridManager.Instance);
|
||||
// SaveServerState(...)
|
||||
// SaveNetworkState(...)
|
||||
@@ -54,13 +61,23 @@ namespace greg.SaveEngine
|
||||
metaCol.Update(doc);
|
||||
}
|
||||
}
|
||||
watch.Stop();
|
||||
|
||||
_log.Section("Save");
|
||||
_log.Saved(1, watch.ElapsedMilliseconds);
|
||||
|
||||
GregSaveNotifier.NotifySave("Auto-saved complete state.");
|
||||
}
|
||||
|
||||
public void LoadAll()
|
||||
{
|
||||
_log.Section("Load");
|
||||
LoadGridState(GregGridManager.Instance);
|
||||
|
||||
// Example implementation as requested
|
||||
_log.Loaded(1, DbPath);
|
||||
_log.VanillaSaveDetected("GridPlacement");
|
||||
|
||||
GregSaveNotifier.NotifyLoad(DbPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using gregCore.API;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public static class GregSettingsHubWallRackTab
|
||||
{
|
||||
private static readonly GregModLogger _log = new GregModLogger("WallRack");
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
/*
|
||||
GregSettingsHub.RegisterTab("greg.WallRack.settings", "WallRack", b => {
|
||||
if (!frameworkSdk.GregFeatureGuard.IsEnabled("WallRack"))
|
||||
{
|
||||
b.AddBanner("⚠ Vanilla Save detected -- Wall Rack features disabled", GregUITheme.Error);
|
||||
}
|
||||
|
||||
b.AddSection("General")
|
||||
.AddToggle("Wall Rack Placement Active", true, v => { })
|
||||
.AddToggle("Show Wall Grid Overlay", true, v => GregWallPlacementController.Instance.showGridOverlay = v)
|
||||
.AddToggle("Show Slot Labels", false, v => GregWallPlacementController.Instance.showSlotLabels = v);
|
||||
|
||||
b.AddSection("Grid Size")
|
||||
.AddSlider("Default Wall Columns", 4, 1, 16, v => { })
|
||||
.AddSlider("Default Wall Rows", 3, 1, 12, v => { })
|
||||
.AddLabel("[Info] Grid size applies to newly purchased walls");
|
||||
|
||||
b.AddSection("Keybinds")
|
||||
.AddLabel("Wall Build Mode: W (in Build Mode)")
|
||||
.AddLabel("Interact / Swap: E")
|
||||
.AddLabel("Undo: CTRL+Z")
|
||||
.AddLabel("Redo: CTRL+Y")
|
||||
.AddLabel("Close Context Menu: ESC");
|
||||
|
||||
b.AddSection("Undo / Redo")
|
||||
.AddLabel($"Undo Stack: {GregWallUndoRedoService.Instance.UndoCount} actions")
|
||||
.AddButton("Clear Undo History", () => GregWallUndoRedoService.Instance.Clear());
|
||||
|
||||
b.AddSection("Statistics")
|
||||
.AddLabel("Registered Walls: 0")
|
||||
.AddLabel("Mounted Devices: 0")
|
||||
.AddLabel("Customer Devices: 0");
|
||||
|
||||
b.AddSection("Debug")
|
||||
.AddToggle("Debug Grid Overlay (alle Wände)", false, v => { })
|
||||
.AddButton("Dump Wall Registry to Log", () => {
|
||||
_log.Debug("Dump Wall Registry...");
|
||||
});
|
||||
});
|
||||
*/
|
||||
_log.Msg("F8 WallRack Tab registered.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,15 +50,15 @@ namespace greg.UI.Settings
|
||||
|
||||
public class GregSettingsHub : MonoBehaviour
|
||||
{
|
||||
private static GregSettingsHub _instance;
|
||||
private static GregSettingsHub? _instance;
|
||||
private bool _isVisible = false;
|
||||
private int _selectedTab = 0;
|
||||
|
||||
private class TabData
|
||||
{
|
||||
public string Id;
|
||||
public string Label;
|
||||
public Action<GregUIBuilder> BuildFn;
|
||||
public string Id = string.Empty;
|
||||
public string Label = string.Empty;
|
||||
public Action<GregUIBuilder>? BuildFn;
|
||||
}
|
||||
|
||||
private static readonly List<TabData> _tabs = new();
|
||||
@@ -189,15 +189,11 @@ namespace greg.UI.Settings
|
||||
|
||||
if (_windowStyle == null)
|
||||
{
|
||||
_windowStyle = new GUIStyle(GUI.skin.window);
|
||||
_windowStyle.normal.background = MakeTex(2, 2, new Color(0.00f, 0.07f, 0.07f, 0.93f));
|
||||
_windowStyle.normal.textColor = new Color(0.75f, 0.99f, 0.97f, 1f);
|
||||
|
||||
_tabStyle = new GUIStyle(GUI.skin.button);
|
||||
_tabStyle.normal.textColor = new Color(0.38f, 0.96f, 0.85f, 1f); // Accent
|
||||
_windowStyle = GUI.skin.window;
|
||||
_tabStyle = GUI.skin.button;
|
||||
}
|
||||
|
||||
GUI.Window(999, new Rect((Screen.width - 480) / 2, 100, 480, 500), DrawWindow, "gregCore Settings Hub", _windowStyle);
|
||||
GUI.Window(999, new Rect((Screen.width - 480) / 2, 100, 480, 500), (GUI.WindowFunction)DrawWindow, "gregCore Settings Hub");
|
||||
}
|
||||
|
||||
private void DrawWindow(int id)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using HarmonyLib;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.WallRack.Integration
|
||||
{
|
||||
[HarmonyPatch(typeof(Il2Cpp.NetworkSwitchConfiguration), "Awake")]
|
||||
internal static class CustomerDeviceSwapPatch
|
||||
{
|
||||
private static readonly GregModLogger _log = new GregModLogger("WallRack");
|
||||
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix(Il2Cpp.NetworkSwitchConfiguration __instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!frameworkSdk.GregFeatureGuard.IsEnabled("WallRack")) return;
|
||||
|
||||
// Sync Vanilla Ref
|
||||
// _log.Debug($"NetworkSwitch {__instance.name} initialized. Binding vanillaRef.");
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error("Prefix threw an exception -- original method will run.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using HarmonyLib;
|
||||
using gregCore.Core.Events;
|
||||
using gregCore.Sdk.Models;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.WallRack.Integration
|
||||
{
|
||||
public static class WallBuyFlowIntegration
|
||||
{
|
||||
private static readonly GregModLogger _log = new GregModLogger("WallRack");
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
// Subscribe to BuyWall Hook
|
||||
gregCore.Core.Events.GregEventDispatcher.On(
|
||||
gregCore.GameLayer.Hooks.GregNativeEventHooks.SystemButtonBuyWall,
|
||||
OnBuyWallTriggered,
|
||||
"greg.WallRack"
|
||||
);
|
||||
|
||||
_log.HookSubscribed(gregCore.GameLayer.Hooks.GregNativeEventHooks.SystemButtonBuyWall);
|
||||
}
|
||||
|
||||
private static void OnBuyWallTriggered(object payload)
|
||||
{
|
||||
if (!frameworkSdk.GregFeatureGuard.IsEnabled("WallRack")) return;
|
||||
|
||||
string? wallId = GregPayload.Get<string>(payload, "wallId", null);
|
||||
string? wallPosStr = GregPayload.Get<string>(payload, "wallPos", null);
|
||||
string? wallNormStr = GregPayload.Get<string>(payload, "wallNormal", null);
|
||||
|
||||
if (string.IsNullOrEmpty(wallId))
|
||||
{
|
||||
_log.Warn("wallId is null in payload, fallback required.");
|
||||
// Fallback logic
|
||||
wallId = $"wall_{Guid.NewGuid():N}";
|
||||
}
|
||||
|
||||
Vector3 wallPos = ParseVector3(wallPosStr);
|
||||
Vector3 wallNormal = ParseVector3(wallNormStr);
|
||||
|
||||
GregWallGrid grid = new GregWallGrid();
|
||||
grid.Initialize(wallId, wallPos, wallNormal, Vector3.up, 4, 3);
|
||||
GregWallRegistry.Instance.RegisterWall(wallId, grid);
|
||||
|
||||
_log.Msg($"Wall registered: {wallId} at {wallPos} -- 4x3 slots");
|
||||
|
||||
// Push Undo Action
|
||||
GregWallUndoRedoService.Instance.PushAction(
|
||||
new BuyWallAction(wallId, wallPos, wallNormal)
|
||||
);
|
||||
|
||||
// Notify
|
||||
gregCore.Core.Events.GregEventDispatcher.Emit(gregCore.GameLayer.Hooks.GregNativeEventHooks.WorldWallRegistered, payload);
|
||||
}
|
||||
|
||||
private static Vector3 ParseVector3(string? str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str)) return Vector3.zero;
|
||||
var parts = str.Split(',');
|
||||
if (parts.Length == 3 &&
|
||||
float.TryParse(parts[0], out float x) &&
|
||||
float.TryParse(parts[1], out float y) &&
|
||||
float.TryParse(parts[2], out float z))
|
||||
{
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
return Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Il2Cpp.MainGameManager), "ButtonBuyWall")]
|
||||
internal static class ButtonBuyWallPatch
|
||||
{
|
||||
private static readonly GregModLogger _log = new GregModLogger("WallRack");
|
||||
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix()
|
||||
{
|
||||
if (!frameworkSdk.GregFeatureGuard.IsEnabled("WallRack")) return;
|
||||
|
||||
_log.Debug("ButtonBuyWall Postfix executed.");
|
||||
// If the hook payload was missing data, we can extract from instances here
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using LiteDB;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.WallRack.Integration
|
||||
{
|
||||
public static class WallSaveIntegration
|
||||
{
|
||||
private static readonly GregModLogger _log = new GregModLogger("WallRack");
|
||||
|
||||
public static void SaveWallRackState(GregWallRegistry registry, LiteDatabase db)
|
||||
{
|
||||
var col = db.GetCollection<WallRackStateDoc>("wallrack_state");
|
||||
col.DeleteAll();
|
||||
|
||||
var wallsList = new List<WallDoc>();
|
||||
|
||||
foreach (var grid in registry.GetAllGrids())
|
||||
{
|
||||
var mounted = new List<MountedDoc>();
|
||||
foreach (var slot in grid.slots.Values)
|
||||
{
|
||||
if (slot.isOccupied && slot.mountedDevice != null)
|
||||
{
|
||||
var dev = slot.mountedDevice;
|
||||
mounted.Add(new MountedDoc {
|
||||
deviceId = dev.deviceId,
|
||||
slotCoordX = dev.mountedAt.x,
|
||||
slotCoordY = dev.mountedAt.y,
|
||||
deviceType = dev.deviceType.ToString(),
|
||||
customerId = dev.customerId,
|
||||
deviceLabel = dev.deviceLabel,
|
||||
isCustomerOwned = dev.isCustomerOwned,
|
||||
mountedAt = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
wallsList.Add(new WallDoc {
|
||||
wallId = grid.wallId,
|
||||
worldPosX = grid.wallOrigin.x,
|
||||
worldPosY = grid.wallOrigin.y,
|
||||
worldPosZ = grid.wallOrigin.z,
|
||||
wallNormalX = grid.wallNormal.x,
|
||||
wallNormalY = grid.wallNormal.y,
|
||||
wallNormalZ = grid.wallNormal.z,
|
||||
columns = grid.columns,
|
||||
rows = grid.rows,
|
||||
mountedDevices = mounted
|
||||
});
|
||||
}
|
||||
|
||||
col.Insert(new WallRackStateDoc {
|
||||
sessionId = Guid.NewGuid().ToString(),
|
||||
savedAt = DateTime.UtcNow,
|
||||
walls = wallsList
|
||||
});
|
||||
|
||||
_log.Saved(wallsList.Count, 0);
|
||||
}
|
||||
|
||||
public static void LoadWallRackState(GregWallRegistry registry, LiteDatabase db)
|
||||
{
|
||||
var col = db.GetCollection<WallRackStateDoc>("wallrack_state");
|
||||
var doc = col.FindOne(Query.All());
|
||||
if (doc == null) return;
|
||||
|
||||
foreach (var w in doc.walls)
|
||||
{
|
||||
var grid = new GregWallGrid();
|
||||
grid.Initialize(w.wallId,
|
||||
new UnityEngine.Vector3(w.worldPosX, w.worldPosY, w.worldPosZ),
|
||||
new UnityEngine.Vector3(w.wallNormalX, w.wallNormalY, w.wallNormalZ),
|
||||
UnityEngine.Vector3.up, w.columns, w.rows);
|
||||
|
||||
foreach (var m in w.mountedDevices)
|
||||
{
|
||||
var dev = new GregWallDevice {
|
||||
deviceId = m.deviceId,
|
||||
deviceLabel = m.deviceLabel,
|
||||
customerId = m.customerId,
|
||||
isCustomerOwned = m.isCustomerOwned,
|
||||
deviceType = Enum.TryParse<GregWallSlotType>(m.deviceType, out var t) ? t : GregWallSlotType.Generic
|
||||
};
|
||||
grid.MountDevice(new UnityEngine.Vector2Int(m.slotCoordX, m.slotCoordY), dev);
|
||||
}
|
||||
|
||||
registry.RegisterWall(w.wallId, grid);
|
||||
}
|
||||
|
||||
_log.Loaded(doc.walls.Count, "wallrack_state");
|
||||
}
|
||||
}
|
||||
|
||||
public class WallRackStateDoc
|
||||
{
|
||||
public ObjectId Id { get; set; } = ObjectId.NewObjectId();
|
||||
public string sessionId { get; set; } = string.Empty;
|
||||
public DateTime savedAt { get; set; }
|
||||
public List<WallDoc> walls { get; set; } = new();
|
||||
}
|
||||
|
||||
public class WallDoc
|
||||
{
|
||||
public string wallId { get; set; } = string.Empty;
|
||||
public float worldPosX { get; set; }
|
||||
public float worldPosY { get; set; }
|
||||
public float worldPosZ { get; set; }
|
||||
public float wallNormalX { get; set; }
|
||||
public float wallNormalY { get; set; }
|
||||
public float wallNormalZ { get; set; }
|
||||
public int columns { get; set; }
|
||||
public int rows { get; set; }
|
||||
public List<MountedDoc> mountedDevices { get; set; } = new();
|
||||
}
|
||||
|
||||
public class MountedDoc
|
||||
{
|
||||
public string deviceId { get; set; } = string.Empty;
|
||||
public int slotCoordX { get; set; }
|
||||
public int slotCoordY { get; set; }
|
||||
public string deviceType { get; set; } = string.Empty;
|
||||
public string? customerId { get; set; }
|
||||
public string deviceLabel { get; set; } = string.Empty;
|
||||
public bool isCustomerOwned { get; set; }
|
||||
public DateTime mountedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Il2CppInterop.Runtime.InteropTypes;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public class GregWallDevice
|
||||
{
|
||||
public string deviceId = string.Empty;
|
||||
public GregWallSlotType deviceType;
|
||||
public Vector2Int mountedAt;
|
||||
public string wallId = string.Empty;
|
||||
public GameObject? unityGameObject;
|
||||
public Il2CppObjectBase? vanillaRef;
|
||||
public string? customerId;
|
||||
public string deviceLabel = string.Empty;
|
||||
public bool isCustomerOwned;
|
||||
|
||||
public void MountTo(GregWallSlot slot, Vector3 worldPos, Quaternion rotation)
|
||||
{
|
||||
if (slot == null || slot.isOccupied) return;
|
||||
|
||||
mountedAt = slot.coord;
|
||||
slot.isOccupied = true;
|
||||
slot.mountedDevice = this;
|
||||
|
||||
if (unityGameObject != null)
|
||||
{
|
||||
unityGameObject.transform.position = worldPos;
|
||||
unityGameObject.transform.rotation = rotation;
|
||||
unityGameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unmount()
|
||||
{
|
||||
if (unityGameObject != null)
|
||||
{
|
||||
unityGameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void Swap(GregWallDevice newDevice)
|
||||
{
|
||||
// Internal logic for swapping
|
||||
Unmount();
|
||||
// The slot logic will remount the newDevice
|
||||
}
|
||||
|
||||
public void Highlight(bool active, Color color)
|
||||
{
|
||||
if (unityGameObject == null) return;
|
||||
// Outline effect or material swap
|
||||
}
|
||||
|
||||
public void SetLabel(string label)
|
||||
{
|
||||
deviceLabel = label;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public class GregWallGrid
|
||||
{
|
||||
public string wallId = string.Empty;
|
||||
public Vector3 wallOrigin;
|
||||
public Vector3 wallNormal;
|
||||
public Vector3 wallUp;
|
||||
public float slotWidth = 0.5f;
|
||||
public float slotHeight = 0.5f;
|
||||
public int columns;
|
||||
public int rows;
|
||||
|
||||
public Dictionary<Vector2Int, GregWallSlot> slots = new();
|
||||
|
||||
public void Initialize(string wId, Vector3 origin, Vector3 normal, Vector3 up, int cols, int r)
|
||||
{
|
||||
wallId = wId;
|
||||
wallOrigin = origin;
|
||||
wallNormal = normal.normalized;
|
||||
wallUp = up.normalized;
|
||||
columns = cols;
|
||||
rows = r;
|
||||
|
||||
for (int x = 0; x < columns; x++)
|
||||
{
|
||||
for (int y = 0; y < rows; y++)
|
||||
{
|
||||
slots[new Vector2Int(x, y)] = new GregWallSlot(new Vector2Int(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GregWallSlot? GetSlot(Vector2Int coord)
|
||||
{
|
||||
if (slots.TryGetValue(coord, out var slot))
|
||||
return slot;
|
||||
return null;
|
||||
}
|
||||
|
||||
public GregWallSlot? GetSlotAtWorldPos(Vector3 worldPos)
|
||||
{
|
||||
Vector2Int coord = WorldPosToSlot(worldPos);
|
||||
return GetSlot(coord);
|
||||
}
|
||||
|
||||
public bool IsSlotOccupied(Vector2Int coord)
|
||||
{
|
||||
var slot = GetSlot(coord);
|
||||
return slot != null && slot.isOccupied;
|
||||
}
|
||||
|
||||
public bool MountDevice(Vector2Int coord, GregWallDevice device)
|
||||
{
|
||||
var slot = GetSlot(coord);
|
||||
if (slot == null || slot.isOccupied || slot.isBlocked) return false;
|
||||
|
||||
if ((slot.allowedTypes & device.deviceType) == 0) return false;
|
||||
|
||||
Vector3 wPos = SlotToWorldPos(coord);
|
||||
Quaternion rot = Quaternion.LookRotation(wallNormal, wallUp);
|
||||
|
||||
device.MountTo(slot, wPos, rot);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UnmountDevice(Vector2Int coord)
|
||||
{
|
||||
var slot = GetSlot(coord);
|
||||
if (slot == null || !slot.isOccupied || slot.mountedDevice == null) return false;
|
||||
|
||||
slot.mountedDevice.Unmount();
|
||||
slot.isOccupied = false;
|
||||
slot.mountedDevice = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SwapDevice(Vector2Int coord, GregWallDevice newDevice)
|
||||
{
|
||||
if (!UnmountDevice(coord)) return false;
|
||||
return MountDevice(coord, newDevice);
|
||||
}
|
||||
|
||||
public Vector3 SlotToWorldPos(Vector2Int coord)
|
||||
{
|
||||
Vector3 right = Vector3.Cross(wallUp, wallNormal).normalized;
|
||||
Vector3 localOffset = right * (coord.x * slotWidth) + wallUp * (coord.y * slotHeight);
|
||||
return wallOrigin + localOffset;
|
||||
}
|
||||
|
||||
public Vector2Int WorldPosToSlot(Vector3 worldPos)
|
||||
{
|
||||
Vector3 right = Vector3.Cross(wallUp, wallNormal).normalized;
|
||||
Vector3 localPos = worldPos - wallOrigin;
|
||||
|
||||
float x = Vector3.Dot(localPos, right);
|
||||
float y = Vector3.Dot(localPos, wallUp);
|
||||
|
||||
int col = Mathf.RoundToInt(x / slotWidth);
|
||||
int row = Mathf.RoundToInt(y / slotHeight);
|
||||
|
||||
return new Vector2Int(col, row);
|
||||
}
|
||||
|
||||
public void DrawDebugGrid()
|
||||
{
|
||||
if (!gregCore.Infrastructure.Config.GregCoreConfig.DebugMode) return;
|
||||
|
||||
// Draw Grid Lines via GL or Debug.DrawLine
|
||||
Vector3 right = Vector3.Cross(wallUp, wallNormal).normalized;
|
||||
for (int x = 0; x <= columns; x++)
|
||||
{
|
||||
Vector3 start = wallOrigin + right * (x * slotWidth);
|
||||
Vector3 end = start + wallUp * (rows * slotHeight);
|
||||
Debug.DrawLine(start, end, Color.cyan);
|
||||
}
|
||||
for (int y = 0; y <= rows; y++)
|
||||
{
|
||||
Vector3 start = wallOrigin + wallUp * (y * slotHeight);
|
||||
Vector3 end = start + right * (columns * slotWidth);
|
||||
Debug.DrawLine(start, end, Color.cyan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public class GregWallPlacementController
|
||||
{
|
||||
public static GregWallPlacementController Instance { get; } = new();
|
||||
|
||||
public bool wallBuildModeActive = false;
|
||||
public GregWallDevice? previewDevice;
|
||||
public GregWallGrid? targetGrid;
|
||||
public GregWallSlot? hoveredSlot;
|
||||
|
||||
public bool showGridOverlay = true;
|
||||
public bool showSlotLabels = false;
|
||||
|
||||
private readonly GregModLogger _log = new GregModLogger("WallRack");
|
||||
|
||||
public void ActivateWallBuildMode()
|
||||
{
|
||||
if (!frameworkSdk.GregFeatureGuard.IsEnabled("WallRack")) return;
|
||||
wallBuildModeActive = true;
|
||||
_log.Msg("Wall Build Mode activated.");
|
||||
}
|
||||
|
||||
public void DeactivateWallBuildMode()
|
||||
{
|
||||
wallBuildModeActive = false;
|
||||
targetGrid = null;
|
||||
hoveredSlot = null;
|
||||
_log.Msg("Wall Build Mode deactivated.");
|
||||
}
|
||||
|
||||
public void OnUpdate()
|
||||
{
|
||||
if (!wallBuildModeActive) return;
|
||||
|
||||
// Simple raycast against walls in a real scenario
|
||||
// For now, pseudo-code behavior
|
||||
targetGrid = null;
|
||||
hoveredSlot = null;
|
||||
|
||||
// Vector3 hitPos = ...
|
||||
// targetGrid = GregWallRegistry.Instance.GetGridAtWorldPos(hitPos, 2.0f);
|
||||
// if (targetGrid != null) {
|
||||
// hoveredSlot = targetGrid.GetSlotAtWorldPos(hitPos);
|
||||
// }
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
if (!wallBuildModeActive && !showGridOverlay) return;
|
||||
|
||||
foreach (var grid in GregWallRegistry.Instance.GetAllGrids())
|
||||
{
|
||||
if (showGridOverlay)
|
||||
{
|
||||
grid.DrawDebugGrid();
|
||||
}
|
||||
|
||||
// If wallBuildModeActive, draw slot highlights
|
||||
if (wallBuildModeActive && grid == targetGrid && hoveredSlot != null)
|
||||
{
|
||||
// Draw highlight
|
||||
// Vector3 wPos = grid.SlotToWorldPos(hoveredSlot.coord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TryMount(Vector3 worldPos)
|
||||
{
|
||||
if (previewDevice == null) return;
|
||||
var grid = GregWallRegistry.Instance.GetGridAtWorldPos(worldPos, 2.0f);
|
||||
if (grid == null) return;
|
||||
|
||||
var slot = grid.GetSlotAtWorldPos(worldPos);
|
||||
if (slot == null || slot.isOccupied) return;
|
||||
|
||||
if (grid.MountDevice(slot.coord, previewDevice))
|
||||
{
|
||||
GregWallUndoRedoService.Instance.PushAction(
|
||||
new MountAction(grid.wallId, slot.coord, previewDevice)
|
||||
);
|
||||
_log.Msg($"Mounted device {previewDevice.deviceId} at {slot.coord}");
|
||||
}
|
||||
}
|
||||
|
||||
public void TryUnmount(Vector3 worldPos)
|
||||
{
|
||||
var grid = GregWallRegistry.Instance.GetGridAtWorldPos(worldPos, 2.0f);
|
||||
if (grid == null) return;
|
||||
|
||||
var slot = grid.GetSlotAtWorldPos(worldPos);
|
||||
if (slot == null || !slot.isOccupied) return;
|
||||
|
||||
var dev = slot.mountedDevice;
|
||||
if (dev != null && grid.UnmountDevice(slot.coord))
|
||||
{
|
||||
GregWallUndoRedoService.Instance.PushAction(
|
||||
new UnmountAction(grid.wallId, slot.coord, dev)
|
||||
);
|
||||
_log.Msg($"Unmounted device from {slot.coord}");
|
||||
}
|
||||
}
|
||||
|
||||
public void TrySwap(Vector3 worldPos)
|
||||
{
|
||||
var grid = GregWallRegistry.Instance.GetGridAtWorldPos(worldPos, 2.0f);
|
||||
if (grid == null) return;
|
||||
|
||||
var slot = grid.GetSlotAtWorldPos(worldPos);
|
||||
if (slot == null || !slot.isOccupied) return;
|
||||
|
||||
var oldDev = slot.mountedDevice;
|
||||
var newDev = previewDevice; // From inventory
|
||||
|
||||
if (oldDev != null && newDev != null && grid.SwapDevice(slot.coord, newDev))
|
||||
{
|
||||
GregWallUndoRedoService.Instance.PushAction(
|
||||
new SwapAction(grid.wallId, slot.coord, oldDev, newDev)
|
||||
);
|
||||
_log.Msg($"Swapped device at {slot.coord}");
|
||||
|
||||
gregCore.Core.Events.GregEventDispatcher.Emit(gregCore.GameLayer.Hooks.GregNativeEventHooks.WorldWallDeviceSwapped, slot.coord);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnInteract(Vector3 worldPos)
|
||||
{
|
||||
if (!frameworkSdk.GregFeatureGuard.IsEnabled("WallRack")) return;
|
||||
|
||||
var grid = GregWallRegistry.Instance.GetGridAtWorldPos(worldPos, 2.0f);
|
||||
if (grid == null) return;
|
||||
|
||||
var slot = grid.GetSlotAtWorldPos(worldPos);
|
||||
if (slot == null || !slot.isOccupied) return;
|
||||
|
||||
// Open context menu (OnGUI driven)
|
||||
_log.Msg("Opened interaction context menu for device.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public class GregWallRegistry
|
||||
{
|
||||
public static GregWallRegistry Instance { get; } = new();
|
||||
|
||||
private readonly Dictionary<string, GregWallGrid> _walls = new();
|
||||
|
||||
public void RegisterWall(string wallId, GregWallGrid grid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(wallId)) return;
|
||||
_walls[wallId] = grid;
|
||||
}
|
||||
|
||||
public void UnregisterWall(string wallId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(wallId)) return;
|
||||
_walls.Remove(wallId);
|
||||
}
|
||||
|
||||
public GregWallGrid? GetGrid(string wallId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(wallId)) return null;
|
||||
_walls.TryGetValue(wallId, out var grid);
|
||||
return grid;
|
||||
}
|
||||
|
||||
public GregWallGrid? GetGridAtWorldPos(Vector3 worldPos, float tolerance)
|
||||
{
|
||||
foreach (var grid in _walls.Values)
|
||||
{
|
||||
if (Vector3.Distance(grid.wallOrigin, worldPos) < tolerance)
|
||||
{
|
||||
return grid;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<GregWallGrid> GetAllGrids() => _walls.Values;
|
||||
|
||||
public GregWallSlot? FindNearestFreeSlot(Vector3 worldPos, GregWallSlotType type)
|
||||
{
|
||||
GregWallSlot? nearestSlot = null;
|
||||
float nearestDist = float.MaxValue;
|
||||
|
||||
foreach (var grid in _walls.Values)
|
||||
{
|
||||
foreach (var slot in grid.slots.Values)
|
||||
{
|
||||
if (slot.isOccupied || slot.isBlocked) continue;
|
||||
if ((slot.allowedTypes & type) == 0) continue;
|
||||
|
||||
Vector3 pos = grid.SlotToWorldPos(slot.coord);
|
||||
float d = Vector3.Distance(pos, worldPos);
|
||||
if (d < nearestDist)
|
||||
{
|
||||
nearestDist = d;
|
||||
nearestSlot = slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nearestSlot;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
[Flags]
|
||||
public enum GregWallSlotType
|
||||
{
|
||||
None = 0,
|
||||
Rack = 1 << 0,
|
||||
Switch = 1 << 1,
|
||||
Router = 1 << 2,
|
||||
Patch = 1 << 3,
|
||||
Generic = 1 << 4,
|
||||
Any = ~0
|
||||
}
|
||||
|
||||
public class GregWallSlot
|
||||
{
|
||||
public UnityEngine.Vector2Int coord;
|
||||
public bool isOccupied;
|
||||
public GregWallDevice? mountedDevice;
|
||||
public GregWallSlotType allowedTypes = GregWallSlotType.Any;
|
||||
public bool isBlocked = false;
|
||||
|
||||
public GregWallSlot(UnityEngine.Vector2Int c)
|
||||
{
|
||||
coord = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public static class GregWallSlotTypeRegistry
|
||||
{
|
||||
private static readonly Dictionary<string, int> _customTypes = new();
|
||||
|
||||
public static void RegisterType(string typeId, int flagValue)
|
||||
{
|
||||
if (string.IsNullOrEmpty(typeId)) return;
|
||||
_customTypes[typeId] = flagValue;
|
||||
}
|
||||
|
||||
public static int GetFlag(string typeId)
|
||||
{
|
||||
if (_customTypes.TryGetValue(typeId, out int flag))
|
||||
{
|
||||
return flag;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public abstract record GregWallAction(string WallId);
|
||||
|
||||
public record MountAction(string WallId, Vector2Int Coord, GregWallDevice Device) : GregWallAction(WallId);
|
||||
public record UnmountAction(string WallId, Vector2Int Coord, GregWallDevice Device) : GregWallAction(WallId);
|
||||
public record SwapAction(string WallId, Vector2Int Coord, GregWallDevice OldDevice, GregWallDevice NewDevice) : GregWallAction(WallId);
|
||||
public record BuyWallAction(string WallId, Vector3 WallPos, Vector3 WallNormal) : GregWallAction(WallId);
|
||||
|
||||
public class GregWallUndoRedoService
|
||||
{
|
||||
public static GregWallUndoRedoService Instance { get; } = new();
|
||||
|
||||
private readonly Stack<GregWallAction> _undoStack = new(50);
|
||||
private readonly Stack<GregWallAction> _redoStack = new();
|
||||
|
||||
public int UndoCount => _undoStack.Count;
|
||||
|
||||
public void PushAction(GregWallAction action)
|
||||
{
|
||||
if (_undoStack.Count >= 50)
|
||||
{
|
||||
// Simple stack management
|
||||
}
|
||||
_undoStack.Push(action);
|
||||
_redoStack.Clear();
|
||||
}
|
||||
|
||||
public void Undo()
|
||||
{
|
||||
if (_undoStack.Count == 0) return;
|
||||
var action = _undoStack.Pop();
|
||||
_redoStack.Push(action);
|
||||
|
||||
var registry = GregWallRegistry.Instance;
|
||||
var grid = registry.GetGrid(action.WallId);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case MountAction m:
|
||||
grid?.UnmountDevice(m.Coord);
|
||||
break;
|
||||
case UnmountAction u:
|
||||
grid?.MountDevice(u.Coord, u.Device);
|
||||
break;
|
||||
case SwapAction s:
|
||||
grid?.SwapDevice(s.Coord, s.OldDevice);
|
||||
break;
|
||||
case BuyWallAction b:
|
||||
registry.UnregisterWall(b.WallId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Redo()
|
||||
{
|
||||
if (_redoStack.Count == 0) return;
|
||||
var action = _redoStack.Pop();
|
||||
_undoStack.Push(action);
|
||||
|
||||
var registry = GregWallRegistry.Instance;
|
||||
var grid = registry.GetGrid(action.WallId);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case MountAction m:
|
||||
grid?.MountDevice(m.Coord, m.Device);
|
||||
break;
|
||||
case UnmountAction u:
|
||||
grid?.UnmountDevice(u.Coord);
|
||||
break;
|
||||
case SwapAction s:
|
||||
grid?.SwapDevice(s.Coord, s.NewDevice);
|
||||
break;
|
||||
case BuyWallAction b:
|
||||
var newGrid = new GregWallGrid();
|
||||
newGrid.Initialize(b.WallId, b.WallPos, b.WallNormal, Vector3.up, 4, 3);
|
||||
registry.RegisterWall(b.WallId, newGrid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_undoStack.Clear();
|
||||
_redoStack.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using MelonLoader;
|
||||
using greg.Logging;
|
||||
|
||||
namespace greg.WallRack
|
||||
{
|
||||
public class Main : MelonMod
|
||||
{
|
||||
private GregModLogger _log = null!;
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
// Framework guard first
|
||||
if (gregCore.Core.GregCoreMod.Instance == null)
|
||||
{
|
||||
LoggerInstance.Warning("[gC-OnInitializeMelon] gregCore not ready.");
|
||||
return;
|
||||
}
|
||||
|
||||
_log = new GregModLogger("WallRack");
|
||||
|
||||
_log.Section("Init");
|
||||
_log.Msg("Starting initialization.");
|
||||
|
||||
_log.PatchApplied("CustomerDevice.Initialize");
|
||||
_log.HookSubscribed("greg.SYSTEM.ButtonBuyWall");
|
||||
_log.FeatureState("WallRack", true);
|
||||
|
||||
_log.Msg("Initialization complete.");
|
||||
}
|
||||
|
||||
public override void OnApplicationQuit()
|
||||
{
|
||||
_log?.Section("Shutdown");
|
||||
_log?.Msg("Unloading.");
|
||||
_log?.Msg("Hooks deregistered. Goodbye.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
<RepoRoot>$(MSBuildProjectDirectory)\..</RepoRoot>
|
||||
<AssemblyName>gregCore</AssemblyName>
|
||||
<RootNamespace>gregCore</RootNamespace>
|
||||
<Version>1.0.0.33-pre</Version>
|
||||
<Authors>TeamGreg</Authors>
|
||||
<Description>gregCore Modding Framework für Data Center</Description>
|
||||
|
||||
<OutputPath Condition="'$(MELON_MODS_DIR)' != ''">$(MELON_MODS_DIR)</OutputPath>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
||||
<TreatWarningsAsErrors Condition="'$(CI)' == 'true'">true</TreatWarningsAsErrors>
|
||||
<NoWarn>CS1591;CS0436</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Common References with CI Fallback -->
|
||||
<Reference Include="MelonLoader">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\net6\MelonLoader.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\MelonLoader.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppInterop.Runtime">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\net6\Il2CppInterop.Runtime.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\Il2CppInterop.Runtime.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppInterop.Common">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\net6\Il2CppInterop.Common.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\Il2CppInterop.Common.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\net6\0Harmony.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\0Harmony.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\Il2CppAssemblies\Assembly-CSharp.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\Assembly-CSharp.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2Cppmscorlib">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\Il2CppAssemblies\Il2Cppmscorlib.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\Il2Cppmscorlib.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\Il2CppAssemblies\UnityEngine.CoreModule.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\UnityEngine.CoreModule.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.IMGUIModule">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\Il2CppAssemblies\UnityEngine.IMGUIModule.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\UnityEngine.IMGUIModule.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UIModule">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\Il2CppAssemblies\UnityEngine.UIModule.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\UnityEngine.UIModule.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.InputLegacyModule">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\Il2CppAssemblies\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Unity.InputSystem">
|
||||
<HintPath Condition="'$(CI)' != 'true'">$(MELON_BASE_DIR)\Il2CppAssemblies\Unity.InputSystem.dll</HintPath>
|
||||
<HintPath Condition="'$(CI)' == 'true'">$(RepoRoot)\ci-stubs\Unity.InputSystem.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.44.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Jint" Version="4.8.0" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.21" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
|
||||
<PackageReference Include="MoonSharp" Version="2.0.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="pythonnet" Version="3.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="ILRepack" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<InputAssemblies Include="$(OutputPath)\$(AssemblyName).dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\MoonSharp.Interpreter.dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\Newtonsoft.Json.dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\Mono.Cecil.dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\Jint.dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\Acornima.dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\System.Runtime.CompilerServices.Unsafe.dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\Python.Runtime.dll" />
|
||||
<InputAssemblies Include="$(OutputPath)\LiteDB.dll" />
|
||||
</ItemGroup>
|
||||
<ILRepack Parallel="true" Internalize="true" InputAssemblies="@(InputAssemblies)" OutputFile="$(OutputPath)\$(AssemblyName).dll" TargetKind="Dll" LibraryPath="$(OutputPath)" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
class Program {
|
||||
static void Main() {
|
||||
try {
|
||||
Assembly asm = Assembly.LoadFrom(@"C:/Program Files (x86)/Steam/steamapps/common/Data Center/MelonLoader/Il2CppAssemblies/Assembly-CSharp.dll");
|
||||
foreach (Type t in asm.GetTypes()) {
|
||||
string name = t.Name.ToLower();
|
||||
if (name.Contains("rack") || name.Contains("save") || name.Contains("grid") || name.Contains("floor") || name.Contains("place")) {
|
||||
Console.WriteLine(t.FullName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user