@@ -1,28 +1,77 @@ | |||
using System.IO; | |||
using System; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Reflection; | |||
using IllusionPlugin; | |||
using CLre.API.Utility; | |||
using Logging = CLre.API.Utility.Logging; | |||
using System.Text; | |||
using HarmonyLib; | |||
using Svelto.ECS; | |||
using UnityEngine; | |||
namespace CLre | |||
{ | |||
public class CLre : IEnhancedPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin' | |||
public class CLre : IllusionPlugin.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 Version { get; } = Assembly.GetExecutingAssembly().GetName().Version.ToString(); | |||
private Harmony harmonyInstance = null; | |||
// called when Cardlife shuts down | |||
public override void OnApplicationQuit() | |||
{ | |||
harmonyInstance.UnpatchAll(); | |||
} | |||
// called when Cardlife starts up | |||
public override void OnApplicationStart() | |||
{ | |||
Logging.MetaLog($"{Name} has been loaded."); | |||
#if DEBUG | |||
FileLog.Reset(); | |||
Harmony.DEBUG = true; | |||
Stopwatch startup = Stopwatch.StartNew(); | |||
#endif | |||
// init all Harmony patches in project | |||
harmonyInstance = new Harmony(Name); | |||
harmonyInstance.PatchAll(); | |||
// patches for bugs | |||
Fixes.InitLogSooner.Init(); | |||
// misc | |||
LogIPAPlugins(); | |||
// Log info | |||
API.Utility.Logging.MetaLog($"{Name} init complete."); | |||
#if DEBUG | |||
API.App.Client.InitComplete += (_, __) => | |||
{ | |||
startup.Stop(); | |||
API.Utility.Logging.MetaLog($"Startup took {startup.ElapsedMilliseconds}ms"); | |||
API.Utility.Logging.Log( | |||
$"EAC has detected code mods? {EasyAntiCheat.Client.Hydra.Runtime.Integrity.Violated}" + | |||
(EasyAntiCheat.Client.Hydra.Runtime.Integrity.Violated | |||
? EasyAntiCheat.Client.Hydra.Runtime.Integrity.ViolationMessage | |||
: "")); | |||
}; | |||
#endif | |||
} | |||
private static void LogIPAPlugins() | |||
{ | |||
StringBuilder sb = new StringBuilder(); | |||
sb.AppendFormat("Running on Unity {0}\n", Application.unityVersion); | |||
sb.AppendFormat("Running on CardLife {0} (aka {1})\n", API.App.Client.Version, Application.version); | |||
sb.AppendFormat("-----------------------------\n"); | |||
sb.AppendFormat("Loading plugins from {0} and found {1}\n", System.IO.Path.Combine(Environment.CurrentDirectory, "Plugins"), IllusionInjector.PluginManager.Plugins.Count()); | |||
sb.AppendFormat("-----------------------------\n"); | |||
foreach (IllusionPlugin.IPlugin plugin in IllusionInjector.PluginManager.Plugins) | |||
{ | |||
sb.AppendFormat(" {0}: {1}\n", plugin.Name, plugin.Version); | |||
} | |||
sb.AppendFormat("-----------------------------\n"); | |||
API.Utility.Logging.Log(sb.ToString()); | |||
} | |||
} | |||
} |
@@ -4,7 +4,7 @@ | |||
<TargetFramework>net472</TargetFramework> | |||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | |||
<Version>0.0.1</Version> | |||
<Authors>Me</Authors> | |||
<Authors>NGnius</Authors> | |||
<PackageLicenseExpression>MIT</PackageLicenseExpression> | |||
<PackageProjectUrl>https://git.exmods.org/NGnius/CLre</PackageProjectUrl> | |||
<NeutralLanguage>en-CA</NeutralLanguage> | |||
@@ -1,7 +1,32 @@ | |||
using System; | |||
using System.Globalization; | |||
using System.Reflection; | |||
using HarmonyLib; | |||
namespace CLre.Fixes | |||
{ | |||
public class EnchantmentTableFloatParseFix | |||
{ | |||
} | |||
[HarmonyPatch] | |||
class Float_TryParse_Patch | |||
{ | |||
[HarmonyPostfix] | |||
public static void BeforeMethodCall(string s, ref float result, ref bool __result) | |||
{ | |||
if (__result) return; | |||
__result = float.TryParse(s, | |||
NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | | |||
NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands | NumberStyles.AllowExponent, | |||
NumberFormatInfo.InvariantInfo, out result); | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||
return AccessTools.Method(typeof(float), "TryParse", new []{typeof(string), typeof(float).MakeByRefType()}); | |||
} | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
using System; | |||
using System.Diagnostics; | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using System.Threading; | |||
using HarmonyLib; | |||
namespace CLre.Fixes | |||
{ | |||
public static class InitLogSooner | |||
{ | |||
public static int millisecondsTimeout = 5000; | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public static void Init() | |||
{ | |||
try | |||
{ | |||
CustomLoggerThread_CreateGameObject_Patch.allowed = true; | |||
CustomLoggerThread.CreateGameObject(); | |||
CustomLoggerThread_CreateGameObject_Patch.allowed = false; | |||
API.Utility.Logging.Log($"Completed early log init"); | |||
//System.IO.File.WriteAllText("InitLogSooner.log", $"Done at " + System.DateTime.Now.ToString()); | |||
} | |||
catch (Exception e) | |||
{ | |||
API.App.Client.LogInitComplete += (_, __) => | |||
{ | |||
API.Utility.Logging.Log($"Failed to initialise log sooner, reason:\n" + e); | |||
}; | |||
System.IO.File.WriteAllText("InitLogSooner.log", e.ToString()); | |||
} | |||
} | |||
[HarmonyPatch(typeof(CustomLoggerThread), "CreateGameObject")] | |||
class CustomLoggerThread_CreateGameObject_Patch | |||
{ | |||
internal static bool allowed = false; | |||
public static bool Prefix() | |||
{ | |||
return allowed; | |||
} | |||
} | |||
[HarmonyPatch(typeof(CustomLoggerThread), "StartQueue")] | |||
class CustomLoggerThread_StartQueue_Patch | |||
{ | |||
internal static volatile bool IsLogStarted = false; | |||
private delegate void Flusher(); | |||
public static bool Prefix() | |||
{ | |||
// setup thru reflection | |||
FieldInfo quitThreadField = AccessTools.Field(typeof(CustomLoggerThread), "_quitThread"); | |||
MethodInfo flushLoggerMethod = AccessTools.Method(typeof(CustomLoggerThread), "FlushLogger"); | |||
Flusher flushLogger = (Flusher) Delegate.CreateDelegate(typeof(Action), null, flushLoggerMethod); | |||
MethodInfo forceFlushMethod = AccessTools.Method("CustomLogger:ForceFlush"); | |||
Flusher forceFlush = (Flusher) Delegate.CreateDelegate(typeof(Action), null, forceFlushMethod); | |||
Thread.MemoryBarrier(); | |||
IsLogStarted = true; | |||
while (!(bool) quitThreadField.GetValue(null)) | |||
{ | |||
flushLogger(); | |||
forceFlush(); | |||
Thread.Sleep(millisecondsTimeout); | |||
} | |||
IsLogStarted = false; | |||
return false; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Reflection; | |||
using HarmonyLib; | |||
namespace CLre.Fixes | |||
{ | |||
public class StartupSpeedup | |||
{ | |||
} | |||
[HarmonyPatch(typeof(FrontEnd.FrontEndContextRoot), "WaitForFrameworkInitialization")] | |||
//[HarmonyPatch] | |||
class Speedup_Benchmark3 | |||
{ | |||
internal static Stopwatch test = null; | |||
public static void Prefix() | |||
{ | |||
test = Stopwatch.StartNew(); | |||
} | |||
} | |||
[HarmonyPatch(typeof(FrontEnd.MainFrontEnd), "RequestPlayerId")] | |||
//[HarmonyPatch] | |||
class Speedup_Benchmark | |||
{ | |||
internal static Stopwatch test = null; | |||
public static void Prefix() | |||
{ | |||
test.Stop(); | |||
long elapsed = test.ElapsedMilliseconds; | |||
API.Utility.Logging.Log($"OnContextInitialized completed in ~{elapsed}ms"); | |||
} | |||
} | |||
[HarmonyPatch(typeof(FrontEnd.MainFrontEnd), "RegisterCustomHtmlElementTypes")] | |||
class Speedup_Benchmark2 | |||
{ | |||
public static void Prefix() | |||
{ | |||
if (Speedup_Benchmark3.test != null) | |||
{ | |||
Speedup_Benchmark3.test.Stop(); | |||
long elapsed = Speedup_Benchmark3.test.ElapsedMilliseconds; | |||
API.App.Client.LogInitComplete += (_, __) => | |||
{ | |||
API.Utility.Logging.Log($"Scene loaded in ~{elapsed}ms"); | |||
}; | |||
} | |||
Speedup_Benchmark.test = Stopwatch.StartNew(); | |||
} | |||
} | |||
} |