using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CartFlipper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CartFlipper")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a20715f2-454b-4f1b-9db2-1475b244b32e")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CartFlipperMod;
public static class Constants
{
public const string ModVersion = "1.0.1";
}
[BepInPlugin("wylker.cartflipper", "Cart Flipper", "1.0.1")]
public class CartFlipper : BaseUnityPlugin
{
[CompilerGenerated]
private sealed class <FlipCartCoroutine>d__18 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public CartFlipper <>4__this;
public GameObject cartObject;
private int <maxRetries>5__2;
private int <attempts>5__3;
private Rigidbody <rb>5__4;
private float <originalDrag>5__5;
private float <originalAngularDrag>5__6;
private Vector3 <originalPos>5__7;
private float <liftDuration>5__8;
private float <liftTimer>5__9;
private Vector3 <targetLiftPos>5__10;
private Quaternion <currentRot>5__11;
private Quaternion <targetRot>5__12;
private float <rotateDuration>5__13;
private float <rotateTimer>5__14;
private float <lowerDuration>5__15;
private float <lowerTimer>5__16;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <FlipCartCoroutine>d__18(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<rb>5__4 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0200: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_0263: Unknown result type (might be due to invalid IL or missing references)
//IL_0269: Unknown result type (might be due to invalid IL or missing references)
//IL_027b: Unknown result type (might be due to invalid IL or missing references)
//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
//IL_02da: Expected O, but got Unknown
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
CartFlipper cartFlipper = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<maxRetries>5__2 = cartFlipper.configMaxRetries.Value;
<attempts>5__3 = 0;
<rb>5__4 = cartObject.GetComponent<Rigidbody>();
if ((Object)(object)<rb>5__4 == (Object)null)
{
((BaseUnityPlugin)cartFlipper).Logger.LogWarning((object)"Cart object lost its Rigidbody during flip.");
return false;
}
<originalDrag>5__5 = <rb>5__4.drag;
<originalAngularDrag>5__6 = <rb>5__4.angularDrag;
<originalPos>5__7 = ((Component)<rb>5__4).transform.position;
<rb>5__4.drag = <originalDrag>5__5 * 5f;
<rb>5__4.angularDrag = <originalAngularDrag>5__6 * 5f;
goto IL_0363;
case 1:
<>1__state = -1;
goto IL_016f;
case 2:
<>1__state = -1;
goto IL_0224;
case 3:
<>1__state = -1;
goto IL_029c;
case 4:
{
<>1__state = -1;
float num2 = Vector3.Angle(((Component)<rb>5__4).transform.up, Vector3.up);
((BaseUnityPlugin)cartFlipper).Logger.LogInfo((object)("Flip attempt " + (<attempts>5__3 + 1) + ": cart angle = " + num2));
if (num2 < 90f)
{
((BaseUnityPlugin)cartFlipper).Logger.LogInfo((object)"Cart successfully flipped upright.");
break;
}
<attempts>5__3++;
goto IL_0363;
}
IL_016f:
if (<liftTimer>5__9 < <liftDuration>5__8)
{
<liftTimer>5__9 += Time.deltaTime;
<rb>5__4.MovePosition(Vector3.Lerp(<originalPos>5__7, <targetLiftPos>5__10, <liftTimer>5__9 / <liftDuration>5__8));
<>2__current = null;
<>1__state = 1;
return true;
}
<currentRot>5__11 = ((Component)<rb>5__4).transform.rotation;
<targetRot>5__12 = Quaternion.Euler(0f, ((Quaternion)(ref <currentRot>5__11)).eulerAngles.y, 0f);
<rotateDuration>5__13 = 3f;
<rotateTimer>5__14 = 0f;
goto IL_0224;
IL_029c:
if (<lowerTimer>5__16 < <lowerDuration>5__15)
{
<lowerTimer>5__16 += Time.deltaTime;
<rb>5__4.MovePosition(Vector3.Lerp(<targetLiftPos>5__10, <originalPos>5__7, <lowerTimer>5__16 / <lowerDuration>5__15));
<>2__current = null;
<>1__state = 3;
return true;
}
<rb>5__4.velocity = Vector3.zero;
<rb>5__4.angularVelocity = Vector3.zero;
<>2__current = (object)new WaitForSeconds(1f);
<>1__state = 4;
return true;
IL_0224:
if (<rotateTimer>5__14 < <rotateDuration>5__13)
{
<rotateTimer>5__14 += Time.deltaTime;
Quaternion val = Quaternion.Lerp(<currentRot>5__11, <targetRot>5__12, <rotateTimer>5__14 / <rotateDuration>5__13);
<rb>5__4.MoveRotation(val);
<>2__current = null;
<>1__state = 2;
return true;
}
<lowerDuration>5__15 = 1f;
<lowerTimer>5__16 = 0f;
goto IL_029c;
IL_0363:
if (<attempts>5__3 >= <maxRetries>5__2)
{
break;
}
<liftDuration>5__8 = 1f;
<liftTimer>5__9 = 0f;
<targetLiftPos>5__10 = <originalPos>5__7 + Vector3.up * 1.5f;
goto IL_016f;
}
<rb>5__4.drag = <originalDrag>5__5;
<rb>5__4.angularDrag = <originalAngularDrag>5__6;
if (<attempts>5__3 == <maxRetries>5__2)
{
((BaseUnityPlugin)cartFlipper).Logger.LogWarning((object)"Flip attempts exhausted; cart remains flipped.");
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <Start>d__10 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public CartFlipper <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Start>d__10(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Expected O, but got Unknown
int num = <>1__state;
CartFlipper cartFlipper = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitUntil((Func<bool>)(() => ZRoutedRpc.instance != null));
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
ConfigFlipKey = cartFlipper.configFlipKey.Value;
ZRoutedRpc.instance.Register<ZPackage>("RPC_FlipCart", (Action<long, ZPackage>)cartFlipper.RPC_FlipCart);
if (cartFlipper.IsServer())
{
ZRoutedRpc.instance.Register<ZPackage>("RPC_SendModVersion", (Action<long, ZPackage>)cartFlipper.RPC_SendModVersion);
<>2__current = (object)new WaitForSeconds(5f);
<>1__state = 2;
return true;
}
ZRoutedRpc.instance.Register<ZPackage>("RPC_RequestModVersion", (Action<long, ZPackage>)cartFlipper.RPC_RequestModVersion);
break;
case 2:
<>1__state = -1;
cartFlipper.RequestModVersionFromAllPeers();
break;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private ConfigEntry<KeyCode> configFlipKey;
private ConfigEntry<int> configMaxRetries;
public static Interactable CurrentHoveredInteractable;
private Harmony harmony;
public static KeyCode ConfigFlipKey { get; private set; }
private void Awake()
{
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
((BaseUnityPlugin)this).Logger.LogInfo((object)"CartFlipper mod loaded (v1.0.1)");
configFlipKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "FlipKey", (KeyCode)111, "The key used to flip the cart.");
configMaxRetries = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxRetries", 3, "Carts are often stubborn about being flipped. Set the maximum number of automatic flip attempts per keypress.");
harmony = new Harmony("com.wylker.cartflipper.patch");
harmony.PatchAll();
}
private void OnDestroy()
{
harmony.UnpatchSelf();
}
[IteratorStateMachine(typeof(<Start>d__10))]
private IEnumerator Start()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Start>d__10(0)
{
<>4__this = this
};
}
private void Update()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
if (Application.isBatchMode || !Input.GetKeyDown(configFlipKey.Value))
{
return;
}
Player localPlayer = Player.m_localPlayer;
GameObject val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetHoverObject() : null);
if ((Object)(object)val != (Object)null)
{
if (IsCart(val.transform))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Targeted object is a cart. Initiating flip.");
FlipCart(val);
}
else
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Targeted object is not a cart.");
}
}
else
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"No acceptable object found.");
}
}
private bool IsCart(Transform t)
{
return ((Object)t).name.Contains("Cart");
}
private bool IsFlipped(Transform t)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
float num = Vector3.Angle(t.up, Vector3.up);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"{((Object)t).name} angle to upright: {num}");
return num > 90f;
}
private long ZDOIDToLong(ZDOID id)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
ZPackage val = new ZPackage();
val.Write(id);
val.SetPos(0);
return val.ReadLong();
}
private void FlipCart(GameObject cartObject)
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Expected O, but got Unknown
ZNetView component = cartObject.GetComponent<ZNetView>();
if ((Object)(object)component == (Object)null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Cart does not have a ZNetView.");
return;
}
ZDO zDO = component.GetZDO();
if (zDO == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Cart has no ZDO.");
return;
}
ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
ZDOID uid = zDO.m_uid;
logger.LogInfo((object)("Preparing to flip cart with UID: " + ((object)(ZDOID)(ref uid)).ToString()));
if ((Object)(object)Player.m_localPlayer != (Object)null)
{
ZNetView component2 = ((Component)Player.m_localPlayer).GetComponent<ZNetView>();
if ((Object)(object)component2 != (Object)null)
{
long num = ZDOIDToLong(component2.GetZDO().m_uid);
string text = ((object)(ZDOID)(ref zDO.m_uid)).ToString();
ZPackage val = new ZPackage();
val.Write(text);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Sending RPC with sender id: " + num + " for cart UID: " + text));
ZRoutedRpc.instance.InvokeRoutedRPC(num, "RPC_FlipCart", new object[1] { val });
((BaseUnityPlugin)this).Logger.LogInfo((object)"RPC invoked via ZRoutedRpc instance.");
}
else
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Local player's ZNetView not found.");
}
}
else
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Local player is null. Cannot send RPC.");
}
}
private ZDOID ParseZDOID(string uidStr)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
string[] array = uidStr.Split(new char[1] { ':' });
if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2))
{
return new ZDOID((long)(uint)result, (uint)result2);
}
throw new Exception("Invalid ZDOID string: " + uidStr);
}
public void RPC_FlipCart(long sender, ZPackage pkg)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: 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_0090: Unknown result type (might be due to invalid IL or missing references)
((BaseUnityPlugin)this).Logger.LogInfo((object)("RPC_FlipCart received on server. Sender: " + sender));
string text = pkg.ReadString();
((BaseUnityPlugin)this).Logger.LogInfo((object)("Received cart UID (as string): " + text));
ZDOID val;
try
{
val = ParseZDOID(text);
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to convert UID string to ZDOID: " + ex.Message));
return;
}
ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
ZDOID val2 = val;
logger.LogInfo((object)("Converted cart UID to ZDOID: " + ((object)(ZDOID)(ref val2)).ToString()));
ZDO zDO = ZDOMan.instance.GetZDO(val);
if (zDO == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("No ZDO found for UID " + text));
return;
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("Retrieved ZDO for UID: " + text));
ZNetView val3 = ZNetScene.instance.FindInstance(zDO);
if ((Object)(object)val3 == (Object)null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Cart with UID " + text + " was not found on the server."));
return;
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("Found cart instance for UID: " + text));
GameObject gameObject = ((Component)val3).gameObject;
if ((Object)(object)gameObject.GetComponent<Rigidbody>() == (Object)null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Cart object '" + ((Object)gameObject).name + "' has no Rigidbody."));
return;
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("Found Rigidbody for cart object: " + ((Object)gameObject).name));
((MonoBehaviour)this).StartCoroutine(FlipCartCoroutine(gameObject));
}
[IteratorStateMachine(typeof(<FlipCartCoroutine>d__18))]
private IEnumerator FlipCartCoroutine(GameObject cartObject)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <FlipCartCoroutine>d__18(0)
{
<>4__this = this,
cartObject = cartObject
};
}
public void RPC_SendModVersion(long sender, ZPackage pkg)
{
string text = pkg.ReadString();
((BaseUnityPlugin)this).Logger.LogInfo((object)("Server received mod version from client: " + text));
if (text != "1.0.1")
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Mod version mismatch! Server: 1.0.1 vs. Client: " + text));
if ((Object)(object)ZNet.instance != (Object)null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Disconnecting client: " + sender));
ZNetPeer peer = ZNet.instance.GetPeer(sender);
if (peer != null)
{
ZNet.instance.Disconnect(peer);
}
else
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Peer not found for sender: " + sender));
}
}
}
else
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Mod version match confirmed.");
}
}
public void RPC_RequestModVersion(long sender, ZPackage pkg)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
((BaseUnityPlugin)this).Logger.LogInfo((object)"Client received mod version request from server.");
ZPackage val = new ZPackage();
val.Write("1.0.1");
long num = ZDOIDToLong(((Component)Player.m_localPlayer).GetComponent<ZNetView>().GetZDO().m_uid);
ZRoutedRpc.instance.InvokeRoutedRPC(num, "RPC_SendModVersion", new object[1] { val });
((BaseUnityPlugin)this).Logger.LogInfo((object)"Client sent mod version: 1.0.1");
}
private void RequestModVersionFromAllPeers()
{
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected O, but got Unknown
try
{
FieldInfo field = typeof(ZNet).GetField("m_peers", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find the m_peers field on ZNet.");
return;
}
if (field.GetValue(ZNet.instance) is IEnumerable enumerable)
{
{
foreach (object item in enumerable)
{
try
{
FieldInfo field2 = item.GetType().GetField("m_uid", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field2 == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find m_uid on a peer.");
continue;
}
long num = (long)field2.GetValue(item);
ZPackage val = new ZPackage();
ZRoutedRpc.instance.InvokeRoutedRPC(num, "RPC_RequestModVersion", new object[1] { val });
((BaseUnityPlugin)this).Logger.LogInfo((object)("Server requested mod version from peer: " + num));
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to request mod version from a peer: " + ex.Message));
}
}
return;
}
}
((BaseUnityPlugin)this).Logger.LogWarning((object)"m_peers field did not return an enumerable.");
}
catch (Exception ex2)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Exception in RequestModVersionFromAllPeers: " + ex2.Message));
}
}
private bool IsServer()
{
if ((Object)(object)ZNet.instance != (Object)null)
{
return ZNet.instance.IsServer();
}
return false;
}
}
[HarmonyPatch(typeof(Vagon), "GetHoverText")]
public static class Vagon_GetHoverText_Patch
{
private static void Postfix(Vagon __instance, ref string __result)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: 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)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
if (__instance != null && (Object)(object)((Component)__instance).transform != (Object)null && ((Object)((Component)__instance).transform).name.Contains("Cart") && Vector3.Angle(((Component)__instance).transform.up, Vector3.up) > 90f)
{
string obj = __result;
KeyCode configFlipKey = CartFlipper.ConfigFlipKey;
__result = obj + "\n[<color=yellow><b>" + ((object)(KeyCode)(ref configFlipKey)).ToString() + "</b></color>] Flip";
}
}
}