using System; using System.Collections; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("EmergencyDiceREPOEDFixed")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("EmergencyDiceREPOEDFixed")] [assembly: AssemblyTitle("EmergencyDiceREPOEDFixed")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 Matsu.EmergencyDiceREPOEDFixed { [BepInPlugin("matsu.repo.emergency_dice_fixed", "Emergency Dice REPOED Fixed", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public static ManualLogSource? Log; private static FieldInfo? _f_isRolling; private static FieldInfo? _f_itemToggle; private static FieldInfo? _f_prevToggleState; private static FieldInfo? _f_rolledFromE; private static FieldInfo? _f_physGrabObject; private static FieldInfo? _f_view; private static FieldInfo? _f_rb; private static FieldInfo? _f_lastHolder; private static MethodInfo? _m_blockPickupAndRollRPC; private static FieldInfo? _f_toggleState; private static FieldInfo? _f_grabbed; private static FieldInfo? _f_playerGrabbing; private static FieldInfo? _f_playerAvatar; private static FieldInfo? _f_rmStaticInstance; private static FieldInfo? _f_levelIsShop; private static Type? _t_runManager; private static MethodInfo? _m_isMaster; private static FieldInfo? _f_throwSpeed; private static MethodInfo? _m_photonRPC; private static Type? _t_rpcTarget; private static object? _v_masterClient; private static PropertyInfo? _p_effectName; private static MethodInfo? _m_isMultiplayer; private static Type? _t_instantReroll; private static FieldInfo? _f_effects; private static FieldInfo? _f_fromRainbow; private static MethodInfo? _m_getRandomEffect; private static MethodInfo? _m_explode; private static FieldInfo? _f_networkerInstance; private static MethodInfo? _m_logToAllRPC; private static MethodInfo? _m_effectUse; private static PropertyInfo? _p_effectTooltip; private static FieldInfo? _f_spoilerMode; private static PropertyInfo? _p_punPhotonView; private static object? _v_others; private static object? _v_all; private static PropertyInfo? _p_inRoom; private static Assembly? _asm_repoDice; private static bool _rpcEmulatorPatched; private static MethodInfo? _m_chatMessageSend; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; new Harmony("matsu.repo.emergency_dice_fixed").PatchAll(); HookRepoDiceLoad(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Emergency Dice REPOED Fixed v1.0.2 loaded."); } private void HookRepoDiceLoad() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == "RepoDice") { ApplyPatch(assembly); return; } } AppDomain.CurrentDomain.AssemblyLoad += delegate(object _, AssemblyLoadEventArgs args) { if (args.LoadedAssembly.GetName().Name == "RepoDice") { ApplyPatch(args.LoadedAssembly); } }; } private static FieldInfo? FindField(Type t, string name) { Type type = t; while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } private static void ApplyPatch(Assembly repoDiceAsm) { //IL_05c0: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Expected O, but got Unknown //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Expected O, but got Unknown //IL_0688: Unknown result type (might be due to invalid IL or missing references) //IL_0691: Unknown result type (might be due to invalid IL or missing references) //IL_069f: Expected O, but got Unknown //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Expected O, but got Unknown //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Expected O, but got Unknown try { _m_chatMessageSend = AccessTools.TypeByName("PlayerAvatar")?.GetMethod("ChatMessageSend", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); ManualLogSource? log = Log; if (log != null) { log.LogInfo((object)((_m_chatMessageSend != null) ? "[Fixed] PlayerAvatar.ChatMessageSend resolved — dice results will be spoken by the roller." : "[Fixed] PlayerAvatar.ChatMessageSend NOT FOUND — dice chat will silently no-op.")); } Type type = repoDiceAsm.GetType("RepoDice.Dice.DieBehaviour"); if (type == null) { ManualLogSource? log2 = Log; if (log2 != null) { log2.LogWarning((object)"[Fixed] DieBehaviour type not found"); } return; } _f_isRolling = FindField(type, "isRolling"); _f_itemToggle = FindField(type, "itemToggle"); _f_prevToggleState = FindField(type, "prevToggleState"); _f_rolledFromE = FindField(type, "rolledFromE"); _f_physGrabObject = FindField(type, "physGrabObject"); _f_view = FindField(type, "view"); _f_rb = FindField(type, "rb"); _f_lastHolder = FindField(type, "lastHolder"); _m_blockPickupAndRollRPC = type.GetMethod("BlockPickupAndRollRPC", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Type type2 = _f_itemToggle?.FieldType; if (type2 != null) { _f_toggleState = FindField(type2, "toggleState"); } Type type3 = _f_physGrabObject?.FieldType; if (type3 != null) { _f_grabbed = FindField(type3, "grabbed"); _f_playerGrabbing = FindField(type3, "playerGrabbing"); } _t_runManager = AccessTools.TypeByName("RunManager"); if (_t_runManager != null) { _f_rmStaticInstance = _t_runManager.GetField("instance", BindingFlags.Static | BindingFlags.Public) ?? _t_runManager.GetField("Instance", BindingFlags.Static | BindingFlags.Public); _f_levelIsShop = _t_runManager.GetField("levelIsShop", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } Type type4 = AccessTools.TypeByName("SemiFunc"); if (type4 != null) { _m_isMaster = type4.GetMethod("IsMasterClientOrSingleplayer", BindingFlags.Static | BindingFlags.Public); _m_isMultiplayer = type4.GetMethod("IsMultiplayer", BindingFlags.Static | BindingFlags.Public); } Type type5 = repoDiceAsm.GetType("RepoDice.RepoDice"); if (type5 != null) { _f_throwSpeed = type5.GetField("throwSpeed", BindingFlags.Static | BindingFlags.Public); _f_spoilerMode = type5.GetField("SpoilerMode", BindingFlags.Static | BindingFlags.Public); } _t_rpcTarget = AccessTools.TypeByName("Photon.Pun.RpcTarget"); _v_masterClient = ((_t_rpcTarget != null) ? Enum.Parse(_t_rpcTarget, "MasterClient") : null); _v_others = ((_t_rpcTarget != null) ? Enum.Parse(_t_rpcTarget, "Others") : null); _v_all = ((_t_rpcTarget != null) ? Enum.Parse(_t_rpcTarget, "All") : null); _p_inRoom = AccessTools.TypeByName("Photon.Pun.PhotonNetwork")?.GetProperty("InRoom", BindingFlags.Static | BindingFlags.Public); _asm_repoDice = repoDiceAsm; Type type6 = _f_view?.FieldType; if (type6 != null) { _m_photonRPC = type6.GetMethod("RPC", new Type[3] { typeof(string), _t_rpcTarget, typeof(object[]) }); } Type type7 = repoDiceAsm.GetType("RepoDice.Effects.IEffect"); if (type7 != null) { _p_effectName = type7.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public); _p_effectTooltip = type7.GetProperty("Tooltip", BindingFlags.Instance | BindingFlags.Public); _m_effectUse = type7.GetMethod("Use", BindingFlags.Instance | BindingFlags.Public); } _t_instantReroll = repoDiceAsm.GetType("RepoDice.Effects.InstantReroll"); _f_effects = FindField(type, "Effects"); _f_fromRainbow = FindField(type, "fromRainbow"); _m_getRandomEffect = type.GetMethod("GetRandomEffect", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _m_explode = type.GetMethod("explodeMachoAndGlitch", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Type type8 = repoDiceAsm.GetType("RepoDice.Networker"); if (type8 != null) { _f_networkerInstance = type8.GetField("Instance", BindingFlags.Static | BindingFlags.Public) ?? type8.GetField("instance", BindingFlags.Static | BindingFlags.Public); _m_logToAllRPC = type8.GetMethod("LogToAllRPC", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _p_punPhotonView = type8.GetProperty("photonView", BindingFlags.Instance | BindingFlags.Public); } MethodInfo method = type.GetMethod("FixedUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { MethodInfo method2 = typeof(Plugin).GetMethod("DieBehaviourFixedUpdatePrefix", BindingFlags.Static | BindingFlags.NonPublic); new Harmony("matsu.repo.emergency_dice_fixed.fixedupdate").Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ManualLogSource? log3 = Log; if (log3 != null) { log3.LogInfo((object)"[Fixed] DieBehaviour.FixedUpdate patched."); } } if (type7 != null) { MethodInfo method3 = typeof(Plugin).GetMethod("IEffectUsePrefix", BindingFlags.Static | BindingFlags.NonPublic); Harmony val = new Harmony("matsu.repo.emergency_dice_fixed.effectchat"); int num = 0; Type[] types = repoDiceAsm.GetTypes(); foreach (Type type9 in types) { if (type9.IsAbstract || type9.IsInterface || !type7.IsAssignableFrom(type9)) { continue; } MethodInfo method4 = type9.GetMethod("Use", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method4 == null)) { try { val.Patch((MethodBase)method4, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } } ManualLogSource? log4 = Log; if (log4 != null) { log4.LogInfo((object)$"[Fixed] Patched {num} IEffect.Use() implementations for chat messages."); } } MethodInfo method5 = type.GetMethod("Roll", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method5 != null) { MethodInfo method6 = typeof(Plugin).GetMethod("DieBehaviourRollPrefix", BindingFlags.Static | BindingFlags.NonPublic); new Harmony("matsu.repo.emergency_dice_fixed.roll").Patch((MethodBase)method5, new HarmonyMethod(method6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ManualLogSource? log5 = Log; if (log5 != null) { log5.LogInfo((object)"[Fixed] DieBehaviour.Roll patched (SP + MP fixes)."); } } if (_rpcEmulatorPatched || !(_f_view?.FieldType != null) || !(_t_rpcTarget != null)) { return; } MethodInfo method7 = _f_view.FieldType.GetMethod("RPC", new Type[3] { typeof(string), _t_rpcTarget, typeof(object[]) }); if (method7 != null) { MethodInfo method8 = typeof(Plugin).GetMethod("PhotonViewRpcPrefix", BindingFlags.Static | BindingFlags.NonPublic); new Harmony("matsu.repo.emergency_dice_fixed.sprpc").Patch((MethodBase)method7, new HarmonyMethod(method8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _rpcEmulatorPatched = true; ManualLogSource? log6 = Log; if (log6 != null) { log6.LogInfo((object)"[Fixed] PhotonView.RPC singleplayer emulator installed (RepoDice-scoped)."); } } } catch (Exception arg) { ManualLogSource? log7 = Log; if (log7 != null) { log7.LogError((object)$"[Fixed] ApplyPatch failed: {arg}"); } } } private static bool DieBehaviourRollPrefix(object __instance) { try { bool flag = _m_isMultiplayer != null && (bool)(_m_isMultiplayer.Invoke(null, null) ?? ((object)false)); int num = Random.Range(1, 7); IList list = _f_effects?.GetValue(__instance) as IList; object obj = _m_getRandomEffect?.Invoke(__instance, new object[2] { num, list }); if (obj == null) { return false; } bool flag2 = _f_fromRainbow != null && (bool)(_f_fromRainbow.GetValue(__instance) ?? ((object)false)); if (_t_instantReroll != null && _t_instantReroll.IsInstanceOfType(obj) && flag2) { int num2 = Math.Min(num + 1, 6); obj = _m_getRandomEffect?.Invoke(__instance, new object[2] { num2, list }) ?? obj; if (obj == null) { return false; } } object obj2 = _f_networkerInstance?.GetValue(null); if (obj2 != null && _m_logToAllRPC != null) { string text = (_p_effectName?.GetValue(obj) as string) ?? "?"; if (flag && _p_punPhotonView != null && _m_photonRPC != null && _v_others != null) { try { object value = _p_punPhotonView.GetValue(obj2); if (value != null) { _m_photonRPC.Invoke(value, new object[3] { "LogToAllRPC", _v_others, new object[1] { "Rolling " + text } }); } } catch { } } _m_logToAllRPC.Invoke(obj2, new object[1] { "Rolling " + text }); } object obj4 = _f_lastHolder?.GetValue(__instance); _m_effectUse?.Invoke(obj, new object[1] { obj4 }); try { _m_explode?.Invoke(__instance, new object[1] { 1 }); } catch { } } catch (Exception arg) { ManualLogSource? log = Log; if (log != null) { log.LogError((object)$"[Fixed] DieBehaviourRollPrefix error: {arg}"); } } return false; } private static void IEffectUsePrefix(object __instance, object __0) { try { if (_p_effectName == null) { ManualLogSource? log = Log; if (log != null) { log.LogWarning((object)"[Fixed] Dice chat: IEffect.Name property missing."); } return; } string text = _p_effectName.GetValue(__instance) as string; if (string.IsNullOrEmpty(text)) { return; } string text2 = text; try { bool flag = true; if (_f_spoilerMode?.GetValue(null) is ConfigEntry val) { flag = val.Value; } if (!flag) { string text3 = _p_effectTooltip?.GetValue(__instance) as string; if (!string.IsNullOrEmpty(text3)) { text2 = text3; } } } catch { } if (__0 == null) { ManualLogSource? log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Fixed] Dice chat: no roller (lastHolder is null) — '" + text2 + "' not spoken.")); } return; } if (_m_chatMessageSend == null) { ManualLogSource? log3 = Log; if (log3 != null) { log3.LogWarning((object)("[Fixed] Dice chat: ChatMessageSend not resolved — '" + text2 + "' not spoken.")); } return; } _m_chatMessageSend.Invoke(__0, new object[1] { text2 }); ManualLogSource? log4 = Log; if (log4 != null) { log4.LogInfo((object)("[Fixed] Dice chat: '" + text2 + "' spoken by the roller.")); } } catch (Exception ex) { ManualLogSource? log5 = Log; if (log5 != null) { log5.LogError((object)("[Fixed] Dice chat error: " + (ex.InnerException?.Message ?? ex.Message))); } } } private static bool PhotonViewRpcPrefix(object __instance, object[] __args) { try { if (_p_inRoom == null || (bool)(_p_inRoom.GetValue(null) ?? ((object)false))) { return true; } Component val = (Component)((__instance is Component) ? __instance : null); if ((Object)(object)val == (Object)null) { return true; } MonoBehaviour[] components = val.GetComponents(); bool flag = false; MonoBehaviour[] array = components; foreach (MonoBehaviour val2 in array) { if (!((Object)(object)val2 == (Object)null)) { Type type = ((object)val2).GetType(); if ((_asm_repoDice != null && type.Assembly == _asm_repoDice) || type.Name == "PlayerAvatar") { flag = true; break; } } } if (!flag) { return true; } string text = ((__args.Length != 0) ? (__args[0] as string) : null); string text2 = ((__args.Length <= 1) ? "" : (__args[1]?.ToString() ?? "")); object[] array2 = ((__args.Length > 2) ? (__args[2] as object[]) : null) ?? Array.Empty(); if (string.IsNullOrEmpty(text)) { return true; } if (text2.Contains("Others")) { return false; } array = components; foreach (MonoBehaviour val3 in array) { if ((Object)(object)val3 == (Object)null) { continue; } Type type2 = ((object)val3).GetType(); while (type2 != null) { MethodInfo[] methods = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != text) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); try { if (parameters.Length == array2.Length) { methodInfo.Invoke(val3, array2); return false; } if (parameters.Length == array2.Length + 1 && parameters[^1].ParameterType.Name == "PhotonMessageInfo") { object[] array3 = new object[array2.Length + 1]; Array.Copy(array2, array3, array2.Length); array3[array2.Length] = Activator.CreateInstance(parameters[^1].ParameterType); methodInfo.Invoke(val3, array3); return false; } } catch (Exception ex) { ManualLogSource? log = Log; if (log != null) { log.LogWarning((object)("[Fixed] SP-RPC '" + text + "' local invoke failed: " + (ex.InnerException?.Message ?? ex.Message))); } return false; } } type2 = type2.BaseType; } } return false; } catch { return true; } } private static bool DieBehaviourFixedUpdatePrefix(object __instance) { //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) if (__instance == null) { return true; } bool flag = _f_isRolling != null && (bool)(_f_isRolling.GetValue(__instance) ?? ((object)false)); bool flag2 = false; if (_f_rmStaticInstance != null && _f_levelIsShop != null) { try { object value = _f_rmStaticInstance.GetValue(null); if (value != null) { flag2 = (bool)(_f_levelIsShop.GetValue(value) ?? ((object)false)); } } catch { flag2 = false; } } if (flag || flag2) { return false; } object obj2 = _f_itemToggle?.GetValue(__instance); bool flag3 = _f_prevToggleState != null && (bool)(_f_prevToggleState.GetValue(__instance) ?? ((object)false)); bool flag4 = false; if (obj2 != null && _f_toggleState != null) { flag4 = (bool)(_f_toggleState.GetValue(obj2) ?? ((object)false)); } object obj3 = _f_physGrabObject?.GetValue(__instance); object view = _f_view?.GetValue(__instance); object? obj4 = _f_rb?.GetValue(__instance); Rigidbody val = (Rigidbody)((obj4 is Rigidbody) ? obj4 : null); bool isMaster = !(_m_isMaster != null) || (bool)(_m_isMaster.Invoke(null, null) ?? ((object)true)); if (obj2 != null && flag4 != flag3) { _f_isRolling?.SetValue(__instance, true); _f_rolledFromE?.SetValue(__instance, true); TriggerBlockPickupAndRoll(__instance, view, isMaster); } _f_prevToggleState?.SetValue(__instance, flag4); bool flag5 = false; object obj5 = null; if (obj3 != null) { flag5 = _f_grabbed != null && (bool)(_f_grabbed.GetValue(obj3) ?? ((object)false)); if (_f_playerGrabbing?.GetValue(obj3) is IList { Count: 1 } list && list[0] != null) { object obj6 = list[0]; if (_f_playerAvatar == null) { _f_playerAvatar = FindField(obj6.GetType(), "playerAvatar"); } obj5 = _f_playerAvatar?.GetValue(obj6); } } object obj7 = _f_lastHolder?.GetValue(__instance); if (obj5 != null && obj7 != obj5) { _f_lastHolder?.SetValue(__instance, obj5); return false; } if (flag || flag5) { return false; } if ((Object)(object)val != (Object)null) { float num = 8f; if (_f_throwSpeed != null && _f_throwSpeed.GetValue(null) is ConfigEntry val2) { num = val2.Value; } Vector3 velocity = val.velocity; if (((Vector3)(ref velocity)).magnitude > num) { _f_isRolling?.SetValue(__instance, true); TriggerBlockPickupAndRoll(__instance, view, isMaster); } } return false; } private static void TriggerBlockPickupAndRoll(object instance, object? view, bool isMaster) { if (isMaster) { _m_blockPickupAndRollRPC?.Invoke(instance, null); } else if (view != null && _m_photonRPC != null && _v_masterClient != null) { _m_photonRPC.Invoke(view, new object[3] { "BlockPickupAndRollRPC", _v_masterClient, Array.Empty() }); } } } }