BepInEx/plugins/RedoMod.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RedoMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RedoMod")]
[assembly: AssemblyTitle("RedoMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace RedoMod;

[BepInPlugin("redo.mod", "RedoMod", "1.0.0")]
public class RedoPlugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	private static Harmony _harmony;

	public void Awake()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		_harmony = new Harmony("redo.mod");
		try
		{
			_harmony.CreateClassProcessor(typeof(RedoPatches)).Patch();
			Log.LogInfo((object)"Loaded RedoMod v1.0.0");
			Type[] array = new Type[5]
			{
				typeof(BuildingActionPlace),
				typeof(BuildingActionDelete),
				typeof(BuildingActionMove),
				typeof(BuildingActionRotate),
				typeof(BuildingActionColor)
			};
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				MethodInfo methodInfo = AccessTools.Method(type, "DoUndo", (Type[])null, (Type[])null);
				Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
				if (patchInfo == null || patchInfo.Prefixes.Count == 0)
				{
					Log.LogWarning((object)("[PATCH] NOT patched: " + type.Name + ".DoUndo"));
				}
				else
				{
					Log.LogInfo((object)("[PATCH] OK: " + type.Name + ".DoUndo"));
				}
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(BuildingUndoManager), "undoLastBuildingAction", (Type[])null, (Type[])null);
			Patches patchInfo2 = Harmony.GetPatchInfo((MethodBase)methodInfo2);
			if (patchInfo2 == null || patchInfo2.Prefixes.Count == 0)
			{
				Log.LogWarning((object)"[PATCH] NOT patched: BuildingUndoManager.undoLastBuildingAction");
			}
			else
			{
				Log.LogInfo((object)"[PATCH] OK: BuildingUndoManager.undoLastBuildingAction");
			}
		}
		catch (Exception arg)
		{
			Log.LogError((object)$"Failed to patch: {arg}");
		}
	}

	public void Update()
	{
		if (Input.GetKeyDown((KeyCode)121))
		{
			Log.LogInfo((object)$"[Y PRESSED] Stack count: {RedoPatches.RedoStack.Count}");
			RedoPatches.PerformRedo();
		}
		if (Input.GetKeyDown((KeyCode)122))
		{
			Log.LogInfo((object)$"[Z PRESSED] Current redo stack: {RedoPatches.RedoStack.Count}");
		}
	}

	public void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchAll("redo.mod");
		}
	}
}
[HarmonyPatch]
public static class RedoPatches
{
	internal class RedoEntry
	{
		public BuildingAction Action;

		public List<PartConfiguration> PostMoveConfigs;

		public List<PartDirection> PostDirections;

		public List<PartRotation> PostRotations;

		public List<int> PostColors;
	}

	internal static List<RedoEntry> RedoStack = new List<RedoEntry>();

	private static bool _isRedoing = false;

	private static bool _isUndoing = false;

	private static PartBuildingContainer GetContainer(BuildingUndoManager m)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		return (PartBuildingContainer)(AccessTools.Field(typeof(BuildingUndoManager), "partBuildingContainer")?.GetValue(m));
	}

	private static BuildingMouseMovement GetMouse(BuildingUndoManager m)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		return (BuildingMouseMovement)(AccessTools.Field(typeof(BuildingUndoManager), "buildingMouseMovement")?.GetValue(m));
	}

	private static void SetDontRegister(BuildingUndoManager m, bool v)
	{
		AccessTools.Field(typeof(BuildingUndoManager), "_dontRegsiterBuildingSteps")?.SetValue(m, v);
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(BuildingUndoManager), "undoLastBuildingAction")]
	public static void Patch_UndoLastBuildingAction(BuildingUndoManager __instance)
	{
		List<BuildingAction> list = (List<BuildingAction>)(AccessTools.Field(typeof(BuildingUndoManager), "_buildingActions")?.GetValue(__instance));
		if (list != null && list.Count != 0)
		{
			BuildingAction val = list[list.Count - 1];
			RedoPlugin.Log.LogInfo((object)("[PATCH] Capturing: " + ((object)val)?.GetType().Name));
			Capture(val, GetContainer(__instance));
			_isUndoing = true;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(BuildingUndoManager), "undoLastBuildingAction")]
	public static void Patch_UndoLastBuildingAction_Post()
	{
		_isUndoing = false;
	}

	private static void Capture(BuildingAction action, PartBuildingContainer container)
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		RedoEntry redoEntry = new RedoEntry
		{
			Action = action
		};
		BuildingActionMove val = (BuildingActionMove)(object)((action is BuildingActionMove) ? action : null);
		if (val != null)
		{
			redoEntry.PostMoveConfigs = new List<PartConfiguration>();
			foreach (PartConfiguration movedPart in val.MovedParts)
			{
				PartBuilding val2 = ((container != null) ? container.GetPart(movedPart) : null);
				object obj = redoEntry.PostMoveConfigs;
				obj = (((Object)(object)val2 != (Object)null) ? ((object)new PartConfiguration(val2.Direction, val2.Rotation, val2.Position, val2.Type)) : ((object)movedPart));
				((List<PartConfiguration>)obj).Add((PartConfiguration)obj);
			}
		}
		else
		{
			BuildingActionRotate val3 = (BuildingActionRotate)(object)((action is BuildingActionRotate) ? action : null);
			if (val3 != null)
			{
				redoEntry.PostDirections = new List<PartDirection>();
				redoEntry.PostRotations = new List<PartRotation>();
				foreach (PartConfiguration movedPart2 in val3.MovedParts)
				{
					PartBuilding val4 = ((container != null) ? container.GetPart(movedPart2) : null);
					redoEntry.PostDirections.Add((val4 != null) ? val4.Direction : movedPart2.partDirection);
					redoEntry.PostRotations.Add((val4 != null) ? val4.Rotation : movedPart2.partRotation);
				}
			}
			else
			{
				BuildingActionColor val5 = (BuildingActionColor)(object)((action is BuildingActionColor) ? action : null);
				if (val5 != null)
				{
					redoEntry.PostColors = new List<int>();
					for (int i = 0; i < val5.Parts.Count; i++)
					{
						int item = val5.PrevColors[i];
						if ((Object)(object)container != (Object)null)
						{
							foreach (PartBuilding part in container.Parts)
							{
								if (((object)part.PartConfiguration).Equals((object?)val5.Parts[i]))
								{
									item = part.Color;
									break;
								}
							}
						}
						redoEntry.PostColors.Add(item);
					}
				}
			}
		}
		RedoStack.Add(redoEntry);
		RedoPlugin.Log.LogInfo((object)$"[CAPTURE] {((object)action).GetType().Name} — stack: {RedoStack.Count}");
	}

	public static void PerformRedo()
	{
		if (RedoStack.Count == 0)
		{
			return;
		}
		BuildingUndoManager val = Object.FindAnyObjectByType<BuildingUndoManager>();
		if ((Object)(object)val == (Object)null)
		{
			RedoPlugin.Log.LogWarning((object)"[REDO] No manager!");
			return;
		}
		PartBuildingContainer container = GetContainer(val);
		BuildingMouseMovement mouse = GetMouse(val);
		if ((Object)(object)container == (Object)null || (Object)(object)mouse == (Object)null)
		{
			RedoPlugin.Log.LogWarning((object)"[REDO] Null container/mouse!");
			return;
		}
		RedoEntry entry = RedoStack[RedoStack.Count - 1];
		RedoStack.RemoveAt(RedoStack.Count - 1);
		mouse.DeselectAllCurrentlySelectedParts();
		SetDontRegister(val, v: true);
		_isRedoing = true;
		try
		{
			DoRedo(entry, container);
		}
		catch (Exception arg)
		{
			RedoPlugin.Log.LogError((object)$"[REDO] {arg}");
		}
		_isRedoing = false;
		SetDontRegister(val, v: false);
	}

	private static void DoRedo(RedoEntry entry, PartBuildingContainer container)
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Expected O, but got Unknown
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Expected O, but got Unknown
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_033c: Unknown result type (might be due to invalid IL or missing references)
		BuildingAction action = entry.Action;
		BuildingActionPlace val = (BuildingActionPlace)(object)((action is BuildingActionPlace) ? action : null);
		if (val != null)
		{
			RedoPlugin.Log.LogInfo((object)$"[REDO] Place {val.PlacedParts.Count}");
			for (int i = 0; i < val.PlacedParts.Count; i++)
			{
				PartConfiguration val2 = val.PlacedParts[i];
				container.AddPart(val2.partType, val2.partDirection, val2.partRotation, val2.partPosition, val.PartColors[i]);
			}
			return;
		}
		BuildingActionDelete val3 = (BuildingActionDelete)(object)((action is BuildingActionDelete) ? action : null);
		if (val3 != null)
		{
			RedoPlugin.Log.LogInfo((object)$"[REDO] Delete {val3.DeletedParts.Count}");
			for (int j = 0; j < val3.DeletedParts.Count; j++)
			{
				container.RemovePart(val3.DeletedParts[j]);
			}
			return;
		}
		BuildingActionMove val4 = (BuildingActionMove)(object)((action is BuildingActionMove) ? action : null);
		if (val4 != null)
		{
			RedoPlugin.Log.LogInfo((object)$"[REDO] Move {val4.MovedParts.Count}");
			for (int k = 0; k < val4.MovedParts.Count; k++)
			{
				PartBuilding part = container.GetPart(new PartConfiguration(val4.MovedParts[k].partDirection, val4.MovedParts[k].partRotation, val4.OriginalPositions[k], val4.MovedParts[k].partType));
				if ((Object)(object)part != (Object)null && entry.PostMoveConfigs != null && k < entry.PostMoveConfigs.Count)
				{
					PartConfiguration val5 = entry.PostMoveConfigs[k];
					part.LerpToNewPose(val5.partPosition, val5.partDirection, val5.partRotation, false, 0.15f);
				}
				else
				{
					RedoPlugin.Log.LogWarning((object)$"[REDO] Move: GetPart returned null for index {k}");
				}
			}
			return;
		}
		BuildingActionRotate val6 = (BuildingActionRotate)(object)((action is BuildingActionRotate) ? action : null);
		if (val6 != null)
		{
			RedoPlugin.Log.LogInfo((object)$"[REDO] Rotate {val6.MovedParts.Count}");
			for (int l = 0; l < val6.MovedParts.Count; l++)
			{
				PartBuilding part2 = container.GetPart(new PartConfiguration(val6.OriginalDirections[l], val6.OriginalRotations[l], val6.MovedParts[l].partPosition, val6.MovedParts[l].partType));
				if ((Object)(object)part2 != (Object)null && entry.PostDirections != null && l < entry.PostDirections.Count)
				{
					part2.LerpToNewPose(val6.MovedParts[l].partPosition, entry.PostDirections[l], entry.PostRotations[l], false, 0.15f);
				}
				else
				{
					RedoPlugin.Log.LogWarning((object)$"[REDO] Rotate: GetPart returned null for index {l}");
				}
			}
			return;
		}
		BuildingActionColor val7 = (BuildingActionColor)(object)((action is BuildingActionColor) ? action : null);
		if (val7 == null)
		{
			return;
		}
		RedoPlugin.Log.LogInfo((object)$"[REDO] Color {val7.Parts.Count}");
		for (int m = 0; m < val7.Parts.Count; m++)
		{
			foreach (PartBuilding part3 in container.Parts)
			{
				if (((object)part3.PartConfiguration).Equals((object?)val7.Parts[m]))
				{
					if (entry.PostColors != null && m < entry.PostColors.Count)
					{
						part3.Color = entry.PostColors[m];
					}
					break;
				}
			}
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(BuildingUndoManager), "PartBuildingContainer_PartPlaced")]
	public static void Clear_PartPlaced()
	{
		if (!_isRedoing && !_isUndoing)
		{
			RedoPlugin.Log.LogInfo((object)"[CLEAR] PartPlaced");
			RedoStack.Clear();
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(BuildingUndoManager), "PartBuildingContainer_PartDeleted")]
	public static void Clear_PartDeleted()
	{
		if (!_isRedoing && !_isUndoing)
		{
			RedoPlugin.Log.LogInfo((object)"[CLEAR] PartDeleted");
			RedoStack.Clear();
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(BuildingUndoManager), "PartBuildingContainer_PartsMoved")]
	public static void Clear_PartsMoved()
	{
		if (!_isRedoing && !_isUndoing)
		{
			RedoPlugin.Log.LogInfo((object)"[CLEAR] PartsMoved");
			RedoStack.Clear();
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(BuildingUndoManager), "PartBuildingContainer_PartsRotated")]
	public static void Clear_PartsRotated()
	{
		if (!_isRedoing && !_isUndoing)
		{
			RedoPlugin.Log.LogInfo((object)"[CLEAR] PartsRotated");
			RedoStack.Clear();
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(BuildingUndoManager), "BuildingMouseMovement_OnColorPart")]
	public static void Clear_ColorPart()
	{
		if (!_isRedoing && !_isUndoing)
		{
			RedoPlugin.Log.LogInfo((object)"[CLEAR] ColorPart");
			RedoStack.Clear();
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(BuildingUndoManager), "ManagerBuilding_BulidingActiveChanged")]
	public static void Clear_BuildingActiveChanged()
	{
		RedoPlugin.Log.LogInfo((object)"[CLEAR] BuildingActiveChanged");
		RedoStack.Clear();
	}
}