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();
}
}