using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using Abilities;
using BepInEx;
using BepInEx.Logging;
using GameplayEntities;
using HarmonyLib;
using LLScreen;
using Microsoft.CodeAnalysis;
using Multiplayer;
using PunishInfo.FrameSync;
using PunishInfo.MatchInfo;
using PunishInfo.PluginSync;
using PunishInfo.Setup;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("com.github.daioutzu.punishinfo")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+3f1be305d6728173debe2b893b99672a62e003ef")]
[assembly: AssemblyProduct("PunishInfo")]
[assembly: AssemblyTitle("com.github.daioutzu.punishinfo")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace PunishInfo
{
[BepInPlugin("com.github.daioutzu.punishinfo", "PunishInfo", "1.1.0")]
[BepInProcess("LLBlaze.exe")]
public class PunishInfo_Plugin : BaseUnityPlugin
{
public static ManualLogSource Logger;
internal MatchInfoData pluginData;
internal MatchInfoData pluginDataSave;
internal CustomStateHistory stateHistory;
public static PunishInfo_Plugin Instance { get; private set; }
internal static Harmony Harmony { get; private set; } = new Harmony("com.github.daioutzu.punishinfo");
private void Awake()
{
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
if (!PluginBundle.Load((BaseUnityPlugin)(object)this, "ui_prefabs", "ui_sprites"))
{
Logger.LogFatal((object)"Plugin com.github.daioutzu.punishinfo has failed to load Bundle!");
return;
}
Harmony.PatchAll();
Logger.LogInfo((object)"Plugin com.github.daioutzu.punishinfo is loaded!");
}
}
internal enum PunishType
{
NONE,
COUNTER,
PUNISH,
PARRY_PUNISH
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.github.daioutzu.punishinfo";
public const string PLUGIN_NAME = "PunishInfo";
public const string PLUGIN_VERSION = "1.1.0";
}
}
namespace PunishInfo.Setup
{
internal static class PluginBundle
{
public static Dictionary<string, GameObject> prefabs { get; private set; } = new Dictionary<string, GameObject>();
public static Dictionary<string, Sprite> sprites { get; private set; } = new Dictionary<string, Sprite>();
public static bool Load(BaseUnityPlugin plugin, string bundleName)
{
AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(new DirectoryInfo(Path.Combine(Path.GetDirectoryName(plugin.Info.Location), "Bundles")).FullName, bundleName));
if ((Object)(object)val == (Object)null)
{
return false;
}
LoadPrefabs(val);
LoadSprites(val);
val.Unload(false);
return true;
}
public static bool Load(BaseUnityPlugin plugin, string prefabBundle, string uibunble)
{
DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(plugin.Info.Location), "Bundles"));
AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(directoryInfo.FullName, uibunble));
if ((Object)(object)val == (Object)null)
{
return false;
}
LoadSprites(val);
val = AssetBundle.LoadFromFile(Path.Combine(directoryInfo.FullName, prefabBundle));
if ((Object)(object)val == (Object)null)
{
return false;
}
LoadPrefabs(val);
val.Unload(false);
return true;
}
private static void LoadPrefabs(AssetBundle bundle)
{
GameObject[] array = bundle.LoadAllAssets<GameObject>();
foreach (GameObject val in array)
{
prefabs.Add(((Object)val).name, val);
}
}
private static void LoadSprites(AssetBundle bundle)
{
Sprite[] array = bundle.LoadAllAssets<Sprite>();
foreach (Sprite val in array)
{
sprites.Add(((Object)val).name, val);
}
}
}
}
namespace PunishInfo.MatchInfo
{
internal class AttackInfo
{
private const int HIT_TYPE_DURATION = 90;
private int playerIndex = -1;
private int prevHideTime = int.MaxValue;
private int prevOnHitFrame;
private PlayerStatistics playerStatistics;
private int prevHitCount;
private PunishType prevPunishType;
internal static AttackInfo[] attackInfos = new AttackInfo[4];
private GameObject attackInfoObjects;
private GameObject counterObj;
private GameObject punishObj;
private GameObject hitCountObj;
private Image imhitCount;
internal GameHudPlayerInfo GameHudPlayerInfo { get; private set; }
internal AttackInfo(GameHudPlayerInfo hudPlayerInfo)
{
GameHudPlayerInfo = hudPlayerInfo;
playerIndex = GameHudPlayerInfo.shownPlayer.CJFLMDNNMIE;
attackInfos[playerIndex] = this;
}
internal void Init()
{
attackInfoObjects = Object.Instantiate<GameObject>(PluginBundle.prefabs["AttackInfo"], ((Component)GameHudPlayerInfo).transform);
((Object)attackInfoObjects).name = $"AttackInfo_{playerIndex}";
GameObject gameObject = ((Component)attackInfoObjects.transform.GetChild(0)).gameObject;
counterObj = gameObject;
counterObj.SetActive(false);
GameObject gameObject2 = ((Component)attackInfoObjects.transform.GetChild(1)).gameObject;
punishObj = gameObject2;
punishObj.SetActive(false);
hitCountObj = ((Component)attackInfoObjects.transform.GetChild(2)).gameObject;
imhitCount = hitCountObj.GetComponent<Image>();
hitCountObj.SetActive(false);
playerStatistics = PunishInfo_Plugin.Instance.pluginData.playerStatistics[playerIndex];
}
private static bool GetSideHit(PlayerEntity playerEntity, Side side)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
Side val = ((EntityData)((MovableEntity)playerEntity).moveableData).heading;
if (((MovableData)((AbilityEntity)playerEntity).abilityData).abilityState.StartsWith("CROC_CLIMB"))
{
val = (Side)(val ^ 1);
}
return val != side;
}
internal void HitOtherPlayer(PlayerEntity victim, Side side)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendFormat("\n[{4}] P{0} Hit P{1} | {2} | {3}", playerIndex, ((AbilityEntity)victim).playerIndex, GetSideHit(victim, side) ? "Behind" : "Front", ((MovableData)victim.playerData).playerState, Math.SecondsToString(World.GetTimeLeftSecs() + 1));
if (((MovableData)((AbilityEntity)victim).abilityData).abilityState != "")
{
stringBuilder.AppendFormat(" | {0}", ((MovableData)((AbilityEntity)victim).abilityData).abilityState);
}
if (IsCounter(victim, ((MovableEntity)victim).GetCurrentAbilityState()))
{
playerStatistics.punishType = PunishType.COUNTER;
prevHideTime = Sync.curFrame + 90;
}
else
{
if (!IsPunish(victim, ((MovableEntity)victim).GetCurrentAbilityState()))
{
playerStatistics.punishType = PunishType.NONE;
return;
}
playerStatistics.punishType = PunishType.PUNISH;
prevHideTime = Sync.curFrame + 90;
}
stringBuilder.AppendFormat(" | {0}", playerStatistics.punishType.ToString());
if (playerStatistics.victimIndex == ((AbilityEntity)victim).playerIndex)
{
prevHitCount = playerStatistics.additionalHitCount++;
stringBuilder.AppendFormat(" | Combo: {0}", playerStatistics.additionalHitCount);
}
else
{
prevHitCount = (playerStatistics.additionalHitCount = 0);
}
SetVictim(victim);
prevOnHitFrame = Sync.curFrame;
PunishInfo_Plugin.Logger.LogWarning((object)stringBuilder.ToString());
}
internal void UpdateUI()
{
if (playerStatistics.punishType != prevPunishType)
{
ShowPunishText(playerStatistics.punishType);
prevPunishType = playerStatistics.punishType;
}
if (playerStatistics.additionalHitCount != prevHitCount)
{
ShowHitCount(playerStatistics.additionalHitCount);
prevHitCount = playerStatistics.additionalHitCount;
if (prevHitCount != 0)
{
ShowPunishText(playerStatistics.punishType);
}
}
HideUI();
}
private void ShowHitCount(int count)
{
if (!((Object)(object)hitCountObj == (Object)null))
{
if (count != 0)
{
imhitCount.sprite = PluginBundle.sprites[$"HitCount_{count - 1}"];
hitCountObj.SetActive(true);
}
else
{
hitCountObj.SetActive(false);
}
}
}
private void HideUI()
{
if (Sync.curFrame > prevHideTime)
{
HideUINow();
}
}
private void HideUINow()
{
punishObj.SetActive(false);
counterObj.SetActive(false);
hitCountObj.SetActive(false);
prevHideTime = int.MaxValue;
}
private void ShowPunishText(PunishType punishType)
{
switch (punishType)
{
case PunishType.COUNTER:
counterObj.SetActive(true);
punishObj.SetActive(false);
break;
case PunishType.PUNISH:
case PunishType.PARRY_PUNISH:
counterObj.SetActive(false);
punishObj.SetActive(true);
break;
default:
counterObj.SetActive(false);
punishObj.SetActive(false);
prevHideTime = int.MaxValue;
break;
}
}
internal void SetVictim(PlayerEntity playerEntity)
{
playerStatistics.victimIndex = ((AbilityEntity)playerEntity).playerIndex;
}
internal void ResetVictim(int playerIndex)
{
if (playerStatistics.victimIndex == playerIndex)
{
playerStatistics.additionalHitCount = 0;
playerStatistics.victimIndex = -1;
playerStatistics.punishType = PunishType.NONE;
}
}
private static bool IsCounter(PlayerEntity player, AbilityState currentAbilityState)
{
if (currentAbilityState == null)
{
return false;
}
int num = currentAbilityState.hitboxes?.Count ?? 0;
for (int i = 0; i < num; i++)
{
string key = currentAbilityState.hitboxes[i];
if (((Box)((AttackingEntity)player).hitboxes[key]).active)
{
return true;
}
}
if (!string.IsNullOrEmpty(currentAbilityState.nextAbilityState))
{
return ((AbilityEntity)player).abilityStates[currentAbilityState.nextAbilityState].hitboxes.Count > 0;
}
string bufferAbility = ((AbilityEntity)player).abilityData.bufferAbility;
if (currentAbilityState.name == "POST_CROUCH" && bufferAbility != "jump" && bufferAbility != string.Empty)
{
return true;
}
return false;
}
private static bool IsPunish(PlayerEntity player, AbilityState abilityState)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Invalid comparison between Unknown and I4
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Invalid comparison between Unknown and I4
string text = ((AbilityEntity)player).GetCurrentAbility()?.name;
bool flag = !string.IsNullOrEmpty(text) && (text == "crouch" || text == "knockedOut");
if ((int)((MovableData)player.playerData).playerState == 2 || flag)
{
return false;
}
if (!((AbilityData)player.playerData).checkedActionsThisFrame && ((int)((MovableData)player.playerData).playerState == 0 || ((int)((MovableData)player.playerData).playerState == 1 && abilityState.canBeCancelledByAnyAction)))
{
return false;
}
return true;
}
internal void Destroy()
{
Object.Destroy((Object)(object)attackInfoObjects);
Object.Destroy((Object)(object)counterObj);
Object.Destroy((Object)(object)punishObj);
Object.Destroy((Object)(object)hitCountObj);
attackInfos[playerIndex] = null;
}
}
internal class PlayerStatistics
{
internal int additionalHitCount;
internal PunishType punishType;
internal int victimIndex = -1;
internal void Load(PlayerStatistics load)
{
additionalHitCount = load.additionalHitCount;
punishType = load.punishType;
victimIndex = load.victimIndex;
}
}
}
namespace PunishInfo.MatchInfo.Patches
{
[HarmonyPatch]
internal static class AttackInfo_Patches
{
[HarmonyPatch(typeof(GameHudPlayerInfo), "UpdateInfo")]
[HarmonyPostfix]
private static void UpdateAttackInfo(GameHudPlayerInfo __instance)
{
for (int i = 0; i < 4; i++)
{
if (AttackInfo.attackInfos[i] != null)
{
AttackInfo.attackInfos[i].UpdateUI();
}
}
}
[HarmonyPatch(typeof(ScreenGameHud), "DestroyPlayerInfos")]
[HarmonyPostfix]
private static void DestroyAttackInfos(ScreenGameHud __instance)
{
for (int i = 0; i < 4; i++)
{
if (AttackInfo.attackInfos[i] != null)
{
AttackInfo.attackInfos[i].Destroy();
AttackInfo.attackInfos[i] = null;
}
}
}
[HarmonyPatch(typeof(AbilityEntity), "EndAbilityStateToNormal")]
[HarmonyPrefix]
private static void ResetHitCount(AbilityEntity __instance)
{
PlayerEntity val = (PlayerEntity)(object)((__instance is PlayerEntity) ? __instance : null);
if ((Object)(object)val == (Object)null)
{
return;
}
for (int i = 0; i < 4; i++)
{
if (AttackInfo.attackInfos[i] != null && (!(((AbilityEntity)val).abilityData.bufferAbility == "bunt") || !(((MovableData)((AbilityEntity)val).abilityData).abilityState == "GET_UP")))
{
AttackInfo.attackInfos[i].ResetVictim(((AbilityEntity)val).playerIndex);
}
}
}
[HarmonyPatch(typeof(AbilityEntity), "Spawn")]
[HarmonyPostfix]
private static void ResetVictimOnSpawn(AbilityEntity __instance)
{
PlayerEntity val = (PlayerEntity)(object)((__instance is PlayerEntity) ? __instance : null);
if ((Object)(object)val == (Object)null)
{
return;
}
for (int i = 0; i < 4; i++)
{
if (AttackInfo.attackInfos[i] != null)
{
AttackInfo.attackInfos[i].ResetVictim(((AbilityEntity)val).playerIndex);
}
}
}
[HarmonyPatch(typeof(GetHitBallEntity), "HitPlayer")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> GetHitBallEntity_HitPlayer(IEnumerable<CodeInstruction> instructions)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Expected O, but got Unknown
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Expected O, but got Unknown
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Expected O, but got Unknown
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Expected O, but got Unknown
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Expected O, but got Unknown
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction iL) => iL.opcode == OpCodes.Callvirt && (iL.operand as MethodBase).Name == "GetHitByBall")).Advance(-1);
MethodInfo methodInfo = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => Invoke_HitOtherPlayer(null, 0, (Side)0)));
val.Insert((CodeInstruction[])(object)new CodeInstruction[6]
{
new CodeInstruction(OpCodes.Ldarg_1, (object)null),
new CodeInstruction(OpCodes.Ldarg_0, (object)null),
new CodeInstruction(OpCodes.Ldfld, (object)typeof(GetHitBallEntity).GetField("ballData")),
new CodeInstruction(OpCodes.Ldfld, (object)typeof(BallData).GetField("lastHitterIndex")),
new CodeInstruction(OpCodes.Ldloc_0, (object)null),
new CodeInstruction(OpCodes.Call, (object)methodInfo)
});
return val.InstructionEnumeration();
}
private static void Invoke_HitOtherPlayer(PlayerEntity victim, int hitterIndex, Side side)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (AttackInfo.attackInfos[hitterIndex] != null)
{
AttackInfo.attackInfos[hitterIndex].HitOtherPlayer(victim, side);
}
}
}
[HarmonyPatch]
internal class SpawnPlayerInfos_Patch
{
[HarmonyTargetMethod]
private static MethodInfo TargetMethod()
{
return typeof(ScreenGameHud).GetNestedType("<SpawnPlayerInfos>c__AnonStoreyC", BindingFlags.NonPublic).GetMethod("<>m__0", BindingFlags.Instance | BindingFlags.NonPublic);
}
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction iL) => iL.opcode == OpCodes.Callvirt && (iL.operand as MethodBase).Name == "SetPlayer")).ThrowIfNotMatch("'SetPlayer' was not found", (CodeMatch[])(object)new CodeMatch[0]).Advance(1);
val.Insert((CodeInstruction[])(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldloc_2, (object)null),
Transpilers.EmitDelegate<Action<GameHudPlayerInfo>>((Action<GameHudPlayerInfo>)delegate(GameHudPlayerInfo playerInfo)
{
new AttackInfo(playerInfo).Init();
})
});
return val.InstructionEnumeration();
}
}
}
namespace PunishInfo.PluginSync
{
internal class MatchInfoData
{
internal PlayerStatistics[] playerStatistics;
public MatchInfoData()
{
playerStatistics = new PlayerStatistics[4];
for (int i = 0; i < 4; i++)
{
playerStatistics[i] = new PlayerStatistics();
}
}
public void Load(MatchInfoData load, bool saving)
{
for (int i = 0; i < 4; i++)
{
playerStatistics[i].Load(load.playerStatistics[i]);
}
}
}
internal class PluginState : FrameObject
{
internal MatchInfoData PluginData { get; private set; }
public PluginState(MatchInfoData pluginData, int frame)
{
PluginData = pluginData;
base.frame = frame;
}
}
}
namespace PunishInfo.FrameSync
{
internal class CustomStateHistory
{
private List<PluginState> history;
public CustomStateHistory()
{
history = new List<PluginState>(50);
}
public void LoadFrame(int frame)
{
PluginState item = FrameObject.GetItem<PluginState>(history, frame);
if (item == null)
{
PunishInfo_Plugin.Logger.LogError((object)("Couldn't get savedgame for frame " + frame + " (history: " + GetHistoryString() + ")"));
}
else
{
PunishInfo_Plugin.Instance.pluginData.Load(item.PluginData, saving: false);
if (history.Count > FrameObject.lastIndex + 1)
{
history.RemoveRange(FrameObject.lastIndex + 1, history.Count - (FrameObject.lastIndex + 1));
}
}
}
public void SaveFrame(int frame)
{
MatchInfoData matchInfoData = MatchDataPool.Get();
matchInfoData.Load(PunishInfo_Plugin.Instance.pluginData, saving: true);
FrameObject.AddToList<PluginState>(history, new PluginState(matchInfoData, frame));
}
public void DeleteFramesBefore(int frame)
{
while (history.Count > 0 && ((FrameObject)history[0]).frame < frame)
{
MatchDataPool.Return(history[0].PluginData);
history.RemoveAt(0);
}
}
public void DeleteFramesAfter(int frame)
{
while (history.Count > 0 && ((FrameObject)history[history.Count - 1]).frame > frame)
{
MatchDataPool.Return(history[history.Count - 1].PluginData);
history.RemoveAt(history.Count - 1);
}
}
public string GetHistoryString()
{
List<string> list = new List<string>(50);
foreach (PluginState item in history)
{
list.Add(((FrameObject)item).frame.ToString());
}
return string.Join(",", list.ToArray());
}
public override string ToString()
{
if (history.Count == 0)
{
return "[empty]";
}
int frame = ((FrameObject)history[0]).frame;
int frame2 = ((FrameObject)history[history.Count - 1]).frame;
string text = "[" + frame + " - " + frame2;
if (history.Count - 1 != frame2 - frame)
{
string text2 = text;
text = text2 + " (length " + history.Count + "??)";
}
return text + "]";
}
}
internal class MatchDataPool
{
private static Stack<MatchInfoData> unused;
private static bool inited;
private static void Init()
{
unused = new Stack<MatchInfoData>();
AddSome();
inited = true;
}
private static void AddSome()
{
for (int i = 0; i < 10; i++)
{
unused.Push(new MatchInfoData());
}
}
public static MatchInfoData Get()
{
if (!inited)
{
Init();
}
if (unused.Count == 0)
{
AddSome();
}
return unused.Pop();
}
public static void Return(MatchInfoData pluginData)
{
unused.Push(pluginData);
}
}
}
namespace PunishInfo.FrameSync.Patches
{
[HarmonyPatch(typeof(StateHistory))]
internal class StateHistory_Patch
{
[HarmonyPatch("LoadFrame")]
[HarmonyPostfix]
private static void LoadFrame(StateHistory __instance, int frame)
{
PunishInfo_Plugin.Instance.stateHistory.LoadFrame(frame);
}
[HarmonyPatch("SaveFrame")]
[HarmonyPostfix]
private static void SaveFrame(StateHistory __instance, int frame)
{
PunishInfo_Plugin.Instance.stateHistory.SaveFrame(frame);
}
[HarmonyPatch("DeleteFramesBefore")]
[HarmonyPostfix]
private static void DeleteFramesBefore(StateHistory __instance, int frame)
{
PunishInfo_Plugin.Instance.stateHistory.DeleteFramesBefore(frame);
}
[HarmonyPatch("DeleteFramesAfter")]
[HarmonyPostfix]
private static void DeleteFramesAfter(StateHistory __instance, int frame)
{
PunishInfo_Plugin.Instance.stateHistory.DeleteFramesAfter(frame);
}
}
[HarmonyPatch]
internal class Sync_Patches
{
[HarmonyPatch(typeof(Sync), "Init")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> CreateNewStateHistory(IEnumerable<CodeInstruction> instructions)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction iL) => iL.opcode == OpCodes.Stsfld && (iL.operand as FieldInfo).Name == "stateHistory")).Advance(1);
val.Insert((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate<Action>((Action)delegate
{
PunishInfo_Plugin.Instance.stateHistory = new CustomStateHistory();
}) });
return val.InstructionEnumeration();
}
}
[HarmonyPatch(typeof(World))]
internal class World_Patches
{
[HarmonyPatch("Init1")]
[HarmonyPostfix]
private static void Init1_Patch(World __instance)
{
PunishInfo_Plugin.Instance.pluginData = new MatchInfoData();
}
[HarmonyPatch("SaveState")]
[HarmonyPostfix]
private static void SaveState(World __instance)
{
PunishInfo_Plugin instance = PunishInfo_Plugin.Instance;
if (instance.pluginDataSave == null)
{
instance.pluginDataSave = new MatchInfoData();
}
instance.pluginDataSave.Load(instance.pluginData, saving: true);
}
[HarmonyPatch("LoadState")]
[HarmonyPostfix]
private static void LoadState(World __instance)
{
PunishInfo_Plugin instance = PunishInfo_Plugin.Instance;
if (instance.pluginDataSave != null)
{
instance.pluginData.Load(instance.pluginDataSave, saving: false);
}
}
}
}