Skip to content

Commit

Permalink
wip newtonsoft compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
CptMoore committed Dec 13, 2024
1 parent a6c4d78 commit ddb9380
Show file tree
Hide file tree
Showing 6 changed files with 654 additions and 8 deletions.
34 changes: 31 additions & 3 deletions ModTek/Features/Logging/LogLevelExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using HBS.Logging;

namespace ModTek.Features.Logging;
Expand All @@ -7,7 +8,7 @@ internal static class LogLevelExtension
{
internal static string LogToString(LogLevel level)
{
var eLogLevel = Convert(level);
var eLogLevel = ConvertHbsLogLevelToELogLevel(level);
return eLogLevel switch // fast switch with static string, in order of most occuring
{
ELogLevels.Trace => "TRACE",
Expand All @@ -23,10 +24,10 @@ internal static string LogToString(LogLevel level)

internal static bool IsLogLevelGreaterThan(LogLevel loggerLevel, LogLevel messageLevel)
{
return Convert(messageLevel) >= Convert(loggerLevel);
return ConvertHbsLogLevelToELogLevel(messageLevel) >= ConvertHbsLogLevelToELogLevel(loggerLevel);
}

private static ELogLevels Convert(LogLevel level)
private static ELogLevels ConvertHbsLogLevelToELogLevel(LogLevel level)
{
var intLevel = (int)level;
if (intLevel is >= (int)LogLevel.Debug and <= (int)LogLevel.Error)
Expand All @@ -36,6 +37,33 @@ private static ELogLevels Convert(LogLevel level)
return (ELogLevels)intLevel;
}

internal static TraceLevel GetLevelFilter(ILog log)
{
if (log is not Logger.LogImpl logImpl)
{
return TraceLevel.Verbose; // either off or verbose, better too much
}
var effectiveLevel = logImpl.EffectiveLevel;
var eLogLevel = ConvertHbsLogLevelToELogLevel(effectiveLevel);
return ConvertELogLevelToTraceLevel(eLogLevel);
}

private static TraceLevel ConvertELogLevelToTraceLevel(ELogLevels level)
{
level = (ELogLevels)((int)level / 10 * 10);
return level switch
{
ELogLevels.OFF => TraceLevel.Off,
ELogLevels.Fatal => TraceLevel.Error,
ELogLevels.Error => TraceLevel.Error,
ELogLevels.Warning => TraceLevel.Warning,
ELogLevels.Log => TraceLevel.Info,
ELogLevels.Debug => TraceLevel.Verbose,
ELogLevels.Trace => TraceLevel.Verbose,
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
}

// log levels
private enum ELogLevels
{
Expand Down
5 changes: 4 additions & 1 deletion ModTek/Features/Logging/LoggingSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ internal class LoggingSettings
[JsonProperty]
internal const string MainLog_Description = "The main log.";
[JsonProperty(Required = Required.Always)]
internal AppenderSettings MainLog = new();
internal AppenderSettings MainLog = new()
{
Excludes = [ new FilterSettings { LoggerNames = ["HarmonyX" ] } ]
};
[JsonProperty(Required = Required.Always)]
internal string MainLogFilePath = "battletech_log.txt";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using BattleTech;
using fastJSON;
using HBS.Util;
using ModTek.Features.Logging;
using ModTek.Misc;
using ModTek.Util;

namespace ModTek.Features.Profiler.Patches;

[HarmonyPatch(typeof(MechDef), nameof(MechDef.RefreshChassis))]
internal static class MechDef_RefreshChassis_Patch
{
internal static void Prefix(ref bool __runOriginal, MechDef __instance)
{
if (__instance.dataManager == null && __instance.Description == null)
{
__runOriginal = false;
}
}
}

[HarmonyPatch(typeof(MechDef), nameof(MechDef.Chassis), MethodType.Setter)]
internal static class MechDef_set_Chassis_Patch
{
[HarmonyPriority(Priority.Last)]
internal static void Prefix(MechDef __instance, ChassisDef value)
{
Log.Main.Trace?.Log($"MechDef.Chassis={value?.GetHashCode()}", new Exception());
}
}

[HarmonyPatch]
internal static class JSONSerializationUtility_FromJSON_Patch
{
private static string basePath;
private static bool testNewton = true;

public static bool Prepare()
{
if (testNewton)
{
basePath = Path.Combine(FilePaths.MergeCacheDirectory, "newton");
if (Directory.Exists(basePath))
{
Directory.Delete(basePath, true);
}
Directory.CreateDirectory(basePath);
}
return ModTek.Enabled; // && ModTek.Config.ProfilerEnabled;
}

[HarmonyTargetMethods]
internal static IEnumerable<MethodBase> TargetMethods()
{
var genericMethod = typeof(JSONSerializationUtility)
.GetMethods(BindingFlags.Public|BindingFlags.Static)
.Single(x => x.Name== nameof(JSONSerializationUtility.FromJSON) && x.GetParameters().Length == 2);
Log.Main.Trace?.Log("JSONSerializationUtility.FromJSON " + genericMethod);

foreach (
var jsonTemplated in
typeof(JSONSerializationUtility)
.Assembly
.GetTypes()
.Where(x => !x.IsAbstract && typeof(IJsonTemplated).IsAssignableFrom(x))
) {
Log.Main.Trace?.Log("IJsonTemplated " + jsonTemplated);

MethodBase GetMethod(BindingFlags bindingAttr = BindingFlags.Default)
{
return jsonTemplated
.GetMethods(BindingFlags.Public | BindingFlags.Instance | bindingAttr)
.SingleOrDefault(x => x.Name == nameof(IJsonTemplated.FromJSON));
}

var fromJsonMethod = GetMethod(BindingFlags.DeclaredOnly);
if (fromJsonMethod == null)
{
fromJsonMethod = GetMethod();
}
if (fromJsonMethod == null)
{
throw new Exception("WTF");
}
if (fromJsonMethod.ContainsGenericParameters)
{
// TODO required by MDD indexer, goes through alot of jsons!
Log.Main.Trace?.Log(fromJsonMethod+ " ContainsGenericParameters");
continue;
}
Log.Main.Trace?.Log("IJsonTemplated.FromJSON " + fromJsonMethod);

yield return genericMethod.MakeGenericMethod(jsonTemplated);
// break;
}
}

private static readonly MTStopwatch s_newton = new();
private static readonly MTStopwatch s_stopwatch = new()
{
Callback = stats =>
{
var newtonStats = s_newton.GetStats();
Log.Main.Trace?.Log(
$"""
JSONSerializationUtility.FromJSON called {stats.Count} times, taking a total of {stats.TotalTime} with an average of {stats.AverageNanoseconds}ns.
Newton called {newtonStats.Count} times, taking a total of {newtonStats.TotalTime} with an average of {newtonStats.AverageNanoseconds}ns.
"""
);
},
CallbackForEveryNumberOfMeasurements = 100
};

internal class MyState
{
internal MTStopwatch.Tracker Tracker;
internal long counter = Interlocked.Increment(ref s_counter);

internal string nn;
internal string nh;
internal string hn;
internal string hh;

internal void Save()
{
var differentPopulate = true;
var differentSerializers = false; // tag sets and dictionaries work differently
if ((differentSerializers && nn != nh) || (differentPopulate && hn != nn))
{
File.WriteAllText(Path.Combine(basePath, $"{counter}_NN.json"), nn);
}
if ((differentSerializers && nn != nh) || (differentPopulate && nh != hh))
{
File.WriteAllText(Path.Combine(basePath, $"{counter}_NH.json"), nh);
}
if ((differentSerializers && hn != hh) || (differentPopulate && hn != nn))
{
File.WriteAllText(Path.Combine(basePath, $"{counter}_HN.json"), hn);
}
if ((differentSerializers && hn != hh) || (differentPopulate && nh != hh))
{
File.WriteAllText(Path.Combine(basePath, $"{counter}_HH.json"), hh);
}
}
}

private static long s_counter;

[HarmonyPriority(Priority.First)]
public static void Prefix(object target, string json, ref MyState __state)
{
if (target == null)
{
return;
}
if (typeof(MechDef).Assembly != target.GetType().Assembly)
{
return;
}

__state = new MyState();

if (testNewton) // && target.GetType() == typeof(MechDef)
{
s_newton.Start();
try
{
var objectCopy = Activator.CreateInstance(target.GetType());

if (objectCopy is MechDef mechDef1)
{
Log.Main.Trace?.Log($"BWTF???? mechDef.dataManager: {mechDef1.dataManager?.GetHashCode()}");
Log.Main.Trace?.Log($"BWTF???? mechDef._chassisDef: {mechDef1._chassisDef?.GetHashCode()}");
}

HBSJsonUtils.PopulateObject(objectCopy, json);

if (objectCopy is MechDef mechDef2)
{
Log.Main.Trace?.Log($"AWTF???? mechDef.dataManager: {mechDef2.dataManager?.GetHashCode()}");
Log.Main.Trace?.Log($"AWTF???? mechDef._chassisDef: {mechDef2._chassisDef?.GetHashCode()}");
}

__state.nn = HBSJsonUtils.SerializeObject(objectCopy);
__state.nh = JSON.ToJSON(objectCopy);
}
catch (Exception ex)
{
Log.Main.Error?.Log("Error Populating and Serializing " + target.GetType(), ex);
}
finally
{
s_newton.Stop();
}
}

__state.Tracker.Begin();
}

[HarmonyPriority(Priority.Last)]
public static void Postfix(object target, string json, ref MyState __state)
{
if (__state == null)
{
return;
}

s_stopwatch.AddMeasurement(__state.Tracker.End());

if (testNewton) // && target.GetType() == typeof(MechDef)
{
try
{
__state.hn = HBSJsonUtils.SerializeObject(target);
__state.hh = JSON.ToJSON(target);
}
catch (Exception ex)
{
Log.Main.Error?.Log("Error Serializing " + target.GetType(), ex);
}

try
{
__state.Save();
}
catch (Exception ex)
{
Log.Main.Error?.Log("Error Saving JSONs " + target.GetType(), ex);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static bool Prepare()
CallbackForEveryNumberOfMeasurements = 1000
};

[HarmonyPriority(Priority.First)]
[HarmonyPriority(Priority.Last)]
public static void Prefix(string classStructure, ref MTStopwatch.Tracker __state)
{
if (string.IsNullOrEmpty(classStructure))
Expand All @@ -43,7 +43,7 @@ public static void Prefix(string classStructure, ref MTStopwatch.Tracker __state
}
}

[HarmonyPriority(Priority.Last)]
[HarmonyPriority(Priority.First)]
public static void Postfix(string classStructure, ref MTStopwatch.Tracker __state)
{
if (string.IsNullOrEmpty(classStructure))
Expand Down
2 changes: 0 additions & 2 deletions ModTek/ModTek.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,10 @@
</ItemGroup>

<!-- helpful direct access to resources in BT, might trigger IDE indexing -->
<!--
<ItemGroup>
<None Include="$(BattleTechGameDir)\Mods\.modtek\*.txt;$(BattleTechGameDir)\Mods\.modtek\*.log" LinkBase=".modtek" />
<None Include="$(BattleTechGameDir)\BattleTech_Data\StreamingAssets\data\**\*.json;$(BattleTechGameDir)\BattleTech_Data\StreamingAssets\data\**\*.csv" LinkBase="BattleTech_Data"/>
</ItemGroup>
-->

<ItemGroup>
<ProjectReference Include="..\ModTek.Common\ModTek.Common.csproj" />
Expand Down
Loading

0 comments on commit ddb9380

Please sign in to comment.