Create minimal API endpoints from explored/understood code
This commit is contained in:
parent
0f5555ab4c
commit
05e196b4c1
7 changed files with 414 additions and 3 deletions
88
CLre/API/App/Client.cs
Normal file
88
CLre/API/App/Client.cs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace CLre.API.App
|
||||||
|
{
|
||||||
|
public static class Client
|
||||||
|
{
|
||||||
|
public static event EventHandler<SetupEventArgs> InitStart
|
||||||
|
{
|
||||||
|
add => FrontEnd_SetupContainer_Patch.preSetup += value;
|
||||||
|
remove => FrontEnd_SetupContainer_Patch.preSetup -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static event EventHandler<SetupEventArgs> LogInitComplete
|
||||||
|
{
|
||||||
|
add => FrontEnd_SetupContainer_Patch.postSyncSetup += value;
|
||||||
|
remove => FrontEnd_SetupContainer_Patch.postSyncSetup -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static event EventHandler<SetupEventArgs> AsynchronousInitComplete
|
||||||
|
{
|
||||||
|
add => FrontEndGuiEngine_SetMainMenuEnabled_Patch.preMenuEnabled += value;
|
||||||
|
remove => FrontEndGuiEngine_SetMainMenuEnabled_Patch.preMenuEnabled -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static event EventHandler<SetupEventArgs> InitComplete
|
||||||
|
{
|
||||||
|
add => FrontEndGuiEngine_SetMainMenuEnabled_Patch.postMenuEnabled += value;
|
||||||
|
remove => FrontEndGuiEngine_SetMainMenuEnabled_Patch.postMenuEnabled -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Version
|
||||||
|
{
|
||||||
|
get => Game.Utilities.VersionReader.GetVersion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct SetupEventArgs {}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(FrontEnd.MainFrontEnd), "SetupContainer")]
|
||||||
|
class FrontEnd_SetupContainer_Patch
|
||||||
|
{
|
||||||
|
internal static event EventHandler<SetupEventArgs> postSyncSetup;
|
||||||
|
|
||||||
|
internal static event EventHandler<SetupEventArgs> preSetup;
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void BeforeMethodCall(FrontEnd.MainFrontEnd __instance)
|
||||||
|
{
|
||||||
|
if (preSetup != null) preSetup(__instance, new SetupEventArgs { });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void AfterMethodCall(FrontEnd.MainFrontEnd __instance)
|
||||||
|
{
|
||||||
|
if (postSyncSetup != null) postSyncSetup(__instance, new SetupEventArgs { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch]
|
||||||
|
class FrontEndGuiEngine_SetMainMenuEnabled_Patch
|
||||||
|
{
|
||||||
|
internal static event EventHandler<SetupEventArgs> preMenuEnabled;
|
||||||
|
|
||||||
|
internal static event EventHandler<SetupEventArgs> postMenuEnabled;
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void BeforeMethodCall(object __instance, bool enabled)
|
||||||
|
{
|
||||||
|
if (!enabled) return;
|
||||||
|
if (preMenuEnabled != null) preMenuEnabled(__instance, new SetupEventArgs { });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void AfterMethodCall(object __instance, bool enabled)
|
||||||
|
{
|
||||||
|
if (!enabled) return;
|
||||||
|
if (postMenuEnabled != null) postMenuEnabled(__instance, new SetupEventArgs { });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyTargetMethod]
|
||||||
|
public static MethodBase ReflectToGetMethodBase()
|
||||||
|
{
|
||||||
|
return AccessTools.Method("FrontEnd.FrontEndGuiEngine:SetMainMenuEnabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
144
CLre/API/Engines/FrontEndEngines.cs
Normal file
144
CLre/API/Engines/FrontEndEngines.cs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
using HarmonyLib;
|
||||||
|
using Svelto.DataStructures;
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
namespace CLre.API.Engines
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Engine to be registered before vanilla engines are built.
|
||||||
|
/// This should be called by any other constructor because this alerts CLre of its existence.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class FrontEndEnginePreBuild : ICLreEngine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a new instance of a FrontEndEngine.
|
||||||
|
/// This should be called by any other constructor because this alerts CLre of its existence.
|
||||||
|
/// </summary>
|
||||||
|
public FrontEndEnginePreBuild()
|
||||||
|
{
|
||||||
|
MainFrontEnd_BuildEngines_Patch.beforeBuildEngines.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Ready();
|
||||||
|
public abstract IEntitiesDB entitiesDB { get; set; }
|
||||||
|
public abstract IEntityFactory entityFactory { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Engine to be registered before obsolete vanilla engines are built.
|
||||||
|
/// This should be called by any other constructor because this alerts CLre of its existence.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class FrontEndObsoleteEnginePreBuild : ICLreEngine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a new instance of a FrontEndEngine.
|
||||||
|
/// This should be called by any other constructor because this alerts CLre of its existence.
|
||||||
|
/// </summary>
|
||||||
|
public FrontEndObsoleteEnginePreBuild()
|
||||||
|
{
|
||||||
|
MainFrontEnd_BuildObsoleteEngines_Patch.beforeBuildEngines.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Ready();
|
||||||
|
public abstract IEntitiesDB entitiesDB { get; set; }
|
||||||
|
public abstract IEntityFactory entityFactory { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Engine to be registered after vanilla engines are built.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class FrontEndEnginePostBuild : ICLreEngine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a new instance of a FrontEndEngine.
|
||||||
|
/// This should be called by any other constructor because this alerts CLre of its existence.
|
||||||
|
/// </summary>
|
||||||
|
public FrontEndEnginePostBuild()
|
||||||
|
{
|
||||||
|
MainFrontEnd_BuildEngines_Patch.afterBuildEngines.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Ready();
|
||||||
|
public abstract IEntitiesDB entitiesDB { get; set; }
|
||||||
|
public abstract IEntityFactory entityFactory { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Engine to be registered after vanilla obsolete engines are built.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class FrontEndObsoleteEnginePostBuild : ICLreEngine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a new instance of a FrontEndEngine.
|
||||||
|
/// This should be called by any other constructor because this alerts CLre of its existence.
|
||||||
|
/// </summary>
|
||||||
|
public FrontEndObsoleteEnginePostBuild()
|
||||||
|
{
|
||||||
|
MainFrontEnd_BuildObsoleteEngines_Patch.afterBuildEngines.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Ready();
|
||||||
|
public abstract IEntitiesDB entitiesDB { get; set; }
|
||||||
|
public abstract IEntityFactory entityFactory { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(FrontEnd.MainFrontEnd), "BuildEngines")]
|
||||||
|
class MainFrontEnd_BuildEngines_Patch
|
||||||
|
{
|
||||||
|
internal static FasterList<FrontEndEnginePreBuild> beforeBuildEngines = new FasterList<FrontEndEnginePreBuild>();
|
||||||
|
|
||||||
|
internal static FasterList<FrontEndEnginePostBuild> afterBuildEngines = new FasterList<FrontEndEnginePostBuild>();
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void BeforeMethodCall(FrontEnd.MainFrontEnd __instance)
|
||||||
|
{
|
||||||
|
IEntityFactory factory = AccessTools.Field(typeof(FrontEnd.MainFrontEnd), "_entityFactory").GetValue(__instance) as IEntityFactory;
|
||||||
|
foreach (ICLreEngine e in beforeBuildEngines)
|
||||||
|
{
|
||||||
|
e.entityFactory = factory;
|
||||||
|
__instance.AddEngine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void AfterMethodCall(FrontEnd.MainFrontEnd __instance)
|
||||||
|
{
|
||||||
|
IEntityFactory factory = AccessTools.Field(typeof(FrontEnd.MainFrontEnd), "_entityFactory").GetValue(__instance) as IEntityFactory;
|
||||||
|
foreach (ICLreEngine e in afterBuildEngines)
|
||||||
|
{
|
||||||
|
e.entityFactory = factory;
|
||||||
|
__instance.AddEngine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(FrontEnd.MainFrontEnd), "BuildObsoleteEngines")]
|
||||||
|
class MainFrontEnd_BuildObsoleteEngines_Patch
|
||||||
|
{
|
||||||
|
internal static FasterList<FrontEndObsoleteEnginePreBuild> beforeBuildEngines = new FasterList<FrontEndObsoleteEnginePreBuild>();
|
||||||
|
|
||||||
|
internal static FasterList<FrontEndObsoleteEnginePostBuild> afterBuildEngines = new FasterList<FrontEndObsoleteEnginePostBuild>();
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void BeforeMethodCall(FrontEnd.MainFrontEnd __instance)
|
||||||
|
{
|
||||||
|
IEntityFactory factory = AccessTools.Field(typeof(FrontEnd.MainFrontEnd), "_entityFactory").GetValue(__instance) as IEntityFactory;
|
||||||
|
foreach (ICLreEngine e in beforeBuildEngines)
|
||||||
|
{
|
||||||
|
e.entityFactory = factory;
|
||||||
|
__instance.AddEngine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void AfterMethodCall(FrontEnd.MainFrontEnd __instance)
|
||||||
|
{
|
||||||
|
IEntityFactory factory = AccessTools.Field(typeof(FrontEnd.MainFrontEnd), "_entityFactory").GetValue(__instance) as IEntityFactory;
|
||||||
|
foreach (ICLreEngine e in afterBuildEngines)
|
||||||
|
{
|
||||||
|
e.entityFactory = factory;
|
||||||
|
__instance.AddEngine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
CLre/API/Engines/GameEngines.cs
Normal file
60
CLre/API/Engines/GameEngines.cs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
using HarmonyLib;
|
||||||
|
using Svelto.DataStructures;
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
namespace CLre.API.Engines
|
||||||
|
{
|
||||||
|
public abstract class GameObsoleteEnginePreBuild : ICLreEngine
|
||||||
|
{
|
||||||
|
public GameObsoleteEnginePreBuild()
|
||||||
|
{
|
||||||
|
MainLevel_BuildDeprecatedEngines_Patch.beforeBuildEngines.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Ready();
|
||||||
|
public abstract IEntitiesDB entitiesDB { get; set; }
|
||||||
|
public abstract IEntityFactory entityFactory { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class GameObsoleteEnginePostBuild : ICLreEngine
|
||||||
|
{
|
||||||
|
public GameObsoleteEnginePostBuild()
|
||||||
|
{
|
||||||
|
MainLevel_BuildDeprecatedEngines_Patch.afterBuildEngines.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Ready();
|
||||||
|
public abstract IEntitiesDB entitiesDB { get; set; }
|
||||||
|
public abstract IEntityFactory entityFactory { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(GameFramework.MainLevel), "BuildDeprecatedEngines")]
|
||||||
|
class MainLevel_BuildDeprecatedEngines_Patch
|
||||||
|
{
|
||||||
|
internal static FasterList<GameObsoleteEnginePreBuild> beforeBuildEngines = new FasterList<GameObsoleteEnginePreBuild>();
|
||||||
|
|
||||||
|
internal static FasterList<GameObsoleteEnginePostBuild> afterBuildEngines = new FasterList<GameObsoleteEnginePostBuild>();
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void BeforeMethodCall(GameFramework.MainLevel __instance)
|
||||||
|
{
|
||||||
|
IEntityFactory factory = AccessTools.Field(typeof(GameFramework.MainLevel), "_entityFactory").GetValue(__instance) as IEntityFactory;
|
||||||
|
foreach (ICLreEngine e in beforeBuildEngines)
|
||||||
|
{
|
||||||
|
e.entityFactory = factory;
|
||||||
|
__instance.AddEngine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void AfterMethodCall(GameFramework.MainLevel __instance)
|
||||||
|
{
|
||||||
|
IEntityFactory factory = AccessTools.Field(typeof(GameFramework.MainLevel), "_entityFactory").GetValue(__instance) as IEntityFactory;
|
||||||
|
foreach (ICLreEngine e in afterBuildEngines)
|
||||||
|
{
|
||||||
|
e.entityFactory = factory;
|
||||||
|
__instance.AddEngine(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
CLre/API/Engines/ICLreEngine.cs
Normal file
9
CLre/API/Engines/ICLreEngine.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
namespace CLre.API.Engines
|
||||||
|
{
|
||||||
|
public interface ICLreEngine : IQueryingEntitiesEngine
|
||||||
|
{
|
||||||
|
IEntityFactory entityFactory { get; set; }
|
||||||
|
}
|
||||||
|
}
|
100
CLre/API/Utility/Logging.cs
Normal file
100
CLre/API/Utility/Logging.cs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CLre.API.Utility
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utility class to access Cardlife's built-in logging capabilities.
|
||||||
|
/// The log is saved to outputLog#.Log
|
||||||
|
/// </summary>
|
||||||
|
public static class Logging
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Log(string msg)
|
||||||
|
{
|
||||||
|
Svelto.Console.Log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write a regular message to Cardlife's log
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to log</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Log(object obj)
|
||||||
|
{
|
||||||
|
Svelto.Console.Log(obj.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void LogError(string msg, Dictionary<string, string> extraData = null)
|
||||||
|
{
|
||||||
|
Svelto.Console.LogError(msg, extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write an error message to Cardlife's log
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to log</param>
|
||||||
|
/// <param name="extraData">The extra data to pass to the ILogger</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void LogError(object obj, Dictionary<string, string> extraData = null)
|
||||||
|
{
|
||||||
|
Svelto.Console.LogError(obj.ToString(), extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write an exception to Cardlife's log and to the screen and exit game
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">The exception to log</param>
|
||||||
|
/// <param name="extraData">The extra data to pass to the ILogger.
|
||||||
|
/// This is automatically populated with "OuterException#" and "OuterStacktrace#" entries</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void LogException(Exception e, string msg = null, Dictionary<string, string> extraData = null)
|
||||||
|
{
|
||||||
|
Svelto.Console.LogException(msg, e, extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void LogWarning(string msg)
|
||||||
|
{
|
||||||
|
Svelto.Console.LogWarning(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write a warning message to Cardlife's log
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to log</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void LogWarning(object obj)
|
||||||
|
{
|
||||||
|
Svelto.Console.LogWarning(obj.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// descriptive logging
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write a descriptive message to Cardlife's log only when the API is a Debug build
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to log</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void MetaDebugLog(object obj)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
MetaLog($"[MetaDebug]{obj.ToString()}");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write a descriptive message to Cardlife's log including the calling method's name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to log</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void MetaLog(object obj)
|
||||||
|
{
|
||||||
|
var method = (new StackTrace()).GetFrame(1).GetMethod();
|
||||||
|
Log($"[{method.DeclaringType.FullName}.{method.Name}] {obj.ToString()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,9 +3,12 @@ using System.Reflection;
|
||||||
|
|
||||||
using IllusionPlugin;
|
using IllusionPlugin;
|
||||||
|
|
||||||
namespace HelloModdingWorld
|
using CLre.API.Utility;
|
||||||
|
using Logging = CLre.API.Utility.Logging;
|
||||||
|
|
||||||
|
namespace CLre
|
||||||
{
|
{
|
||||||
public class MyPlugin : IEnhancedPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin'
|
public class CLre : IEnhancedPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin'
|
||||||
{
|
{
|
||||||
public override string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name;
|
public override string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name;
|
||||||
|
|
||||||
|
@ -19,7 +22,7 @@ namespace HelloModdingWorld
|
||||||
// called when Cardlife starts up
|
// called when Cardlife starts up
|
||||||
public override void OnApplicationStart()
|
public override void OnApplicationStart()
|
||||||
{
|
{
|
||||||
File.WriteAllText(Name + ".log", "CLre was loaded and started up");
|
Logging.MetaLog($"{Name} has been loaded.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
7
CLre/Fixes/EnchantmentTableFloatParseFix.cs
Normal file
7
CLre/Fixes/EnchantmentTableFloatParseFix.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace CLre.Fixes
|
||||||
|
{
|
||||||
|
public class EnchantmentTableFloatParseFix
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue