Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Quads Slot Machine v1.2.3
plugins/SlotMachine.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DHack.Shared; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (Claude Code).")] [assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 SlotMachine { internal static class Look { private static readonly Dictionary<string, Material> Materials = new Dictionary<string, Material>(); private static readonly Dictionary<string, Color> Plain = new Dictionary<string, Color> { { "StoneDark", new Color(0.36f, 0.36f, 0.38f) }, { "Coal", new Color(0.15f, 0.15f, 0.17f) }, { "Parchment", new Color(0.9f, 0.82f, 0.63f) }, { "Ink", new Color(0.16f, 0.11f, 0.08f) }, { "Bone", new Color(0.92f, 0.89f, 0.8f) }, { "Red", new Color(0.66f, 0.1f, 0.08f) }, { "Gold", new Color(0.93f, 0.72f, 0.2f) }, { "Leather", new Color(0.42f, 0.26f, 0.13f) }, { "Glow", new Color(1f, 0.72f, 0.28f) }, { "Cream", new Color(0.95f, 0.92f, 0.84f) }, { "Black", new Color(0.06f, 0.06f, 0.07f) }, { "Green", new Color(0.18f, 0.5f, 0.25f) }, { "Blue", new Color(0.2f, 0.35f, 0.7f) }, { "Teal", new Color(0.25f, 0.75f, 0.8f) }, { "RedDark", new Color(0.38f, 0.05f, 0.05f) }, { "Chrome", new Color(0.78f, 0.8f, 0.84f) }, { "GlowB", new Color(1f, 0.45f, 0.2f) } }; private static readonly Dictionary<string, float> Glows = new Dictionary<string, float> { { "Glow", 1.1f }, { "GlowB", 1.1f }, { "Gold", 0.18f } }; private static Material Find(ZNetScene scene, string prefab, string material) { GameObject prefab2 = scene.GetPrefab(prefab); if ((Object)(object)prefab2 == (Object)null) { return null; } Renderer[] componentsInChildren = prefab2.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == material) { return val2; } } } return null; } internal static void Harvest(ZNetScene scene, Material fallbackBase) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Expected O, but got Unknown //IL_0338: 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_030c: Unknown result type (might be due to invalid IL or missing references) Materials.Clear(); Materials["Stone"] = Find(scene, "stone_wall_1x1", "stone_mat"); Materials["Planks"] = Find(scene, "wood_floor", "woodwall"); Materials["Dark"] = Find(scene, "darkwood_pole", "DarkWood_mat"); Materials["Iron"] = Find(scene, "iron_grate", "metalwall"); Material val = Find(scene, "piece_cauldron", "cauldron_chain"); Material val2 = (((Object)(object)val != (Object)null) ? val : fallbackBase); foreach (KeyValuePair<string, Color> item in Plain) { Material val3 = new Material(val2) { color = item.Value }; if (val3.HasProperty("_MainTex")) { val3.mainTexture = null; } if (Glows.TryGetValue(item.Key, out var value) && val3.HasProperty("_EmissionColor")) { val3.EnableKeyword("_EMISSION"); val3.SetColor("_EmissionColor", item.Value * value); } Materials[item.Key] = val3; } Texture2D val4 = Icon.LoadEmbedded("symbols.png"); for (int i = 0; i < 8; i++) { Material val5 = new Material(val2) { color = Color.white }; if ((Object)(object)val4 != (Object)null) { val5.mainTexture = (Texture)(object)val4; val5.mainTextureScale = new Vector2(0.125f, 1f); val5.mainTextureOffset = new Vector2((float)i / 8f, 0f); if (val5.HasProperty("_EmissionMap")) { val5.EnableKeyword("_EMISSION"); val5.SetTexture("_EmissionMap", (Texture)(object)val4); val5.SetTextureScale("_EmissionMap", new Vector2(0.125f, 1f)); val5.SetTextureOffset("_EmissionMap", new Vector2((float)i / 8f, 0f)); val5.SetColor("_EmissionColor", new Color(0.45f, 0.45f, 0.45f)); } } Materials["Sym" + i] = val5; } string[] array = new string[4] { "Stone", "Planks", "Dark", "Iron" }; foreach (string text in array) { if ((Object)(object)Materials[text] == (Object)null) { Materials[text] = new Material(val2) { color = (Color)(text switch { "Dark" => new Color(0.25f, 0.17f, 0.11f), "Planks" => new Color(0.5f, 0.34f, 0.2f), "Stone" => new Color(0.5f, 0.5f, 0.52f), _ => new Color(0.38f, 0.38f, 0.42f), }) }; } } Debug.Log((object)("[SlotMachine] materials: " + string.Join(", ", Materials.Select((KeyValuePair<string, Material> kv) => kv.Key + "=" + ((Object)kv.Value).name).ToArray()))); } internal static Material Of(string name) { if (!Materials.TryGetValue(name, out var value)) { return Materials.Values.FirstOrDefault(); } return value; } internal static void Clear() { Materials.Clear(); } } public class SlotMachinePiece : MonoBehaviour, Interactable, Hoverable { private const string KeyStart = "sm_t"; private const string KeyCells = "sm_r"; private const string KeyPay = "sm_w"; private const string KeyWho = "sm_who"; private const string KeyBet = "sm_bet"; private const string KeyPaid = "sm_paid"; private static readonly float[] StopAt = new float[3] { 1.7f, 2.4f, 3.1f }; private const float Total = 3.6f; private const float LeverTime = 0.7f; private ZNetView _nview; private readonly Transform[] _reels = (Transform[])(object)new Transform[3]; private Transform _lever; private readonly List<Renderer> _bulbsA = new List<Renderer>(); private readonly List<Renderer> _bulbsB = new List<Renderer>(); private int[] _shown = new int[3]; private string _shownText; private ZDOID _id = ZDOID.None; private long _spinSeen; private readonly Random _rng = new Random(); private static long _owedSpin; private static int _owedCoins; private static ZDOID _owedMachine = ZDOID.None; private static bool _owedPouring; private static long _settledSpin; private ZDO Zdo { get { if (!((Object)(object)_nview != (Object)null) || !_nview.IsValid()) { return null; } return _nview.GetZDO(); } } private static long NowMs { get { if (!((Object)(object)ZNet.instance != (Object)null)) { return 0L; } return (long)(ZNet.instance.GetTimeSeconds() * 1000.0); } } private bool Spinning { get { ZDO zdo = Zdo; if (zdo != null) { return NowMs - zdo.GetLong("sm_t", 0L) < 3800; } return false; } } internal static void PayOwed() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0131: 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_013b: 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) if (_owedCoins <= 0) { _owedSpin = 0L; _owedPouring = false; return; } Player localPlayer = Player.m_localPlayer; GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("Coins") : null); if ((Object)(object)localPlayer == (Object)null || (Object)(object)val == (Object)null) { return; } int num = _owedCoins; int owedCoins = _owedCoins; ZDO val2 = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(_owedMachine) : null); if (val2 != null && !_owedPouring) { if (val2.GetLong("sm_paid", 0L) == _owedSpin) { _owedCoins = 0; _owedSpin = 0L; return; } if (val2.IsOwner()) { val2.Set("sm_paid", _owedSpin); } } _settledSpin = _owedSpin; _owedCoins = 0; _owedSpin = 0L; _owedPouring = false; Inventory inventory = ((Humanoid)localPlayer).GetInventory(); int num2 = Mathf.Max(1, val.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize); while (num > 0) { int num3 = Mathf.Min(num, num2); num -= num3; if (inventory.CanAddItem(val, num3)) { inventory.AddItem(val, num3); } else { Object.Instantiate<GameObject>(val, ((Component)localPlayer).transform.position + Vector3.up, Quaternion.identity).GetComponent<ItemDrop>().SetStack(num3); } } ((Character)localPlayer).Message((MessageType)1, Translations.T("slotmachine_paid_owed", owedCoins), 0, (Sprite)null, false); } private void OnDestroy() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (_owedCoins > 0 && !((ZDOID)(ref _id)).IsNone() && _id == _owedMachine) { PayOwed(); } } private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "reel0") { _reels[0] = val; } else if (((Object)val).name == "reel1") { _reels[1] = val; } else if (((Object)val).name == "reel2") { _reels[2] = val; } else if (((Object)val).name == "lever") { _lever = val; } else if (((Object)val).name == "bulbA") { Renderer component = ((Component)val).GetComponent<Renderer>(); if ((Object)(object)component != (Object)null) { _bulbsA.Add(component); } } else if (((Object)val).name == "bulbB") { Renderer component2 = ((Component)val).GetComponent<Renderer>(); if ((Object)(object)component2 != (Object)null) { _bulbsB.Add(component2); } } } } private static int[] ParseCells(string s) { string[] array = (s ?? "").Split(new char[1] { ',' }); int[] array2 = new int[3]; for (int i = 0; i < 3; i++) { if (array.Length > i && int.TryParse(array[i], out var result)) { array2[i] = Mathf.Clamp(result, 0, 7); } } return array2; } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return false; } Player val = (Player)user; if (alt) { Plugin.NextBet(); ((Character)val).Message((MessageType)1, Translations.T("slotmachine_bet", Plugin.Bet.Value), 0, (Sprite)null, false); return true; } Pull(val); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } private void Pull(Player player) { //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) ZDO zdo = Zdo; if (zdo == null) { return; } if (Spinning) { ((Character)player).Message((MessageType)2, Translations.T("slotmachine_still_turning"), 0, (Sprite)null, false); return; } int value = Plugin.Bet.Value; Inventory inventory = ((Humanoid)player).GetInventory(); int num = Coins(inventory); if (num < value) { ((Character)player).Message((MessageType)2, Translations.T("slotmachine_need_coins", value), 0, (Sprite)null, false); return; } inventory.RemoveItem("$item_coins", value, -1, false); int num2 = num - Coins(inventory); if (num2 < value) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("Coins") : null); if (num2 > 0 && (Object)(object)val != (Object)null) { inventory.AddItem(val, num2); } ((Character)player).Message((MessageType)2, Translations.T("slotmachine_need_coins", value), 0, (Sprite)null, false); return; } int[] array = Payout.Roll(_rng); int num3 = Mathf.RoundToInt((float)(Payout.Multiplier(array) * value * Plugin.PayoutPercent.Value) / 100f); _nview.ClaimOwnership(); zdo.Set("sm_r", array[0] + "," + array[1] + "," + array[2]); zdo.Set("sm_w", num3); zdo.Set("sm_bet", value); zdo.Set("sm_who", ZDOMan.GetSessionID()); long nowMs = NowMs; zdo.Set("sm_t", nowMs); if (_owedCoins > 0) { PayOwed(); } _id = zdo.m_uid; _owedSpin = nowMs; _owedCoins = num3; _owedMachine = zdo.m_uid; _owedPouring = false; Effect(done: false); } private static int Coins(Inventory inv) { int num = 0; foreach (ItemData allItem in inv.GetAllItems()) { if (allItem.m_shared.m_name == "$item_coins") { num += allItem.m_stack; } } return num; } public string GetHoverText() { return Localization.instance.Localize(Translations.T("slotmachine_piece") + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Translations.T("slotmachine_pull", Plugin.Bet.Value) + "\n[<color=yellow><b>$KEY_AltPlace</b></color> + <color=yellow><b>$KEY_Use</b></color>] " + Translations.T("slotmachine_change_bet") + "\n<size=13>" + Payout.Summary() + "</size>"); } public string GetHoverName() { return Translations.T("slotmachine_piece"); } public float GetHoverOffset() { return 0f; } private void Update() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) ZDO zdo = Zdo; if (zdo == null) { return; } _id = zdo.m_uid; long num = zdo.GetLong("sm_t", 0L); float num2 = ((num == 0L) ? 999f : ((float)(NowMs - num) / 1000f)); string text = zdo.GetString("sm_r", "0,0,0"); if (text != _shownText) { _shownText = text; _shown = ParseCells(text); } int[] shown = _shown; for (int i = 0; i < 3; i++) { if (!((Object)(object)_reels[i] == (Object)null)) { float num3 = StopAt[i]; float num4 = -45f * (float)shown[i]; if (num2 >= 0f && num2 < num3) { num4 += 360f * (float)(5 + i) * (1f - Ease(num2 / num3)); } _reels[i].localRotation = Quaternion.Euler(num4, 0f, 0f); } } if ((Object)(object)_lever != (Object)null) { float num5 = ((num2 < 0f || num2 > 0.7f) ? 0f : ((num2 < 0.25f) ? (num2 / 0.25f) : (1f - (num2 - 0.25f) / 0.45f))); _lever.localRotation = Quaternion.Euler(-62f * Mathf.SmoothStep(0f, 1f, num5), 0f, 0f); } Lamps(num2, zdo.GetInt("sm_w", 0) > 0); Settle(zdo, num, num2, shown); } private static float Ease(float x) { x = Mathf.Clamp01(x); return 1f - (1f - x) * (1f - x) * (1f - x); } private void Lamps(float t, bool won) { bool flag = t >= 0f && t < 3.6f; bool flag2 = won && t >= 3.6f && t < 8.6f; float num = (flag ? 0.12f : (flag2 ? 0.18f : 0.9f)); bool flag3 = Mathf.FloorToInt(Time.time / num) % 2 == 0; foreach (Renderer item in _bulbsA) { if ((Object)(object)item != (Object)null) { item.enabled = flag2 || flag3; } } foreach (Renderer item2 in _bulbsB) { if ((Object)(object)item2 != (Object)null) { item2.enabled = (flag2 ? flag3 : (!flag3)); } } } private void Settle(ZDO zdo, long start, float t, int[] cells) { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if (start == 0L || t < 3.6f || _spinSeen == start) { return; } _spinSeen = start; if (t > 11.6f || zdo.GetLong("sm_who", 0L) != ZDOMan.GetSessionID() || zdo.GetLong("sm_paid", 0L) == start || _settledSpin == start) { return; } _nview.ClaimOwnership(); zdo.Set("sm_paid", start); _settledSpin = start; int num = zdo.GetInt("sm_w", 0); int num2 = zdo.GetInt("sm_bet", 0); Player localPlayer = Player.m_localPlayer; if (num <= 0) { if (_owedSpin == start) { _owedSpin = 0L; _owedCoins = 0; _owedPouring = false; } if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)1, Translations.T("slotmachine_no_luck"), 0, (Sprite)null, false); } return; } if (_owedSpin != start && _owedCoins > 0) { PayOwed(); } _owedSpin = start; _owedCoins = num; _owedMachine = zdo.m_uid; _owedPouring = true; bool flag = Payout.IsJackpot(cells); if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, Translations.T(flag ? "slotmachine_jackpot" : "slotmachine_win", num), 0, (Sprite)null, false); } Effect(done: true); ((MonoBehaviour)this).StartCoroutine(Spit(start)); } private IEnumerator Spit(long spin) { GameObject prefab = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("Coins") : null); if ((Object)(object)prefab == (Object)null) { PayOwed(); yield break; } int max = Mathf.Max(1, prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize); while (_owedSpin == spin && _owedPouring && _owedCoins > 0) { int num = Mathf.Min(_owedCoins, max); Vector3 val = ((Component)this).transform.TransformPoint(new Vector3(0f, 0.36f, -0.5f) * 0.82f); GameObject val2 = Object.Instantiate<GameObject>(prefab, val, Quaternion.identity); ItemDrop component = val2.GetComponent<ItemDrop>(); component.SetStack(num); _owedCoins -= num; if (_owedCoins <= 0) { _owedCoins = 0; _owedSpin = 0L; _owedPouring = false; } Rigidbody component2 = val2.GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.velocity = -((Component)this).transform.forward * Random.Range(1.2f, 1.8f) + Vector3.up * Random.Range(1f, 1.8f) + ((Component)this).transform.right * Random.Range(-0.5f, 0.5f); } Effect(done: false); yield return (object)new WaitForSeconds(0.08f); } } private void Effect(bool done) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_workbench") : null); CraftingStation val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<CraftingStation>() : null); if ((Object)(object)val2 != (Object)null) { (done ? val2.m_craftItemDoneEffects : val2.m_craftItemEffects).Create(((Component)this).transform.position + Vector3.up, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } } catch { } } } internal static class ModelBuilder { internal static GameObject Build(Transform parent, object[][] parts, int layer) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: 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) GameObject val = new GameObject("Model") { layer = layer }; val.transform.SetParent(parent, false); val.transform.localScale = Vector3.one * 0.82f; Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(); Vector3 localPosition = default(Vector3); Vector3 localScale = default(Vector3); Vector3 val2 = default(Vector3); Transform val3; GameObject val4; for (int i = 0; i < parts.Length; val4.transform.SetParent(val3, false), val4.transform.localPosition = localPosition, val4.transform.localRotation = Quaternion.Euler(val2), i++) { object[] array = parts[i]; string text = (string)array[0]; string text2 = (string)array[1]; string text3 = (string)array[2]; ((Vector3)(ref localPosition))..ctor((float)array[3], (float)array[4], (float)array[5]); ((Vector3)(ref localScale))..ctor((float)array[6], (float)array[7], (float)array[8]); ((Vector3)(ref val2))..ctor((float)array[9], (float)array[10], (float)array[11]); val3 = ((text3.Length > 0 && dictionary.TryGetValue(text3, out var value)) ? value : val.transform); int num; switch (text2) { case "Group": val4 = new GameObject(text) { layer = layer }; dictionary[text] = val4.transform; continue; default: num = 0; break; case "Quad": num = 5; break; case "Cylinder": num = 2; break; case "Cube": num = 3; break; } val4 = GameObject.CreatePrimitive((PrimitiveType)num); ((Object)val4).name = text; Object.DestroyImmediate((Object)(object)val4.GetComponent<Collider>()); val4.layer = layer; val4.GetComponent<Renderer>().sharedMaterial = Look.Of((string)array[12]); val4.transform.localScale = localScale; } return val; } } internal static class ModelData { internal const float Scale = 0.82f; internal static readonly object[][] Parts = new object[166][] { new object[13] { "plinth", "Cube", "", 0f, 0.07f, 0f, 1.22f, 0.14f, 0.96f, 0f, 0f, 0f, "Stone" }, new object[13] { "plinthEdge", "Cube", "", 0f, 0.15f, 0f, 1.14f, 0.03f, 0.88f, 0f, 0f, 0f, "StoneDark" }, new object[13] { "lower", "Cube", "", 0f, 0.58f, 0f, 1f, 0.86f, 0.8f, 0f, 0f, 0f, "Dark" }, new object[13] { "lowerFront", "Cube", "", 0f, 0.5f, -0.405f, 0.88f, 0.5f, 0.03f, 0f, 0f, 0f, "Planks" }, new object[13] { "plankLine", "Cube", "", -0.15f, 0.5f, -0.422f, 0.012f, 0.5f, 0.004f, 0f, 0f, 0f, "Dark" }, new object[13] { "plankLine", "Cube", "", 0.15f, 0.5f, -0.422f, 0.012f, 0.5f, 0.004f, 0f, 0f, 0f, "Dark" }, new object[13] { "plankLine", "Cube", "", 0.45f, 0.5f, -0.422f, 0.012f, 0.5f, 0.004f, 0f, 0f, 0f, "Dark" }, new object[13] { "lowerBand", "Cube", "", 0f, 0.28f, -0.41f, 0.94f, 0.05f, 0.04f, 0f, 0f, 0f, "Iron" }, new object[13] { "lowerBand", "Cube", "", 0f, 0.72f, -0.41f, 0.94f, 0.05f, 0.04f, 0f, 0f, 0f, "Iron" }, new object[13] { "rivet", "Sphere", "", -0.4f, 0.28f, -0.435f, 0.04f, 0.04f, 0.02f, 0f, 0f, 0f, "Gold" }, new object[13] { "rivet", "Sphere", "", -0.4f, 0.72f, -0.435f, 0.04f, 0.04f, 0.02f, 0f, 0f, 0f, "Gold" }, new object[13] { "rivet", "Sphere", "", 0.4f, 0.28f, -0.435f, 0.04f, 0.04f, 0.02f, 0f, 0f, 0f, "Gold" }, new object[13] { "rivet", "Sphere", "", 0.4f, 0.72f, -0.435f, 0.04f, 0.04f, 0.02f, 0f, 0f, 0f, "Gold" }, new object[13] { "trayOpening", "Cube", "", 0f, 0.36f, -0.41f, 0.62f, 0.22f, 0.03f, 0f, 0f, 0f, "Coal" }, new object[13] { "trayDoor", "Cube", "", 0f, 0.44f, -0.425f, 0.6f, 0.06f, 0.02f, 0f, 0f, 0f, "Iron" }, new object[13] { "trayFloor", "Cube", "", 0f, 0.255f, -0.5f, 0.66f, 0.03f, 0.26f, -8f, 0f, 0f, "Gold" }, new object[13] { "trayLip", "Cube", "", -0.32f, 0.29f, -0.5f, 0.03f, 0.09f, 0.26f, -8f, 0f, 0f, "Gold" }, new object[13] { "trayLip", "Cube", "", 0.32f, 0.29f, -0.5f, 0.03f, 0.09f, 0.26f, -8f, 0f, 0f, "Gold" }, new object[13] { "trayFront", "Cube", "", 0f, 0.27f, -0.63f, 0.66f, 0.06f, 0.03f, -8f, 0f, 0f, "Gold" }, new object[13] { "deck", "Cube", "", 0f, 1f, -0.47f, 1.06f, 0.46f, 0.06f, 25f, 0f, 0f, "Dark" }, new object[13] { "deckTrimLow", "Cube", "", 0f, 0.7955f, -0.5874f, 1.08f, 0.04f, 0.07f, 25f, 0f, 0f, "Gold" }, new object[13] { "deckTrimHigh", "Cube", "", 0f, 1.2214f, -0.3888f, 1.08f, 0.04f, 0.07f, 25f, 0f, 0f, "Gold" }, new object[13] { "deckPlate", "Cube", "", 0f, 1.0329f, -0.4933f, 0.94f, 0.36f, 0.012f, 25f, 0f, 0f, "Red" }, new object[13] { "button", "Cylinder", "", -0.3f, 0.9347f, -0.5666f, 0.13f, 0.03f, 0.13f, -65f, 0f, 0f, "Red" }, new object[13] { "buttonRing", "Cylinder", "", -0.3f, 0.9284f, -0.553f, 0.17f, 0.012f, 0.17f, -65f, 0f, 0f, "Gold" }, new object[13] { "button", "Cylinder", "", 0f, 0.9347f, -0.5666f, 0.13f, 0.03f, 0.13f, -65f, 0f, 0f, "Gold" }, new object[13] { "buttonRing", "Cylinder", "", 0f, 0.9284f, -0.553f, 0.17f, 0.012f, 0.17f, -65f, 0f, 0f, "Gold" }, new object[13] { "button", "Cylinder", "", 0.3f, 0.9347f, -0.5666f, 0.13f, 0.03f, 0.13f, -65f, 0f, 0f, "Green" }, new object[13] { "buttonRing", "Cylinder", "", 0.3f, 0.9284f, -0.553f, 0.17f, 0.012f, 0.17f, -65f, 0f, 0f, "Gold" }, new object[13] { "slotBezel", "Cube", "", 0f, 1.1096f, -0.4685f, 0.22f, 0.09f, 0.012f, 25f, 0f, 0f, "Gold" }, new object[13] { "slotCut", "Cube", "", 0f, 1.1139f, -0.4776f, 0.14f, 0.022f, 0.012f, 25f, 0f, 0f, "Black" }, new object[13] { "slotGlow", "Cube", "", 0f, 1.1686f, -0.4411f, 0.2f, 0.014f, 0.01f, 25f, 0f, 0f, "Glow" }, new object[13] { "neck", "Cube", "", 0f, 1.26f, -0.02f, 1f, 0.22f, 0.7f, 0f, 0f, 0f, "Dark" }, new object[13] { "upperTop", "Cube", "", 0f, 1.88f, 0f, 1.04f, 0.3f, 0.8f, 0f, 0f, 0f, "Dark" }, new object[13] { "upperSill", "Cube", "", 0f, 1.355f, 0f, 1.04f, 0.1f, 0.8f, 0f, 0f, 0f, "Dark" }, new object[13] { "upperSide", "Cube", "", -0.49f, 1.55f, 0f, 0.1f, 0.3f, 0.8f, 0f, 0f, 0f, "Dark" }, new object[13] { "upperSide", "Cube", "", 0.49f, 1.55f, 0f, 0.1f, 0.3f, 0.8f, 0f, 0f, 0f, "Dark" }, new object[13] { "upperBack", "Cube", "", 0f, 1.55f, 0.17f, 0.9f, 0.34f, 0.46f, 0f, 0f, 0f, "Dark" }, new object[13] { "windowBack", "Cube", "", 0f, 1.55f, -0.055f, 0.9f, 0.34f, 0.02f, 0f, 0f, 0f, "Black" }, new object[13] { "reel0", "Group", "", -0.3f, 1.55f, -0.12f, 1f, 1f, 1f, 0f, 0f, 0f, "" }, new object[13] { "core", "Cylinder", "reel0", 0f, 0f, 0f, 0.34f, 0.15f, 0.34f, 0f, 0f, 90f, "Coal" }, new object[13] { "face0", "Quad", "reel0", 0f, 0f, -0.19f, 0.27f, 0.159f, 1f, 0f, 0f, 0f, "Sym0" }, new object[13] { "face1", "Quad", "reel0", 0f, 0.1344f, -0.1344f, 0.27f, 0.159f, 1f, 45f, 0f, 0f, "Sym1" }, new object[13] { "face2", "Quad", "reel0", 0f, 0.19f, 0f, 0.27f, 0.159f, 1f, 90f, 0f, 0f, "Sym2" }, new object[13] { "face3", "Quad", "reel0", 0f, 0.1344f, 0.1344f, 0.27f, 0.159f, 1f, 135f, 0f, 0f, "Sym3" }, new object[13] { "face4", "Quad", "reel0", 0f, 0f, 0.19f, 0.27f, 0.159f, 1f, 180f, 0f, 0f, "Sym4" }, new object[13] { "face5", "Quad", "reel0", 0f, -0.1344f, 0.1344f, 0.27f, 0.159f, 1f, 225f, 0f, 0f, "Sym5" }, new object[13] { "face6", "Quad", "reel0", 0f, -0.19f, 0f, 0.27f, 0.159f, 1f, 270f, 0f, 0f, "Sym6" }, new object[13] { "face7", "Quad", "reel0", 0f, -0.1344f, -0.1344f, 0.27f, 0.159f, 1f, 315f, 0f, 0f, "Sym7" }, new object[13] { "rim", "Cylinder", "reel0", -0.145f, 0f, 0f, 0.4f, 0.014f, 0.4f, 0f, 0f, 90f, "Gold" }, new object[13] { "hub", "Cylinder", "reel0", -0.16f, 0f, 0f, 0.1f, 0.012f, 0.1f, 0f, 0f, 90f, "Iron" }, new object[13] { "rim", "Cylinder", "reel0", 0.145f, 0f, 0f, 0.4f, 0.014f, 0.4f, 0f, 0f, 90f, "Gold" }, new object[13] { "hub", "Cylinder", "reel0", 0.16f, 0f, 0f, 0.1f, 0.012f, 0.1f, 0f, 0f, 90f, "Iron" }, new object[13] { "reel1", "Group", "", 0f, 1.55f, -0.12f, 1f, 1f, 1f, 0f, 0f, 0f, "" }, new object[13] { "core", "Cylinder", "reel1", 0f, 0f, 0f, 0.34f, 0.15f, 0.34f, 0f, 0f, 90f, "Coal" }, new object[13] { "face0", "Quad", "reel1", 0f, 0f, -0.19f, 0.27f, 0.159f, 1f, 0f, 0f, 0f, "Sym0" }, new object[13] { "face1", "Quad", "reel1", 0f, 0.1344f, -0.1344f, 0.27f, 0.159f, 1f, 45f, 0f, 0f, "Sym1" }, new object[13] { "face2", "Quad", "reel1", 0f, 0.19f, 0f, 0.27f, 0.159f, 1f, 90f, 0f, 0f, "Sym2" }, new object[13] { "face3", "Quad", "reel1", 0f, 0.1344f, 0.1344f, 0.27f, 0.159f, 1f, 135f, 0f, 0f, "Sym3" }, new object[13] { "face4", "Quad", "reel1", 0f, 0f, 0.19f, 0.27f, 0.159f, 1f, 180f, 0f, 0f, "Sym4" }, new object[13] { "face5", "Quad", "reel1", 0f, -0.1344f, 0.1344f, 0.27f, 0.159f, 1f, 225f, 0f, 0f, "Sym5" }, new object[13] { "face6", "Quad", "reel1", 0f, -0.19f, 0f, 0.27f, 0.159f, 1f, 270f, 0f, 0f, "Sym6" }, new object[13] { "face7", "Quad", "reel1", 0f, -0.1344f, -0.1344f, 0.27f, 0.159f, 1f, 315f, 0f, 0f, "Sym7" }, new object[13] { "rim", "Cylinder", "reel1", -0.145f, 0f, 0f, 0.4f, 0.014f, 0.4f, 0f, 0f, 90f, "Gold" }, new object[13] { "hub", "Cylinder", "reel1", -0.16f, 0f, 0f, 0.1f, 0.012f, 0.1f, 0f, 0f, 90f, "Iron" }, new object[13] { "rim", "Cylinder", "reel1", 0.145f, 0f, 0f, 0.4f, 0.014f, 0.4f, 0f, 0f, 90f, "Gold" }, new object[13] { "hub", "Cylinder", "reel1", 0.16f, 0f, 0f, 0.1f, 0.012f, 0.1f, 0f, 0f, 90f, "Iron" }, new object[13] { "reel2", "Group", "", 0.3f, 1.55f, -0.12f, 1f, 1f, 1f, 0f, 0f, 0f, "" }, new object[13] { "core", "Cylinder", "reel2", 0f, 0f, 0f, 0.34f, 0.15f, 0.34f, 0f, 0f, 90f, "Coal" }, new object[13] { "face0", "Quad", "reel2", 0f, 0f, -0.19f, 0.27f, 0.159f, 1f, 0f, 0f, 0f, "Sym0" }, new object[13] { "face1", "Quad", "reel2", 0f, 0.1344f, -0.1344f, 0.27f, 0.159f, 1f, 45f, 0f, 0f, "Sym1" }, new object[13] { "face2", "Quad", "reel2", 0f, 0.19f, 0f, 0.27f, 0.159f, 1f, 90f, 0f, 0f, "Sym2" }, new object[13] { "face3", "Quad", "reel2", 0f, 0.1344f, 0.1344f, 0.27f, 0.159f, 1f, 135f, 0f, 0f, "Sym3" }, new object[13] { "face4", "Quad", "reel2", 0f, 0f, 0.19f, 0.27f, 0.159f, 1f, 180f, 0f, 0f, "Sym4" }, new object[13] { "face5", "Quad", "reel2", 0f, -0.1344f, 0.1344f, 0.27f, 0.159f, 1f, 225f, 0f, 0f, "Sym5" }, new object[13] { "face6", "Quad", "reel2", 0f, -0.19f, 0f, 0.27f, 0.159f, 1f, 270f, 0f, 0f, "Sym6" }, new object[13] { "face7", "Quad", "reel2", 0f, -0.1344f, -0.1344f, 0.27f, 0.159f, 1f, 315f, 0f, 0f, "Sym7" }, new object[13] { "rim", "Cylinder", "reel2", -0.145f, 0f, 0f, 0.4f, 0.014f, 0.4f, 0f, 0f, 90f, "Gold" }, new object[13] { "hub", "Cylinder", "reel2", -0.16f, 0f, 0f, 0.1f, 0.012f, 0.1f, 0f, 0f, 90f, "Iron" }, new object[13] { "rim", "Cylinder", "reel2", 0.145f, 0f, 0f, 0.4f, 0.014f, 0.4f, 0f, 0f, 90f, "Gold" }, new object[13] { "hub", "Cylinder", "reel2", 0.16f, 0f, 0f, 0.1f, 0.012f, 0.1f, 0f, 0f, 90f, "Iron" }, new object[13] { "frameTop", "Cube", "", 0f, 1.77f, -0.405f, 1.04f, 0.12f, 0.05f, 0f, 0f, 0f, "Gold" }, new object[13] { "frameBottom", "Cube", "", 0f, 1.33f, -0.405f, 1.04f, 0.12f, 0.05f, 0f, 0f, 0f, "Gold" }, new object[13] { "frameSide", "Cube", "", -0.49f, 1.55f, -0.405f, 0.1f, 0.4f, 0.05f, 0f, 0f, 0f, "Gold" }, new object[13] { "frameSide", "Cube", "", 0.49f, 1.55f, -0.405f, 0.1f, 0.4f, 0.05f, 0f, 0f, 0f, "Gold" }, new object[13] { "frameInner", "Cube", "", 0f, 1.77f, -0.435f, 0.88f, 0.035f, 0.02f, 0f, 0f, 0f, "Dark" }, new object[13] { "frameInnerB", "Cube", "", 0f, 1.33f, -0.435f, 0.88f, 0.035f, 0.02f, 0f, 0f, 0f, "Dark" }, new object[13] { "payline", "Cube", "", 0f, 1.55f, -0.36f, 0.9f, 0.012f, 0.006f, 0f, 0f, 0f, "Red" }, new object[13] { "lineMarker", "Sphere", "", -0.45f, 1.55f, -0.43f, 0.05f, 0.05f, 0.03f, 0f, 0f, 0f, "Red" }, new object[13] { "lineMarker", "Sphere", "", 0.45f, 1.55f, -0.43f, 0.05f, 0.05f, 0.03f, 0f, 0f, 0f, "Red" }, new object[13] { "marquee", "Cube", "", 0f, 2.14f, -0.04f, 1.1f, 0.42f, 0.66f, 0f, 0f, 0f, "Dark" }, new object[13] { "signBoard", "Cube", "", 0f, 2.14f, -0.372f, 0.96f, 0.32f, 0.03f, 0f, 0f, 0f, "Red" }, new object[13] { "signTrimTop", "Cube", "", 0f, 2.31f, -0.385f, 0.98f, 0.03f, 0.03f, 0f, 0f, 0f, "Gold" }, new object[13] { "signTrimBottom", "Cube", "", 0f, 1.97f, -0.385f, 0.98f, 0.03f, 0.03f, 0f, 0f, 0f, "Gold" }, new object[13] { "emblemL", "Quad", "", -0.29f, 2.14f, -0.392f, 0.24f, 0.24f, 1f, 0f, 0f, 0f, "Sym4" }, new object[13] { "emblemC", "Quad", "", 0f, 2.14f, -0.392f, 0.26f, 0.26f, 1f, 0f, 0f, 0f, "Sym5" }, new object[13] { "emblemR", "Quad", "", 0.29f, 2.14f, -0.392f, 0.24f, 0.24f, 1f, 0f, 0f, 0f, "Sym4" }, new object[13] { "signDivider", "Cube", "", -0.15f, 2.14f, -0.39f, 0.012f, 0.26f, 0.01f, 0f, 0f, 0f, "Gold" }, new object[13] { "signDividerOuter", "Cube", "", -0.44f, 2.14f, -0.39f, 0.012f, 0.26f, 0.01f, 0f, 0f, 0f, "Gold" }, new object[13] { "signDivider", "Cube", "", 0.15f, 2.14f, -0.39f, 0.012f, 0.26f, 0.01f, 0f, 0f, 0f, "Gold" }, new object[13] { "signDividerOuter", "Cube", "", 0.44f, 2.14f, -0.39f, 0.012f, 0.26f, 0.01f, 0f, 0f, 0f, "Gold" }, new object[13] { "bulbA", "Sphere", "", -0.46f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", -0.345f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", -0.23f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", -0.115f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", 0f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", 0.115f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", 0.23f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", 0.345f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", 0.46f, 2.355f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", -0.46f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", -0.345f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", -0.23f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", -0.115f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", 0f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", 0.115f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", 0.23f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", 0.345f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", 0.46f, 1.93f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", -0.5f, 2.05f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", -0.5f, 2.15f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", -0.5f, 2.25f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", 0.5f, 2.05f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "bulbA", "Sphere", "", 0.5f, 2.15f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "Glow" }, new object[13] { "bulbB", "Sphere", "", 0.5f, 2.25f, -0.4f, 0.05f, 0.05f, 0.04f, 0f, 0f, 0f, "GlowB" }, new object[13] { "cap", "Cube", "", 0f, 2.38f, -0.02f, 1.2f, 0.06f, 0.74f, 0f, 0f, 0f, "Gold" }, new object[13] { "capTop", "Cube", "", 0f, 2.43f, -0.02f, 1.06f, 0.05f, 0.6f, 0f, 0f, 0f, "Dark" }, new object[13] { "capBall", "Sphere", "", -0.56f, 2.46f, -0.35f, 0.1f, 0.1f, 0.1f, 0f, 0f, 0f, "Gold" }, new object[13] { "capBall", "Sphere", "", -0.56f, 2.46f, 0.31f, 0.1f, 0.1f, 0.1f, 0f, 0f, 0f, "Gold" }, new object[13] { "capBall", "Sphere", "", 0.56f, 2.46f, -0.35f, 0.1f, 0.1f, 0.1f, 0f, 0f, 0f, "Gold" }, new object[13] { "capBall", "Sphere", "", 0.56f, 2.46f, 0.31f, 0.1f, 0.1f, 0.1f, 0f, 0f, 0f, "Gold" }, new object[13] { "perch", "Cube", "", 0f, 2.48f, -0.05f, 0.3f, 0.03f, 0.14f, 0f, 0f, 0f, "Gold" }, new object[13] { "ravenBody", "Sphere", "", 0f, 2.6f, -0.04f, 0.2f, 0.17f, 0.3f, -18f, 0f, 0f, "Black" }, new object[13] { "ravenHead", "Sphere", "", 0f, 2.7f, -0.17f, 0.12f, 0.12f, 0.12f, 0f, 0f, 0f, "Black" }, new object[13] { "ravenBeak", "Cube", "", 0f, 2.69f, -0.255f, 0.035f, 0.035f, 0.09f, 12f, 0f, 0f, "Gold" }, new object[13] { "ravenEyeL", "Sphere", "", -0.04f, 2.72f, -0.225f, 0.025f, 0.025f, 0.02f, 0f, 0f, 0f, "Red" }, new object[13] { "ravenEyeR", "Sphere", "", 0.04f, 2.72f, -0.225f, 0.025f, 0.025f, 0.02f, 0f, 0f, 0f, "Red" }, new object[13] { "ravenTail", "Cube", "", 0f, 2.55f, 0.14f, 0.1f, 0.03f, 0.2f, -25f, 0f, 0f, "Black" }, new object[13] { "ravenWing", "Cube", "", -0.1f, 2.61f, -0.02f, 0.05f, 0.12f, 0.26f, 0f, 0f, -10f, "Coal" }, new object[13] { "ravenWing", "Cube", "", 0.1f, 2.61f, -0.02f, 0.05f, 0.12f, 0.26f, 0f, 0f, 10f, "Coal" }, new object[13] { "sidePanel", "Cube", "", -0.505f, 0.58f, 0f, 0.025f, 0.56f, 0.6f, 0f, 0f, 0f, "Planks" }, new object[13] { "sideTrimTop", "Cube", "", -0.515f, 0.88f, 0f, 0.02f, 0.025f, 0.64f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideTrimBottom", "Cube", "", -0.515f, 0.28f, 0f, 0.02f, 0.025f, 0.64f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideTrimFront", "Cube", "", -0.515f, 0.58f, -0.31f, 0.02f, 0.6f, 0.025f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideTrimBack", "Cube", "", -0.515f, 0.58f, 0.31f, 0.02f, 0.6f, 0.025f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideCoin", "Cylinder", "", -0.52f, 0.58f, 0f, 0.3f, 0.012f, 0.3f, 0f, 0f, 90f, "Gold" }, new object[13] { "sideCoinInner", "Cylinder", "", -0.53f, 0.58f, 0f, 0.2f, 0.012f, 0.2f, 0f, 0f, 90f, "Dark" }, new object[13] { "sidePanel", "Cube", "", 0.505f, 0.58f, 0f, 0.025f, 0.56f, 0.6f, 0f, 0f, 0f, "Planks" }, new object[13] { "sideTrimTop", "Cube", "", 0.515f, 0.88f, 0f, 0.02f, 0.025f, 0.64f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideTrimBottom", "Cube", "", 0.515f, 0.28f, 0f, 0.02f, 0.025f, 0.64f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideTrimFront", "Cube", "", 0.515f, 0.58f, -0.31f, 0.02f, 0.6f, 0.025f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideTrimBack", "Cube", "", 0.515f, 0.58f, 0.31f, 0.02f, 0.6f, 0.025f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideCoin", "Cylinder", "", 0.52f, 0.58f, 0f, 0.3f, 0.012f, 0.3f, 0f, 0f, 90f, "Gold" }, new object[13] { "sideCoinInner", "Cylinder", "", 0.53f, 0.58f, 0f, 0.2f, 0.012f, 0.2f, 0f, 0f, 90f, "Dark" }, new object[13] { "cornerStrip", "Cube", "", -0.515f, 1.2f, -0.405f, 0.04f, 2.1f, 0.04f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideBand", "Cube", "", -0.505f, 1f, 0f, 0.03f, 0.06f, 0.82f, 0f, 0f, 0f, "Iron" }, new object[13] { "sideBandUpper", "Cube", "", -0.525f, 1.66f, 0f, 0.03f, 0.06f, 0.82f, 0f, 0f, 0f, "Iron" }, new object[13] { "cornerStrip", "Cube", "", 0.515f, 1.2f, -0.405f, 0.04f, 2.1f, 0.04f, 0f, 0f, 0f, "Gold" }, new object[13] { "sideBand", "Cube", "", 0.505f, 1f, 0f, 0.03f, 0.06f, 0.82f, 0f, 0f, 0f, "Iron" }, new object[13] { "sideBandUpper", "Cube", "", 0.525f, 1.66f, 0f, 0.03f, 0.06f, 0.82f, 0f, 0f, 0f, "Iron" }, new object[13] { "leverBoss", "Cylinder", "", 0.56f, 1.05f, -0.08f, 0.15f, 0.04f, 0.15f, 0f, 0f, 90f, "Iron" }, new object[13] { "leverPlate", "Cylinder", "", 0.53f, 1.05f, -0.08f, 0.26f, 0.012f, 0.26f, 0f, 0f, 90f, "Gold" }, new object[13] { "lever", "Group", "", 0.62f, 1.05f, -0.08f, 1f, 1f, 1f, 0f, 0f, 0f, "" }, new object[13] { "armPivot", "Cylinder", "lever", 0f, 0f, 0f, 0.1f, 0.04f, 0.1f, 0f, 0f, 90f, "Gold" }, new object[13] { "arm", "Cylinder", "lever", 0f, 0.26f, 0f, 0.045f, 0.28f, 0.045f, 0f, 0f, 0f, "Iron" }, new object[13] { "knob", "Sphere", "lever", 0f, 0.58f, 0f, 0.14f, 0.14f, 0.14f, 0f, 0f, 0f, "Red" } }; } internal static class Payout { internal static readonly string[] Names = new string[6] { "slotmachine_coin", "slotmachine_boar", "slotmachine_horn", "slotmachine_axe", "slotmachine_raven", "slotmachine_valknut" }; private static readonly int[] Weight = new int[6] { 7, 5, 4, 2, 1, 1 }; private static readonly int[] Three = new int[6] { 5, 10, 16, 40, 100, 300 }; private static readonly int[] Pair = new int[6] { 1, 0, 0, 0, 5, 10 }; internal static readonly int[] Faces = new int[8] { 0, 1, 2, 3, 4, 5, 0, 1 }; internal const int Jackpot = 5; internal static int[] Roll(Random rng) { int[] array = new int[3]; for (int i = 0; i < 3; i++) { int num = rng.Next(20); int num2 = 0; for (int j = 0; j < Weight.Length; j++) { num -= Weight[j]; if (num < 0) { num2 = j; break; } } List<int> list = new List<int>(); for (int k = 0; k < Faces.Length; k++) { if (Faces[k] == num2) { list.Add(k); } } array[i] = list[rng.Next(list.Count)]; } return array; } internal static int Multiplier(int[] cells) { int num = Faces[cells[0]]; int num2 = Faces[cells[1]]; int num3 = Faces[cells[2]]; if (num == num2 && num2 == num3) { return Three[num]; } if (num == num2) { return Pair[num]; } if (num == num3) { return Pair[num]; } if (num2 == num3) { return Pair[num2]; } return 0; } internal static bool IsJackpot(int[] cells) { if (Faces[cells[0]] == 5 && Faces[cells[1]] == 5) { return Faces[cells[2]] == 5; } return false; } internal static string Summary() { return Pays(3, 5, Three[5]) + " · " + Pays(3, 4, Three[4]) + " · " + Pays(3, 3, Three[3]) + " · " + Pays(3, 2, Three[2]) + "\n" + Pays(3, 1, Three[1]) + " · " + Pays(3, 0, Three[0]) + " · " + Pays(2, 5, Pair[5]) + " · " + Pays(2, 4, Pair[4]) + " · " + Pays(2, 0, Pair[0]); } private static string Pays(int count, int symbol, int times) { return Translations.T("slotmachine_pays", count, Translations.T(Names[symbol]), times); } } [BepInPlugin("com.quad.slotmachine", "SlotMachine", "1.2.3")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.quad.slotmachine"; public const string OldGuid = "com.dhack.slotmachine"; public const string Name = "SlotMachine"; public const string Version = "1.2.3"; public const string PiecePrefab = "piece_slotmachine"; internal static ConfigEntry<int> Bet; internal static ConfigEntry<int> PayoutPercent; internal static ConfigEntry<string> Cost; internal static ManualLogSource Log; internal const string DefaultCost = "FineWood:15, Bronze:8, Stone:10"; private static bool _tellNoServer; internal static ServerSettings Synced; private static readonly int[] Bets = new int[5] { 5, 10, 25, 50, 100 }; private static GameObject _holder; private static GameObject _prefab; private static PieceTable _table; private Harmony _harmony; private void Awake() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown Migration.FromOldGuid((BaseUnityPlugin)(object)this, "com.dhack.slotmachine"); Translations.Load((BaseUnityPlugin)(object)this); Log = ((BaseUnityPlugin)this).Logger; Synced = new ServerSettings("com.quad.slotmachine", ((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); Bet = ((BaseUnityPlugin)this).Config.Bind<int>("Play", "Bet", 10, new ConfigDescription("Coins per pull (change it at the machine with the alternate-use key + use).", (AcceptableValueBase)(object)new AcceptableValueList<int>(Bets), Array.Empty<object>())); PayoutPercent = Synced.Add<int>(((BaseUnityPlugin)this).Config.Bind<int>("Play", "PayoutPercent", 100, new ConfigDescription("Scales every prize (100 = standard, which returns about 93% over time; 50 = half the prizes; above 107 the machine pays out more than goes in). In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 300), Array.Empty<object>()))); Cost = Synced.Bind("Building", "Cost", "FineWood:15, Bronze:8, Stone:10", "What a slot machine costs to build with the hammer (at a workbench). Item prefab names and amounts, separated by commas, like FineWood:12, BronzeNails:30 (Claude Tools' `prefabs <text>` shows exact names). A cost with a mistake in it keeps the last good one.", null); Cost.SettingChanged += delegate { ApplyCost(); }; Synced.ServerChanged += delegate { _tellNoServer = Synced.Server == ServerSettings.ServerMod.Missing; }; _harmony = new Harmony("com.quad.slotmachine"); _harmony.PatchAll(); if ((Object)(object)ZNetScene.instance != (Object)null) { Register(ZNetScene.instance); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"SlotMachine 1.2.3 loaded"); } private void Update() { Synced?.Update(); if (_tellNoServer && (Object)(object)Player.m_localPlayer != (Object)null) { _tellNoServer = false; ((Character)Player.m_localPlayer).Message((MessageType)2, "$slotmachine_server_missing", 0, (Sprite)null, false); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Unregister(); Synced?.Dispose(); Translations.Unload(); } internal static void NextBet() { int num = Array.IndexOf(Bets, Bet.Value); Bet.Value = Bets[(num + 1) % Bets.Length]; } internal static void Register(ZNetScene scene) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown GameObject prefab = scene.GetPrefab("piece_chest_wood"); GameObject prefab2 = scene.GetPrefab("Hammer"); GameObject prefab3 = scene.GetPrefab("piece_workbench"); if ((Object)(object)prefab == (Object)null || (Object)(object)prefab2 == (Object)null) { Debug.LogWarning((object)"SlotMachine: chest or hammer prefab not found"); return; } if ((Object)(object)_prefab == (Object)null) { _holder = new GameObject("SlotMachinePrefabs"); _holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_holder); try { Look.Harvest(scene, prefab.GetComponentInChildren<Renderer>(true).sharedMaterial); } catch (Exception ex) { Debug.LogWarning((object)("SlotMachine: could not gather the materials for its look: " + ex.Message)); } _prefab = Make(prefab, ((Object)(object)prefab3 != (Object)null) ? prefab3.GetComponent<CraftingStation>() : null); } Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs").GetValue(scene); PieceTable buildPieces = prefab2.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces; if (!scene.m_prefabs.Contains(_prefab)) { scene.m_prefabs.Add(_prefab); } dictionary[StringExtensionMethods.GetStableHashCode(((Object)_prefab).name)] = _prefab; buildPieces.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null); if (!buildPieces.m_pieces.Contains(_prefab)) { buildPieces.m_pieces.Add(_prefab); } _table = buildPieces; Synced.NeedsServer(_prefab); } internal static void ApplyCost() { Piece val = (((Object)(object)_prefab != (Object)null) ? _prefab.GetComponent<Piece>() : null); if ((Object)(object)val != (Object)null) { Costs.Apply(val, Cost.Value, Log); } } private static GameObject Make(GameObject source, CraftingStation workbench) { //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(source, _holder.transform); ((Object)val).name = "piece_slotmachine"; Container component = val.GetComponent<Container>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } int num = LayerMask.NameToLayer("piece"); if (num < 0) { num = val.layer; } Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren2) { Object.DestroyImmediate((Object)(object)val2); } GameObject val3 = new GameObject("Hitbox") { layer = num }; val3.transform.SetParent(val.transform, false); BoxCollider val4 = val3.AddComponent<BoxCollider>(); val4.center = new Vector3(0f, 1.13f, -0.02f); val4.size = new Vector3(1.05f, 2.3f, 0.92f); try { ModelBuilder.Build(val.transform, ModelData.Parts, val.layer); Renderer[] array = componentsInChildren; foreach (Renderer val5 in array) { val5.enabled = false; } } catch (Exception ex) { Debug.LogWarning((object)("SlotMachine: could not build the slot machine's look, it keeps the chest's: " + ex.Message)); Transform val6 = val.transform.Find("Model"); if ((Object)(object)val6 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val6).gameObject); } } SnapPoints.Clear(val); SnapPoints.Box(val, new Vector3(-0.61f, 0f, -0.65f), new Vector3(0.69f, 0f, 0.48f)); Piece component2 = val.GetComponent<Piece>(); component2.m_name = "$slotmachine_piece"; component2.m_description = "$slotmachine_piece_desc"; component2.m_category = (PieceCategory)0; component2.m_usage = (UsageTagFlags)640; component2.m_craftingStation = workbench; if (!Costs.Apply(component2, Cost.Value, Log)) { Costs.Apply(component2, "FineWood:15, Bronze:8, Stone:10", Log); } try { Sprite val7 = Icon.Make(val); if ((Object)(object)val7 != (Object)null) { component2.m_icon = val7; } } catch (Exception ex2) { Debug.LogWarning((object)("SlotMachine: could not draw the build-menu picture: " + ex2.Message)); } val.AddComponent<SlotMachinePiece>(); return val; } internal static void Unregister() { if ((Object)(object)_prefab == (Object)null) { return; } if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.m_prefabs.Remove(_prefab); Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs").GetValue(ZNetScene.instance); int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)_prefab).name); if (dictionary.TryGetValue(stableHashCode, out var value) && (Object)(object)value == (Object)(object)_prefab) { dictionary.Remove(stableHashCode); } } GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("Hammer") : null); (_table ?? (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces : null))?.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || (Object)(object)p == (Object)(object)_prefab); _table = null; _prefab = null; Object.Destroy((Object)(object)_holder); _holder = null; Look.Clear(); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetScene_Awake { private static void Postfix(ZNetScene __instance) { Plugin.Register(__instance); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDB_Awake { private static void Postfix() { if ((Object)(object)ZNetScene.instance != (Object)null) { Plugin.Register(ZNetScene.instance); } } } [HarmonyPatch(typeof(Game), "Shutdown")] internal static class Game_Shutdown { private static void Prefix() { SlotMachinePiece.PayOwed(); } } } namespace DHack.Shared { internal static class Migration { private sealed class Notice : MonoBehaviour { public string Text; private float _next; private void Update() { if (!(Time.unscaledTime < _next) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)MessageHud.instance == (Object)null)) { ((Character)Player.m_localPlayer).Message((MessageType)2, Text, 0, (Sprite)null, false); _next = Time.unscaledTime + 60f; } } } public static void FromOldGuid(BaseUnityPlugin plugin, string oldGuid) { BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin); string text = ((metadata != null) ? metadata.GUID : null); if (string.IsNullOrEmpty(oldGuid) || string.IsNullOrEmpty(text) || oldGuid == text) { return; } ManualLogSource val = Logger.CreateLogSource(text); try { bool flag = false; if (Directory.Exists(Paths.ConfigPath)) { string[] files = Directory.GetFiles(Paths.ConfigPath, oldGuid + ".*"); foreach (string text2 in files) { string fileName = Path.GetFileName(text2); if (!fileName.EndsWith(".cfg") && !fileName.EndsWith(".json") && !fileName.EndsWith(".txt")) { continue; } string text3 = Path.Combine(Paths.ConfigPath, text + fileName.Substring(oldGuid.Length)); if (!File.Exists(text3)) { File.Copy(text2, text3); val.LogInfo((object)("Settings moved over from " + fileName + " (the mod's id is now " + text + "; the old file is kept as a backup)")); if (fileName == oldGuid + ".cfg") { flag = true; } } } } if (flag) { plugin.Config.Reload(); } } catch (Exception ex) { val.LogWarning((object)("Couldn't move the settings over from " + oldGuid + ".cfg: " + ex.Message)); } finally { Logger.Sources.Remove((ILogSource)(object)val); } ((MonoBehaviour)plugin).StartCoroutine(StandDownIfTwin(plugin, oldGuid)); } private static IEnumerator StandDownIfTwin(BaseUnityPlugin plugin, string oldGuid) { yield return null; yield return null; if (!((Object)(object)plugin == (Object)null) && Chainloader.PluginInfos.TryGetValue(oldGuid, out var value) && !((Object)(object)value.Instance == (Object)null) && !((Object)(object)value.Instance == (Object)(object)plugin)) { BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin); string text = ((metadata != null) ? metadata.Name : null) ?? oldGuid; string text2 = (string.IsNullOrEmpty(value.Location) ? "an older copy" : value.Location); string text3 = text + ": two copies are installed, an old one (" + text2 + ") and this one. Both would run and do everything twice, so this one stands down. Delete the old copy, then restart the game."; Debug.LogError((object)("[" + text + "] " + text3)); Object.Destroy((Object)(object)plugin); GameObject val = new GameObject("Migration_TwoCopies_" + text); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<Notice>().Text = text3; } } } internal static class Translations { private sealed class Blank { public string Tag; public Func<string> Value; public Action Unhook; } public static readonly string[] Shipped = new string[9] { "English", "Russian", "German", "Chinese", "Portuguese_Brazilian", "Spanish", "French", "Polish", "Turkish" }; private static readonly Dictionary<string, Dictionary<string, string>> Languages = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); private static Dictionary<string, string> _english = new Dictionary<string, string>(); private static string _overrideDir; private static bool _hooked; private static readonly MethodInfo AddWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null); private static readonly FieldInfo Cache = AccessTools.Field(typeof(Localization), "m_cache"); private static readonly FieldInfo GameWords = AccessTools.Field(typeof(Localization), "m_translations"); private static Dictionary<string, string> _given = new Dictionary<string, string>(); private static Dictionary<string, string> _files = new Dictionary<string, string>(); private static readonly Dictionary<string, Dictionary<string, Dictionary<string, string>>> Runtime = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>(); private static readonly HashSet<string> _runtimeGiven = new HashSet<string>(); private static readonly Dictionary<string, List<Blank>> Fills = new Dictionary<string, List<Blank>>(); public static void Load(BaseUnityPlugin plugin) { Languages.Clear(); Assembly assembly = ((object)plugin).GetType().Assembly; foreach (string item in from n in assembly.GetManifestResourceNames() where n.StartsWith("translations/") && n.EndsWith(".json") select n) { using StreamReader streamReader = new StreamReader(assembly.GetManifestResourceStream(item)); Languages[Path.GetFileNameWithoutExtension(item.Substring("translations/".Length))] = Parse(streamReader.ReadToEnd()); } _english = (Languages.TryGetValue("English", out var value) ? value : new Dictionary<string, string>()); _overrideDir = Path.Combine(Paths.ConfigPath, "translations", plugin.Info.Metadata.GUID); if (!_hooked) { Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(Apply)); _hooked = true; } Apply(); } public static void Unload() { if (_hooked) { Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(Apply)); _hooked = false; } foreach (List<Blank> value2 in Fills.Values) { foreach (Blank item in value2) { item.Unhook?.Invoke(); } } Fills.Clear(); Runtime.Clear(); Localization val = ((_runtimeGiven.Count > 0) ? Localization.instance : null); if (val != null && AddWord != null) { Dictionary<string, string> dictionary = GameWords?.GetValue(val) as Dictionary<string, string>; foreach (string item2 in _runtimeGiven) { if (_files.TryGetValue(item2, out var value)) { AddWord.Invoke(val, new object[2] { item2, value }); } else { dictionary?.Remove(item2); } } EvictCache(val); } _runtimeGiven.Clear(); } public static string T(string key, params object[] args) { string text = ((Localization.instance != null) ? Localization.instance.Localize("$" + key) : null); if (string.IsNullOrEmpty(text) || text == "[" + key + "]") { text = (_english.TryGetValue(key, out var value) ? FillIn(key, value) : key); } if (args == null || args.Length == 0) { return text; } try { return string.Format(text, args); } catch (FormatException) { string value2; return _english.TryGetValue(key, out value2) ? SafeFormat(FillIn(key, value2), args) : text; } } private static string SafeFormat(string text, object[] args) { try { return string.Format(text, args); } catch (FormatException) { return text; } } public static void Fill<TValue>(string key, string placeholder, ConfigEntry<TValue> setting, Func<TValue, string> format = null) { if (setting != null) { Fill(key, placeholder, () => (format == null) ? Text(setting.Value) : format(setting.Value), (ConfigEntryBase)setting); } } public static void Fill(string key, string placeholder, Func<string> value, params ConfigEntryBase[] settings) { if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(placeholder) || value == null) { return; } key = key.TrimStart(new char[1] { '$' }); string tag = (placeholder.StartsWith("{") ? placeholder : ("{" + placeholder + "}")); if (!Fills.TryGetValue(key, out var value2)) { value2 = (Fills[key] = new List<Blank>()); } int num = value2.FindIndex((Blank b) => b.Tag == tag); if (num >= 0) { value2[num].Unhook?.Invoke(); value2.RemoveAt(num); } Blank blank = new Blank { Tag = tag, Value = value }; if (settings != null) { EventHandler changed = delegate { Show(key); }; foreach (ConfigEntryBase setting in settings.Where((ConfigEntryBase s) => s != null).Distinct()) { EventInfo ev = ((object)setting).GetType().GetEvent("SettingChanged"); if (!(ev == null)) { ev.AddEventHandler(setting, changed); blank.Unhook = (Action)Delegate.Combine(blank.Unhook, (Action)delegate { ev.RemoveEventHandler(setting, changed); }); } } } value2.Add(blank); Show(key); } public static void Refresh() { Localization instance = Localization.instance; if (instance == null || AddWord == null) { return; } foreach (string key in Fills.Keys) { if (_given.TryGetValue(key, out var value)) { AddWord.Invoke(instance, new object[2] { key, FillIn(key, value) }); } } EvictCache(instance); } private static void Show(string key) { Localization instance = Localization.instance; if (instance != null && !(AddWord == null) && _given.TryGetValue(key, out var value)) { AddWord.Invoke(instance, new object[2] { key, FillIn(key, value) }); EvictCache(instance); } } private static string FillIn(string key, string text) { if (text == null || !Fills.TryGetValue(key, out var value)) { return text; } foreach (Blank item in value) { if (text.IndexOf(item.Tag, StringComparison.Ordinal) >= 0) { try { text = text.Replace(item.Tag, item.Value() ?? ""); } catch (Exception ex) { Debug.LogWarning((object)("Translations: filling " + item.Tag + " in " + key + ": " + ex.Message)); } } } return text; } private static string Text(object value) { object obj; if (!(value is IFormattable formattable)) { obj = value?.ToString(); if (obj == null) { return ""; } } else { obj = formattable.ToString(null, CultureInfo.InvariantCulture); } return (string)obj; } public static void AddWords(string group, string language, IDictionary<string, string> words) { if (!string.IsNullOrEmpty(group) && !string.IsNullOrEmpty(language)) { SetWords(group, language, words); Apply(); } } public static void AddWords(string group, IDictionary<string, Dictionary<string, string>> languages) { if (string.IsNullOrEmpty(group)) { return; } Runtime.Remove(group); if (languages != null) { foreach (KeyValuePair<string, Dictionary<string, string>> language in languages) { if (!string.IsNullOrEmpty(language.Key)) { SetWords(group, language.Key, language.Value); } } } Apply(); } public static void RemoveWords(string group) { if (group != null && Runtime.Remove(group)) { Apply(); } } public static Dictionary<string, string> ParseJson(string json) { if (!string.IsNullOrEmpty(json)) { return Parse(json); } return new Dictionary<string, string>(); } private static void SetWords(string group, string language, IDictionary<string, string> words) { if (!Runtime.TryGetValue(group, out var value)) { value = (Runtime[group] = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase)); } if (words == null || words.Count == 0) { value.Remove(language); return; } Dictionary<string, string> dictionary2 = new Dictionary<string, string>(); foreach (KeyValuePair<string, string> word in words) { if (!string.IsNullOrEmpty(word.Key) && word.Value != null) { dictionary2[word.Key.TrimStart(new char[1] { '$' })] = word.Value; } } value[language] = dictionary2; } private static void AddRuntime(Dictionary<string, string> words, string language) { foreach (Dictionary<string, Dictionary<string, string>> value2 in Runtime.Values) { if (!value2.TryGetValue(language, out var value)) { continue; } foreach (KeyValuePair<string, string> item in value) { words[item.Key] = item.Value; } } } private static void Apply() { Localization instance = Localization.instance; if (instance == null || AddWord == null) { return; } string selectedLanguage = instance.GetSelectedLanguage(); Dictionary<string, string> dictionary = new Dictionary<string, string>(_english); Dictionary<string, string> dictionary2 = new Dictionary<string, string>(_english); AddRuntime(dictionary, "English"); if (!string.Equals(selectedLanguage, "English", StringComparison.OrdinalIgnoreCase)) { if (Languages.TryGetValue(selectedLanguage, out var value)) { foreach (KeyValuePair<string, string> item in value) { dictionary[item.Key] = item.Value; dictionary2[item.Key] = item.Value; } } AddRuntime(dictionary, selectedLanguage); } try { string path = Path.Combine(_overrideDir ?? "", selectedLanguage + ".json"); if (_overrideDir != null && File.Exists(path)) { foreach (KeyValuePair<string, string> item2 in Parse(File.ReadAllText(path))) { dictionary[item2.Key] = item2.Value; dictionary2[item2.Key] = item2.Value; } } } catch (Exception ex) { Debug.LogWarning((object)("Translations: couldn't read the player's " + selectedLanguage + " file: " + ex.Message)); } Dictionary<string, string> dictionary3 = GameWords?.GetValue(instance) as Dictionary<string, string>; foreach (string item3 in _runtimeGiven) { if (!dictionary.ContainsKey(item3)) { dictionary3?.Remove(item3); } } _runtimeGiven.Clear(); foreach (Dictionary<string, Dictionary<string, string>> value2 in Runtime.Values) { foreach (Dictionary<string, string> value3 in value2.Values) { foreach (string key in value3.Keys) { _runtimeGiven.Add(key); } } } _given = dictionary; _files = dictionary2; foreach (KeyValuePair<string, string> item4 in dictionary) { AddWord.Invoke(instance, new object[2] { item4.Key, FillIn(item4.Key, item4.Value) }); } EvictCache(instance); } private static void EvictCache(Localization loc) { object obj = Cache?.GetValue(loc); obj?.GetType().GetMethod("EvictAll")?.Invoke(obj, null); } private static Dictionary<string, string> Parse(string json) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (Match item in Regex.Matches(json, "\"((?:[^\"\\\\]|\\\\.)*)\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"")) { dictionary[Unescape(item.Groups[1].Value)] = Unescape(item.Groups[2].Value); } return dictionary; } private static string Unescape(string s) { return Regex.Replace(s, "\\\\(u[0-9a-fA-F]{4}|.)", delegate(Match m) { string value = m.Groups[1].Value; return value[0] switch { 'n' => "\n", 't' => "\t", 'u' => ((char)Convert.ToInt32(value.Substring(1), 16)).ToString(), _ => value, }; }); } } internal sealed class ServerSettings : IDisposable { public enum ServerMod { NotConnected, Checking, Installed, Missing } private sealed class ConfigurationManagerAttributes { public bool? ReadOnly; } private sealed class SyncedText { public string Key; public Func<string> Own; public Action<string> Use; public string Given; public bool FromServer; public bool Pending; public byte[] Packed; public bool TooBig; public MemoryStream Incoming; public int NextPart; } private sealed class Sending { public ZRpc Rpc; public string Key; public byte[] Data; public int Next; public int Parts; } private const int Protocol = 2; private const float ChangeSendGap = 0.5f; private const float AnswerWait = 20f; private const float FileWait = 1f; private const int PartSize = 65536; private const int CompressFrom = 1024; private const int WarnBytes = 262144; private const int MaxBytes = 8388608; private const int PaceBelow = 10240; private readonly string _send; private readonly string _ask; private readonly string _dAsk; private readonly string _dHello; private readonly string _dSend; private readonly string _edit; private readonly string _dTextAsk; private readonly string _dText; private readonly string _dAgain; private readonly ConfigFile _config; private readonly ManualLogSource _log; private readonly string _name; private readonly List<ConfigEntryBase> _entries = new List<ConfigEntryBase>(); private readonly Dictionary<ConfigEntryBase, object> _own = new Dictionary<ConfigEntryBase, object>(); private readonly Dictionary<ConfigEntryBase, object> _server = new Dictionary<ConfigEntryBase, object>(); private readonly List<GameObject> _guardedPieces = new List<GameObject>(); private readonly List<Recipe> _guardedRecipes = new List<Recipe>(); private ZRoutedRpc _registeredOn; private bool _applying; private bool _reloading; private bool _changePending; private float _nextChangeSend; private float _askedAt = -1f; private int _serverProtocol; private bool _directSeen; private readonly HashSet<ZRpc> _directPeers = new HashSet<ZRpc>(); private readonly List<SyncedText> _texts = new List<SyncedText>(); private readonly Dictionary<ZRpc, HashSet<string>> _textPeers = new Dictionary<ZRpc, HashSet<string>>(); private bool _textPending; private float _nextTextSend; private bool _readOnlyShown; private float _nextAdminCheck; private FileSystemWatcher _watcher; private volatile bool _fileTouched; private float _reloadAt = -1f; private string _fileText; private readonly List<Sending> _outbox = new List<Sending>(); private static readonly MethodInfo UpdateAvailablePieces = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null); private static readonly List<ServerSettings> Live = new List<ServerSettings>(); private static Harmony _saveHarmony; public string Version { get; } public bool FromServer => _server.Count > 0; public ServerMod Server { get; private set; } public string ServerVersion { get; private set; } public bool CanEditServer { get { if (!IsServer) { if (Server == ServerMod.Installed && _serverProtocol >= 1 && (Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.LocalPlayerIsAdminOrHost(); } return false; } return true; } } private static bool IsServer { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } public event Action ServerChanged; public ServerSettings(string guid, ConfigFile config, ManualLogSource log) { _send = guid + ".settings"; _ask = guid + ".settings.ask"; _dAsk = guid + ".settings.d.ask"; _dHello = guid + ".settings.d.hello"; _dSend = guid + ".settings.d.values"; _edit = guid + ".settings.d.edit"; _dTextAsk = guid + ".settings.d.textask"; _dAgain = guid + ".settings.d.again"; _dText = guid + ".settings.d.text"; _config = config; _log = log; BepInPlugin val = PluginOf(guid); _name = ((val != null) ? val.Name : null) ?? guid; Version = ((val == null) ? null : val.Version?.ToString()) ?? ""; Live.Add(this); if (Live.Count == 1) { PatchSave(); } WatchFile(); } public ConfigEntry<T> Add<T>(ConfigEntry<T> entry) { if (entry == null || _entries.Contains((ConfigEntryBase)(object)entry)) { return entry; } _entries.Add((ConfigEntryBase)(object)entry); entry.SettingChanged += OnChanged; GiveManagerAttributes((ConfigEntryBase)(object)entry); return entry; } private static void GiveManagerAttributes(ConfigEntryBase entry) { ConfigDescription description = entry.Description; if (description == null || description == ConfigDescription.Empty || (description.Tags ?? new object[0]).Any(IsManagerAttributes)) { return; } try { object[] value = new object[1] { new ConfigurationManagerAttributes() }.Concat(description.Tags ?? new object[0]).ToArray(); AccessTools.Field(typeof(ConfigDescription), "<Tags>k__BackingField")?.SetValue(description, value); } catch (Exception) { } } public ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase range = null, params object[] tags) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown if (!description.Contains("[Synced with Server]")) { description += " [Synced with Server]"; } return Add<T>(_config.Bind<T>(section, key, value, new ConfigDescription(description, range, tags ?? new object[0]))); } public void NeedsServer(GameObject piecePrefab) { if (!((Object)(object)piecePrefab == (Object)null)) { _guardedPieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || ((Object)p).name == ((Object)piecePrefab).name); _guardedPieces.Add(piecePrefab); Guard(); } } public void NeedsServer(Recipe recipe) { if (!((Object)(object)recipe == (Object)null)) { _guardedRecipes.RemoveAll((Recipe r) => (Object)(object)r == (Object)null || (Object)(object)r == (Object)(object)recipe || (!string.IsNullOrEmpty(((Object)recipe).name) && ((Object)r).name == ((Object)recipe).name)); _guardedRecipes.Add(recipe); Guard(); } } public void AddText(string key, Func<string> own, Action<string> use) { if (string.IsNullOrEmpty(key) || own == null || use == null) { ManualLogSource log = _log; if (log != null) { log.LogError((object)"AddText needs a key, own and use"); } return; } _texts.RemoveAll((SyncedText x) => x.Key == key); SyncedText syncedText = new SyncedText { Key = key, Own = own, Use = use }; _texts.Add(syncedText); Give(syncedText, OwnText(syncedText)); ZRpc val = ((!((Object)(object)ZNet.instance != (Object)null) || IsServer) ? null : ZNet.instance.GetServerPeer()?.m_rpc); if (_registeredOn != null && val != null) { val.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText); AskTexts(val); } } public void TextChanged(string key) { SyncedText syncedText = _texts.FirstOrDefault((SyncedText x) => x.Key == key); if (syncedText != null) { syncedText.Packed = null; if (!syncedText.FromServer) { Give(syncedText, OwnText(syncedText)); } if (IsServer) { syncedText.Pending = true; _textPending = true; } } } public bool TextFromServer(string key) { return _texts.Any((SyncedText x) => x.Key == key && x.FromServer); } public void Update() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != _registeredOn) { Unregister(); Restore(); RestoreTexts(give: true); _changePending = false; _textPending = false; SetServer(ServerMod.NotConnected, null, 0); if (instance != null) { Register(instance); } } float unscaledTime = Time.unscaledTime; if (_changePending && unscaledTime >= _nextChangeSend) { SendChange(); } if (_textPending && unscaledTime >= _nextTextSend) { SendTexts(); } if (_outbox.Count > 0) { Pump(); } if (Server == ServerMod.Checking && _askedAt >= 0f && unscaledTime - _askedAt > 20f) { if (_guardedPieces.Count + _guardedRecipes.Count > 0) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("The server didn't answer: " + _name + " isn't installed there (or its copy is older than 2026-10-11), so its pieces and items can't be made on this server.")); } } else { ManualLogSource log2 = _log; if (log2 != null) { log2.LogInfo((object)("The server didn't answer: " + _name + " isn't installed there, or its copy is older" + (FromServer ? " (its settings apply)." : " (your own settings apply)."))); } } SetServer(ServerMod.Missing, null, 0); } if (_fileTouched) { _fileTouched = false; _reloadAt = unscaledTime + 1f; } if (_reloadAt >= 0f && unscaledTime >= _reloadAt) { _reloadAt = -1f; ReloadFile(); } if (FromServer && unscaledTime >= _nextAdminCheck) { _nextAdminCheck = unscaledTime + 1f; ShowReadOnly(); } } public void Dispose() { Unregister(); Restore(); RestoreTexts(give: false); SetServer(ServerMod.NotConnected, null, 0); foreach (ConfigEntryBase entry in _entries) { Unsubscribe(entry); } _entries.Clear(); _texts.Clear(); try { _watcher?.Dispose(); } catch (Exception) { } _watcher = null; Live.Remove(this); if (Live.Count == 0) { UnpatchSave(); } } private void Register(ZRoutedRpc rpc) { Forget(rpc, _send); Forget(rpc, _ask); rpc.Register<ZPackage>(_send, (Action<long, ZPackage>)OnRoutedValues); rpc.Register(_ask, (Action<long>)OnRoutedAsk); rpc.m_onNewPeer = (Action<long>)Delegate.Combine(rpc.m_onNewPeer, new Action<long>(OnNewPeer)); _registeredOn = rpc; if (IsServer) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ListenTo(peer); if (peer != null) { ZRpc rpc2 = peer.m_rpc; if (rpc2 != null) { rpc2.Invoke(_dAgain, Array.Empty<object>()); } } } return; } if ((Object)(object)ZNet.instance != (Object)null) { SetServer(ServerMod.Checking, null, 0); if (ZNet.instance.GetServerPeer() != null) { AskServer(); } } } private void Unregister() { if (_registeredOn == null) { return; } ZRoutedRpc registeredOn = _registeredOn; registeredOn.m_onNewPeer = (Action<long>)Delegate.Remove(registeredOn.m_onNewPeer, new Action<long>(OnNewPeer)); Forget(_registeredOn, _send); Forget(_registeredOn, _ask); if ((Object)(object)ZNet.instance != (Object)null) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer?.m_rpc != null) { string[] array = new string[7] { _dAsk, _dHello, _dSend, _edit, _dTextAsk, _dText, _dAgain }; foreach (string name in array) { ForgetDirect(peer.m_rpc, name); } } } } _directPeers.Clear(); _textPeers.Clear(); _outbox.Clear(); _directSeen = false; _registeredOn = null; } private static void Forget(ZRoutedRpc rpc, string name) { if (AccessTools.Field(typeof(ZRoutedRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary) { dictionary.Remove(StringExtensionMethods.GetStableHashCode(name)); } } private static void ForgetDirect(ZRpc rpc, string name) { if (AccessTools.Field(typeof(ZRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary) { dictionary.Remove(StringExtensionMethods.GetStableHashCode(name)); } } private void OnNewPeer(long uid) { if (IsServer) { ZNetPeer peer = ZNet.instance.GetPeer(uid); ListenTo(peer); if (peer?.m_rpc != null) { SendDirect(peer.m_rpc); } SendRouted(uid); } else if ((Object)(object)ZNet.instance != (Object)null) { ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.m_uid == uid) { AskServer(); } } } private void ListenTo(ZNetPeer peer) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (peer?.m_rpc != null) { peer.m_rpc.Register(_dAsk, new Method(OnDirectAsk)); peer.m_rpc.Register<ZPackage>(_edit, (Action<ZRpc, ZPackage>)OnEdit); peer.m_rpc.Register<ZPackage>(_dTextAsk, (Action<ZRpc, ZPackage>)OnTextAsk); } } private void OnDirectAsk(ZRpc rpc) { if (IsServer) { _directPeers.Add(rpc); SendDirect(rpc); } } private void OnRoutedAsk(long sender) { if (IsServer) { SendRouted(sender); } } private void SendDirect(ZRpc rpc) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(2); val.Write(Version); rpc.Invoke(_dHello, new object[1] { val }); if (_entries.Count > 0) { rpc.Invoke(_dSend, new object[1] { Values() }); } } private void SendRouted(long target) { if (ZRoutedRpc.instance != null && _entries.Count > 0) { ZRoutedRpc.instance.InvokeRoutedRPC(target, _send, new object[1] { Values() }); } } private ZPackage Values() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(_entries.Count); foreach (ConfigEntryBase entry in _entries) { val.Write(entry.Definition.Section); val.Write(entry.Definition.Key); val.Write(TomlTypeConverter.ConvertToString(entry.BoxedValue, entry.SettingType)); } return val; } private void AskServer() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null); if (val?.m_rpc == null) { return; } _askedAt = Time.unscaledTime; val.m_rpc.Register<ZPackage>(_dHello, (Action<ZRpc, ZPackage>)OnDirectHello); val.m_rpc.Register<ZPackage>(_dSend, (Action<ZRpc, ZPackage>)OnDirectValues); val.m_rpc.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText); val.m_rpc.Register(_dAgain, new Method(OnAskAgain)); val.m_rpc.Invoke(_dAsk, Array.Empty<object>()); AskTexts(val.m_rpc); try { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(val.m_uid, _ask, Array.Empty<object>()); } } catch (Exception) { } } private static bool IsServerConnection(ZRpc rpc) { if (!IsServer) { ZNet instance = ZNet.instance; return ((instance == null) ? null : instance.GetServerPeer()?.m_rpc) == rpc; } return false; } private void OnAskAgain(ZRpc rpc) { if (IsServerConnection(rpc)) { rpc.Invoke(_dAsk, Array.Empty<object>()); AskTexts(rpc); } } private void OnDirectHello(ZRpc rpc, ZPackage pkg) { if (!IsServerConnection(rpc)) { return; } try { int protocol = pkg.ReadInt(); string text = pkg.ReadString(); if (text != Version && text != ServerVersion) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("The server has " + _name + " " + text + ", you have " + Version + ": some things may not match. Use the same version as the server.")); } } _directSeen = true; SetServer(ServerMod.Installed, text, protocol); } catch (Exception ex) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogWarning((object)("Could not read the server's hello: " + ex.Message)); } } } private void OnDirectValues(ZRpc rpc, ZPackage pkg) { if (IsServerConnection(rpc)) { TakeValues(pkg); } } private void OnRoutedValues(long sender, ZPackage pkg) { if (!_directSeen && !IsServer) { ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null); if (val != null && val.m_uid == sender) { TakeValues(pkg); } } } private void TakeValues(ZPackage pkg) { try { int num = pkg.ReadInt(); List<string> list = new List<string>(); for (int i = 0; i < num; i++) { string section = pkg.ReadString(); string key = pkg.ReadString(); string text = pkg.ReadString(); ConfigEntryBase val = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key)); if (val != null) { object obj; try { obj = TomlTypeConverter.ConvertToValue(text, val.SettingType); } catch (Exception) { continue; } if (!_own.ContainsKey(val)) { _own[val] = val.BoxedValue; } _server[val] = obj; if (!object.Equals(val.BoxedValue, obj)) { Apply(val, obj); list.Add(section + "/" + key + " = " + text); } } } ManualLogSource log = _log; if (log != null) { log.LogInfo((object)($"Settings from the server apply while you play here ({_server.Count})" + ((list.Count > 0) ? (": " + string.Join(", ", list.ToArray())) : ""))); } ShowReadOnly(); } catch (Exception ex2) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogWarning((object)("Could not read the server's settings: " + ex2.Message)); } } } private void Apply(ConfigEntryBase e, object value) { bool saveOnConfigSet = _config.SaveOnConfigSet; _applying = true; try { _config.SaveOnConfigSet = false; e.BoxedValue = value; } finally { _config.SaveOnConfigSet = saveOnConfigSet; _applying = false; } } private void Restore() { if (_server.Count == 0) { return; } foreach (KeyValuePair<ConfigEntryBase, object> item in _own) { Apply(item.Key, item.Value); } _own.Clear(); _server.Clear(); ShowReadOnly(); ManualLogSource log = _log; if (log != null) { log.LogInfo((object)"Your own settings apply again"); } } private void OnChanged(object sender, EventArgs args) { if (_applying) { return; } ConfigEntryBase val = (ConfigEntryBase)((sender is ConfigEntryBase) ? sender : null); if (val == null) { return; } if (_server.TryGetValue(val, out var value)) { if (!_reloading && CanEditServer) { SendEdit(val); } else { _own[val] = val.BoxedValue; } Apply(val, value); } else if (IsServer) { _changePending = true; if (Time.unscaledTime >= _nextChangeSend) { SendChange(); } } } private void SendChange() { _changePending = false; _nextChangeSend = Time.unscaledTime + 0.5f; if (!IsServer) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer?.m_rpc == null) { continue; } if (_directPeers.Contains(peer.m_rpc)) { if (_entries.Count > 0) { peer.m_rpc.Invoke(_dSend, new object[1] { Values() }); } } else { SendRouted(peer.m_uid); } } } private void SendEdit(ConfigEntryBase e) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetServerPeer() : null); if (val?.m_rpc != null) { ZPackage val2 = new ZPackage(); val2.Write(e.Definition.Section); val2.Write(e.Definition.Key); val2.Write(TomlTypeConverter.ConvertToString(e.BoxedValue, e.SettingType)); val.m_rpc.Invoke(_edit, new object[1] { val2 }); ManualLogSource log = _log; if (log != null) { log.LogInfo((object)("Asked the server to set " + e.Definition.Section + "/" + e.Definition.Key)); } } } private void OnEdit(ZRpc rpc, ZPackage pkg) { try { if (!IsServer) { return; } ISocket socket = rpc.GetSocket(); string text = ((socket != null) ? socket.GetHostName() : null) ?? ""; ZNetPeer val = ((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc)); string section = pkg.ReadString(); string key = pkg.ReadString(); string text2 = pkg.ReadString(); if (!ZNet.instance.IsAdmin(text)) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)((val?.m_playerName ?? text) + " tried to change " + section + "/" + key + " but isn't on the admin list")); } if (_entries.Count > 0) { rpc.Invoke(_dSend, new object[1] { Values() }); } return; } ConfigEntryBase val2 = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key)); if (val2 != null) { val2.BoxedValue = TomlTypeConverter.ConvertToValue(text2, val2.SettingType); ManualLogSource log2 = _log; if (log2 != null) { log2.LogInfo((object)("Admin " + (val?.m_playerName ?? text) + " set " + section + "/" + key + " = " + text2)); } } } catch (Exception ex) { ManualLogSource log3 = _log; if (log3 != null) { log3.LogWarning((object)("Could not take an admin's change: " + ex.Message)); } } } private void ShowReadOnly() { bool flag = FromServer && !CanEditServer; if (flag == _readOnlyShown) { return; } _readOnlyShown = flag; foreach (ConfigEntryBase entry in _entries) { ConfigDescription description = entry.Description; object[] array = ((description != null) ? description.Tags : null) ?? new object[0]; foreach (object obj in array) { if (IsManagerAttributes(obj)) { try { AccessTools.Field(obj.GetType(), "ReadOnly")?.SetValue(obj, flag ? ((object)true) : null); } catch (Exception) { } } } } } private static bool IsManagerAttributes(object tag) { if (tag != null) { return tag.GetType().Name == "ConfigurationManagerAttributes"; } return false; } private string OwnText(SyncedText t) { try { return t.Own() ?? ""; } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not read " + t.Key + ": " + ex.Message)); } return t.Given ?? ""; } } private void Give(SyncedText t, string text) { if (t.Given != null && t.Given == text) { return; } t.Given = text; try { t.Use(text); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not use " + t.Key + ": " + ex)); } } } private void RestoreTexts(bool give) { foreach (SyncedText text in _texts) { text.Incoming = null; if (!text.FromServer) { continue; } text.FromServer = false; if (give) { Give(text, OwnText(text)); ManualLogSource log = _log; if (log != null) { log.LogInfo((object)("Your own " + text.Key + " applies again")); } } } } private void AskTexts(ZRpc server) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if (_texts.Count == 0 || server == null) { return; } ZPackage val = new ZPackage(); val.Write(_texts.Count); foreach (SyncedText text in _texts) { val.Write(text.Key); } server.Invoke(_dTextAsk, new object[1] { val }); } private void OnTextAsk(ZRpc rpc, ZPackage pkg) { try { if (!IsServer) { return; } int num = pkg.ReadInt(); HashSet<string> hashSet = new HashSet<string>(); for (int i = 0; i < num && i < 1000; i++) { string key = pkg.ReadString(); if (_texts.Any((SyncedText x) => x.Key == key)) { hashSet.Add(key); } } if (_textPeers.TryGetValue(rpc, out var value)) { hashSet.UnionWith(value); } foreach (ZRpc item in _textPeers.Keys.Where((ZRpc r) => !r.IsConnected()).ToList()) { _textPeers.Remove(item); } _textPeers[rpc] = hashSet; foreach (SyncedText text in _texts) { if (hashSet.Contains(text.Key)) { SendText(rpc, text); } } } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not answer a player's ask for server data: " + ex.Message)); } } } private void SendTexts() { _textPending = false; _nextTextSend = Time.unscaledTime + 0.5f; if (!IsServer) { return; } foreach (SyncedText text in _texts) { if (!text.Pending) { continue; } text.Pending = false; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer?.m_rpc != null && _textPeers.TryGetValue(peer.m_rpc, out var value) && value.Contains(text.Key)) { SendText(peer.m_rpc, text); } } } } private void SendText(ZRpc rpc, SyncedText t) { byte[] array = Packed(t); if (array != null) { _outbox.RemoveAll((Sending s) => s.Rpc == rpc && s.Key == t.Key); _outbox.Add(new Sending { Rpc = rpc, Key = t.Key, Data = array, Parts = Math.Max(1, (array.Length + 65536 - 1) / 65536) }); Pump(); } } private void Pump() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown for (int num = _outbox.Count - 1; num >= 0; num--) { Sending sending = _outbox[num]; try { while (sending.Next < sending.Parts && sending.Rpc.IsConnected() && sending.Rpc.GetSocket().GetSendQueueSize() < 10240) { int num2 = sending.Next * 65536; int num3 = Math.Min(65536, sending.Data.Length - num2); byte[] array = new byte[num3]; Buffer.BlockCopy(sending.Data, num2, array, 0, num3); ZPackage val = new ZPackage(); val.Write(sending.Key); val.Write(sending.Next); val.Write(sending.Parts); val.Write(array); sending.Rpc.Invoke(_dText, new object[1] { val }); sending.Next++; } if (sending.Next >= sending.Parts || !sending.Rpc.IsConnected()) { _outbox.RemoveAt(num); } } catch (Exception ex) { _outbox.RemoveAt(num); ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Could not send " + sending.Key + " to a player: " + ex.Message)); } } } } private byte[] Packed(SyncedText t) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if (t.Packed == null) { string text = OwnText(t); ZPackage val = new ZPackage(); val.Write(text); ZPackage val2 = new ZPackage(); bool flag = text.Length > 1024; val2.Write(flag); if (flag) { val2.WriteCompressed(val); } else { val2.Write(val); } t.Packed = val2.GetArray(); t.TooBig = t.Packed.Length > 8388608; string arg = $"{t.Packed.Length / 1024} KB" + (flag ? $" gzipped ({text.Length / 1024} KB of text)" : ""); if (t.TooBig) { ManualLogSource log = _log; if (log != null) { log.LogError((object)$"{t.Key} is too big to send to players ({arg}, at most {8} MB): they keep their own."); } } else if (t.Packed.Length > 262144) { ManualLogSource log2 = _log; if (log2 != null) {