using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CleanerCasinoUX.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.UI;
[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("CleanerCasinoUX")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.1.0")]
[assembly: AssemblyInformationalVersion("0.3.1+b976f5f8628a07bfe8cd978ee2c216333282d5e7")]
[assembly: AssemblyProduct("CleanerCasinoUX")]
[assembly: AssemblyTitle("CleanerCasinoUX")]
[assembly: AssemblyVersion("0.3.1.0")]
[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 CleanerCasinoUX
{
[BepInPlugin("com.saltedbyte.cleanercasinoux", "CleanerCasinoUX", "0.3.0")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.saltedbyte.cleanercasinoux";
public const string PluginName = "CleanerCasinoUX";
public const string PluginVersion = "0.3.0";
internal static ManualLogSource Log = null;
internal static ConfigEntry<bool> RelocateMoneyPopup = null;
internal static ConfigEntry<float> MoneyPopupMarginX = null;
internal static ConfigEntry<float> MoneyPopupMarginY = null;
internal static ConfigEntry<bool> DisableRoamingNPCs = null;
internal static ConfigEntry<bool> NPCsIgnoreInteractRays = null;
private static readonly Type[] PatchClasses = new Type[6]
{
typeof(MoneyDisplay_BuildContainer),
typeof(MoneyDisplay_ReparentPopup),
typeof(NPC_DestroyOnStartServer),
typeof(NPCSpawner_SkipSpawnAll),
typeof(NPCSpawner_SkipSpawnFloor),
typeof(PlayerInteract_FilterNPCRaycasts)
};
private void Awake()
{
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
BindConfig();
Log.LogInfo((object)"CleanerCasinoUX v0.3.0 loaded.");
Log.LogInfo((object)$" RelocateMoneyPopup = {RelocateMoneyPopup.Value} (margin {MoneyPopupMarginX.Value}, {MoneyPopupMarginY.Value})");
Log.LogInfo((object)$" DisableRoamingNPCs = {DisableRoamingNPCs.Value}");
Log.LogInfo((object)$" NPCsIgnoreInteractRays = {NPCsIgnoreInteractRays.Value}");
Harmony val = new Harmony("com.saltedbyte.cleanercasinoux");
int num = 0;
Type[] patchClasses = PatchClasses;
foreach (Type type in patchClasses)
{
try
{
val.CreateClassProcessor(type).Patch();
Log.LogInfo((object)(" ✔ patched " + type.Name));
num++;
}
catch (Exception arg)
{
Log.LogError((object)$" ✘ FAILED to patch {type.Name}: {arg}");
}
}
Log.LogInfo((object)$"Harmony patches applied: {num}/{PatchClasses.Length}");
}
private void BindConfig()
{
RelocateMoneyPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("MoneyPopup", "Relocate", true, "Move the friends-earned/lost-money popup from the center of the screen to the bottom-left, so it stops covering the table you're playing at. Same content and animation, just a different anchor.");
MoneyPopupMarginX = ((BaseUnityPlugin)this).Config.Bind<float>("MoneyPopup", "MarginX", 32f, "Pixels of padding from the LEFT edge of the screen to the popup anchor. Increase if the popup is clipping into the casino HUD on the left.");
MoneyPopupMarginY = ((BaseUnityPlugin)this).Config.Bind<float>("MoneyPopup", "MarginY", 32f, "Pixels of padding from the BOTTOM edge of the screen to the popup anchor. Increase to push the popup further up.");
DisableRoamingNPCs = ((BaseUnityPlugin)this).Config.Bind<bool>("NPCs", "DisableRoaming", true, "Skip the casino's NPC spawn entirely on the host. With no roaming NPCs, no one walks in front of the table you're trying to click. Host-only effect — Mirror replicates the empty state to all clients automatically. Only the host needs the mod for this to take effect.");
NPCsIgnoreInteractRays = ((BaseUnityPlugin)this).Config.Bind<bool>("NPCs", "IgnoreInteractRays", false, "When DisableRoaming is OFF, you can enable this instead: NPCs no longer block your interact raycast (the one that highlights cash-out buttons etc.). NPCs still physically collide with you and walk around for atmosphere, but clicks pass through them. Has no effect when DisableRoaming is ON, since there are no NPCs to filter.");
}
}
internal static class PopupContainer
{
private static RectTransform _container;
private static Canvas _canvas;
public static RectTransform GetOrCreate(MoneyDisplayAndFeedbacks instance)
{
//IL_008e: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Expected O, but got Unknown
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_container != (Object)null)
{
return _container;
}
object? value = AccessTools.Field(typeof(MoneyDisplayAndFeedbacks), "feedbackParent").GetValue(instance);
Transform val = (Transform)((value is Transform) ? value : null);
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"[MoneyPopup] feedbackParent is null — can't anchor a custom container.");
return null;
}
_canvas = ((Component)val).GetComponentInParent<Canvas>();
if ((Object)(object)_canvas == (Object)null)
{
Plugin.Log.LogWarning((object)"[MoneyPopup] no Canvas in feedbackParent's parent chain — can't anchor a custom container.");
return null;
}
GameObject val2 = new GameObject("CleanerCasinoUX_PopupContainer", new Type[1] { typeof(RectTransform) });
RectTransform component = val2.GetComponent<RectTransform>();
((Transform)component).SetParent(((Component)_canvas).transform, false);
component.anchorMin = Vector2.zero;
component.anchorMax = Vector2.zero;
component.pivot = Vector2.zero;
component.sizeDelta = new Vector2(600f, 800f);
component.anchoredPosition = new Vector2(Plugin.MoneyPopupMarginX.Value, Plugin.MoneyPopupMarginY.Value);
VerticalLayoutGroup obj = val2.AddComponent<VerticalLayoutGroup>();
((LayoutGroup)obj).childAlignment = (TextAnchor)6;
((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false;
((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false;
((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f;
((LayoutGroup)obj).padding = new RectOffset(0, 0, 0, 0);
_container = component;
Plugin.Log.LogInfo((object)$"[MoneyPopup] created custom container under canvas '{((Object)_canvas).name}' (renderMode={_canvas.renderMode}) at bottom-left ({Plugin.MoneyPopupMarginX.Value}, {Plugin.MoneyPopupMarginY.Value}).");
return _container;
}
}
}
namespace CleanerCasinoUX.Patches
{
[HarmonyPatch(typeof(MoneyDisplayAndFeedbacks), "Start")]
internal static class MoneyDisplay_BuildContainer
{
[HarmonyPostfix]
private static void Postfix(MoneyDisplayAndFeedbacks __instance)
{
if (Plugin.RelocateMoneyPopup.Value)
{
PopupContainer.GetOrCreate(__instance);
}
}
}
[HarmonyPatch(typeof(MoneyDisplayAndFeedbacks), "SpawnMoneyChangeText")]
internal static class MoneyDisplay_ReparentPopup
{
[HarmonyPostfix]
private static void Postfix(MoneyDisplayAndFeedbacks __instance)
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.RelocateMoneyPopup.Value)
{
return;
}
RectTransform orCreate = PopupContainer.GetOrCreate(__instance);
if ((Object)(object)orCreate == (Object)null)
{
return;
}
object? value = AccessTools.Field(typeof(MoneyDisplayAndFeedbacks), "feedbackParent").GetValue(__instance);
Transform val = (Transform)((value is Transform) ? value : null);
if ((Object)(object)val == (Object)null)
{
return;
}
List<Transform> list = new List<Transform>(val.childCount);
for (int i = 0; i < val.childCount; i++)
{
list.Add(val.GetChild(i));
}
foreach (Transform item in list)
{
item.SetParent((Transform)(object)orCreate, false);
RectTransform val2 = (RectTransform)(object)((item is RectTransform) ? item : null);
if (val2 != null)
{
val2.anchorMin = Vector2.zero;
val2.anchorMax = Vector2.zero;
val2.pivot = Vector2.zero;
((Transform)val2).localScale = Vector3.one;
}
}
}
}
[HarmonyPatch(typeof(NPCSpawner), "SpawnAllCoroutine")]
internal static class NPCSpawner_SkipSpawnAll
{
private static IEnumerator Empty()
{
yield break;
}
[HarmonyPrefix]
private static bool Prefix(ref IEnumerator __result)
{
if (!Plugin.DisableRoamingNPCs.Value)
{
return true;
}
__result = Empty();
return false;
}
}
[HarmonyPatch(typeof(NPCSpawner), "SpawnNPCsForFloor")]
internal static class NPCSpawner_SkipSpawnFloor
{
private static IEnumerator Empty()
{
yield break;
}
[HarmonyPrefix]
private static bool Prefix(ref IEnumerator __result)
{
if (!Plugin.DisableRoamingNPCs.Value)
{
return true;
}
__result = Empty();
return false;
}
}
[HarmonyPatch(typeof(NPC), "OnStartServer")]
internal static class NPC_DestroyOnStartServer
{
[HarmonyPostfix]
private static void Postfix(NPC __instance)
{
if (Plugin.DisableRoamingNPCs.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).gameObject == (Object)null))
{
Plugin.Log.LogInfo((object)("[NPCs] destroying NPC '" + ((Object)__instance).name + "' on server."));
NetworkServer.Destroy(((Component)__instance).gameObject);
}
}
}
[HarmonyPatch(typeof(PlayerInteract), "RaycastInteractable")]
internal static class PlayerInteract_FilterNPCRaycasts
{
private static readonly FieldInfo CamField = AccessTools.Field(typeof(PlayerInteract), "_cam");
private static readonly FieldInfo HitsField = AccessTools.Field(typeof(PlayerInteract), "_hits");
private static readonly MethodInfo SetTargetInteractableMethod = AccessTools.Method(typeof(PlayerInteract), "SetTargetInteractable", (Type[])null, (Type[])null);
[HarmonyPrefix]
private static bool Prefix(PlayerInteract __instance)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.NPCsIgnoreInteractRays.Value)
{
return true;
}
object? value = CamField.GetValue(__instance);
Camera val = (Camera)((value is Camera) ? value : null);
RaycastHit[] array = HitsField.GetValue(__instance) as RaycastHit[];
if ((Object)(object)val == (Object)null || array == null)
{
return true;
}
int num = Physics.SphereCastNonAlloc(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), __instance.raycastRadius, array, __instance.raycastDistance, LayerMask.op_Implicit(__instance.raycastLayer));
Array.Sort(array, 0, num, Comparer<RaycastHit>.Create((RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)));
IInteractable val2 = null;
float num2 = float.MaxValue;
float num3 = __instance.raycastDistance + 1f;
IInteractable val4 = default(IInteractable);
for (int i = 0; i < num; i++)
{
RaycastHit val3 = array[i];
if ((Object)(object)((RaycastHit)(ref val3)).transform == (Object)(object)((Component)__instance).transform || (Object)(object)((Component)((RaycastHit)(ref val3)).transform).GetComponentInParent<NPC>() != (Object)null)
{
continue;
}
if (((RaycastHit)(ref val3)).distance > num3 + __instance.raycastBlockThreshold)
{
break;
}
if (((Component)((RaycastHit)(ref val3)).transform).TryGetComponent<IInteractable>(ref val4))
{
Vector3 val5 = ((RaycastHit)(ref val3)).transform.position - ((Component)val).transform.position;
float num4 = Vector3.Angle(((Component)val).transform.forward, val5);
if (num4 < num2)
{
num2 = num4;
val2 = val4;
}
}
if (!((RaycastHit)(ref val3)).collider.isTrigger && num3 >= __instance.raycastDistance)
{
num3 = ((RaycastHit)(ref val3)).distance;
}
}
SetTargetInteractableMethod.Invoke(__instance, new object[1] { val2 });
return false;
}
}
}