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 ProvisioningCache v0.3.11
BepInEx/plugins/ProvisioningCache/ProvisioningCache.dll
Decompiled 4 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using ProvisioningCache.Core; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ProvisioningCache")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.11.0")] [assembly: AssemblyInformationalVersion("0.3.11")] [assembly: AssemblyProduct("ProvisioningCache")] [assembly: AssemblyTitle("ProvisioningCache")] [assembly: AssemblyVersion("0.3.11.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 ProvisioningCache { internal sealed class CacheAccounts { internal const string OwnerKey = "pc.account.owner"; internal const string LinkKey = "pc.mp.account"; internal const string LedgerKey = "pc.mp.collections"; internal const string RevisionKey = "pc.mp.revision"; private readonly ZDOMan world; private readonly Dictionary<long, ZDO> records = new Dictionary<long, ZDO>(); internal IEnumerable<ZDO> Records => records.Values; internal CacheAccounts(ZDOMan world) { this.world = world; } internal ZDO Find(long owner) { if (!records.TryGetValue(owner, out var value)) { return null; } return value; } internal void Load(List<ZDO> accounts) { records.Clear(); foreach (ZDO item in from z in accounts orderby ((ZDOID)(ref z.m_uid)).UserID, ((ZDOID)(ref z.m_uid)).ID select z) { long num = item.GetLong("pc.account.owner", 0L); if (num != 0L) { if (records.ContainsKey(num)) { Plugin.Instance.ReportError("Duplicate cache account preserved for player " + num); continue; } item.SetOwner(ZNet.GetUID()); item.Persistent = true; records.Add(num, item); } } } internal ZDO GetOrCreate(long owner, ZDO piece) { //IL_0066: 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) if (records.TryGetValue(owner, out var value)) { return value; } string text = piece.GetString("pc.mp.state", ""); CacheState state = ((text.Length == 0) ? new CacheState { LastWorldSeconds = ZNet.instance.GetTimeSeconds() } : StateCodec.Decode(text)); CollectionLedger ledger = CollectionLedger.Decode(piece.GetString("pc.mp.collections", ""), state); value = world.CreateNewZDO(Vector3.zero, StringExtensionMethods.GetStableHashCode("pc_cache_account")); value.SetPrefab(StringExtensionMethods.GetStableHashCode("pc_cache_account")); value.Persistent = true; value.SetType((ObjectType)2); value.SetOwner(ZNet.GetUID()); if (text.Length > 0) { CopyPieceMetadata(piece, value); } value.Set("pc.account.owner", owner); RememberPiece(value, piece.m_uid); Save(value, state, ledger); records.Add(owner, value); return value; } internal void Attach(ZDO account, ZDO piece) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) CacheState state = StateCodec.Decode(account.GetString("pc.mp.state", "")); CacheOwner.Remember(account, piece); CacheBinding.Attach(state, ((ZDOID)(ref piece.m_uid)).UserID, ((ZDOID)(ref piece.m_uid)).ID, ZNet.instance.GetTimeSeconds()); RememberPiece(account, piece.m_uid); Save(account, state); } internal void Pause(ZDO account) { CacheState state = StateCodec.Decode(account.GetString("pc.mp.state", "")); CacheBinding.Pause(state, ZNet.instance.GetTimeSeconds()); Save(account, state); } internal void Advance(ZDO account, CacheState state) { if (BoundPiece(account, state) != null) { Production.Advance(state, ZNet.instance.GetTimeSeconds(), active: true); } else { CacheBinding.Pause(state, ZNet.instance.GetTimeSeconds()); } } internal ZDO FindForPiece(ZDOID id) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = world.GetZDO(id); if (zDO != null && zDO.GetPrefab() == StringExtensionMethods.GetStableHashCode("pc_provisioning_cache") && records.TryGetValue(zDO.GetLong("creator", 0L), out var value) && zDO.GetZDOID("pc.mp.account") == value.m_uid && value.GetInt(PieceKey(id), 0) == 1) { return value; } return ((IEnumerable<ZDO>)records.Values).FirstOrDefault((Func<ZDO, bool>)((ZDO record) => record.GetInt(PieceKey(id), 0) == 1)); } internal void Save(ZDO account, CacheState state, CollectionLedger ledger = null) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) string text = StateCodec.Encode(state); long num = account.GetLong("pc.mp.revision", 0L) + 1; account.SetOwner(ZNet.GetUID()); account.Set("pc.mp.state", text); if (ledger != null) { account.Set("pc.mp.collections", ledger.Encode()); } account.Set("pc.mp.revision", num); ZDO val = BoundPiece(account, state); if (val != null) { val.SetOwner(ZNet.GetUID()); val.Set("pc.mp.account", account.m_uid); val.Set("pc.mp.state", text); val.Set("pc.mp.revision", num); val.Set("pc.mp.used", account.GetInt("pc.mp.used", 0)); } } private ZDO BoundPiece(ZDO account, CacheState state) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (state.BoundUser == 0L || state.BoundId == 0) { return null; } ZDO zDO = world.GetZDO(new ZDOID(state.BoundUser, state.BoundId)); if (zDO == null || zDO.GetPrefab() != StringExtensionMethods.GetStableHashCode("pc_provisioning_cache") || zDO.GetLong("creator", 0L) != account.GetLong("pc.account.owner", 0L)) { return null; } return zDO; } private static string PieceKey(ZDOID id) { return "pc.account.piece." + ((ZDOID)(ref id)).UserID + "." + ((ZDOID)(ref id)).ID; } private static void RememberPiece(ZDO account, ZDOID id) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) account.Set(PieceKey(id), 1); } private static void CopyPieceMetadata(ZDO source, ZDO target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) List<KeyValuePair<int, float>> list = default(List<KeyValuePair<int, float>>); List<KeyValuePair<int, Vector3>> list2 = default(List<KeyValuePair<int, Vector3>>); List<KeyValuePair<int, Quaternion>> list3 = default(List<KeyValuePair<int, Quaternion>>); List<KeyValuePair<int, int>> list4 = default(List<KeyValuePair<int, int>>); List<KeyValuePair<int, long>> list5 = default(List<KeyValuePair<int, long>>); List<KeyValuePair<int, string>> list6 = default(List<KeyValuePair<int, string>>); List<KeyValuePair<int, byte[]>> list7 = default(List<KeyValuePair<int, byte[]>>); ZDOConnection val = default(ZDOConnection); ZDOExtraData.GetData(source.m_uid, ref list, ref list2, ref list3, ref list4, ref list5, ref list6, ref list7, ref val); if (list4 != null) { foreach (KeyValuePair<int, int> item in list4) { target.Set(item.Key, item.Value, false); } } if (list5 != null) { foreach (KeyValuePair<int, long> item2 in list5) { target.Set(item2.Key, item2.Value); } } if (list6 == null) { return; } foreach (KeyValuePair<int, string> item3 in list6) { target.Set(item3.Key, item3.Value); } } } internal sealed class CacheCommand : ConsoleCommand { private readonly bool admin; public override string Name { get { if (!admin) { return "cache"; } return "cache_admin"; } } public override string Help { get { if (!admin) { return "Open your own placed Provisioning Cache from anywhere."; } return "Open another player's cache: cache_admin <player name or character ID>. No arguments lists cache owners. Server admins only."; } } internal CacheCommand(bool admin) { this.admin = admin; } public override void Run(string[] args) { ((ConsoleCommand)this).Run(args, (Terminal)(object)Console.instance); } public override void Run(string[] args, Terminal context) { if (!admin && args.Length != 0) { if (context != null) { context.AddString("Usage: cache"); } return; } string text = Plugin.Instance.Network.OpenRemote(admin, string.Join(" ", args), context); if (text.Length > 0 && context != null) { context.AddString(text); } } internal static void Register() { CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CacheCommand(admin: false)); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CacheCommand(admin: true)); } } internal static class CacheInventory { internal static ItemData CreateItem(string id) { GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(id) : null); ItemData val2 = ((!Object.op_Implicit((Object)(object)val)) ? null : val.GetComponent<ItemDrop>()?.m_itemData); if (val2 == null) { return null; } ItemData obj = val2.Clone(); obj.m_dropPrefab = val; obj.m_stack = 1; obj.m_worldLevel = (byte)Game.m_worldLevel; return obj; } internal static bool TryAddOne(string id) { ItemData val = CreateItem(id); Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (val != null && inventory.CanAddItem(val, 1)) { return inventory.AddItem(val); } return false; } internal static void ShowPickups(Dictionary<string, int> received) { foreach (KeyValuePair<string, int> item in received) { ItemData val = CreateItem(item.Key); if (val != null) { ((Character)Player.m_localPlayer).ShowPickupMessage(val, item.Value); } } } } internal static class CacheModel { private static Mesh mesh; private static Material woodMaterial; internal static void Apply(GameObject cache) { //IL_00b7: 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) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: 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_0216: 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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: 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_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_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Expected O, but got Unknown //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab("wood_pole"); if (!Object.op_Implicit((Object)(object)prefab)) { throw new InvalidOperationException("Valheim wood pole prefab is unavailable."); } WearNTear component = prefab.GetComponent<WearNTear>(); Material val = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_new)) ? component.m_new : prefab).GetComponentsInChildren<MeshRenderer>(true).SelectMany((MeshRenderer renderer) => ((Renderer)renderer).sharedMaterials).FirstOrDefault((Func<Material, bool>)((Material candidate) => Object.op_Implicit((Object)(object)candidate))); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Valheim wood material is unavailable."); } if (!Object.op_Implicit((Object)(object)woodMaterial)) { woodMaterial = new Material(val) { name = "ProvisionCacheWood", mainTextureScale = Vector2.one, mainTextureOffset = Vector2.zero }; } val = woodMaterial; if (!Object.op_Implicit((Object)(object)mesh)) { mesh = ReadMesh(Assembly.GetExecutingAssembly().GetManifestResourceStream("ProvisioningCache.Model")); } BoxCollider[] array = (from c in cache.GetComponentsInChildren<BoxCollider>(true) where !((Collider)c).isTrigger select c).ToArray(); Bounds val2 = default(Bounds); bool flag = false; BoxCollider[] array2 = array; foreach (BoxCollider val3 in array2) { Matrix4x4 val4 = cache.transform.worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix; for (int num2 = 0; num2 < 8; num2++) { Vector3 val5 = ((Matrix4x4)(ref val4)).MultiplyPoint3x4(val3.center + Vector3.Scale(val3.size * 0.5f, new Vector3((float)(((num2 & 1) != 0) ? 1 : (-1)), (float)(((num2 & 2) != 0) ? 1 : (-1)), (float)(((num2 & 4) != 0) ? 1 : (-1))))); if (!flag) { ((Bounds)(ref val2))..ctor(val5, Vector3.zero); flag = true; } else { ((Bounds)(ref val2)).Encapsulate(val5); } } } float num3 = (flag ? Mathf.Max(((Bounds)(ref val2)).size.x, ((Bounds)(ref val2)).size.z) : 1f); if (num3 <= 0f) { num3 = 1f; } LODGroup[] componentsInChildren = cache.GetComponentsInChildren<LODGroup>(true); for (int num = 0; num < componentsInChildren.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren[num]); } Animator[] componentsInChildren2 = cache.GetComponentsInChildren<Animator>(true); for (int num = 0; num < componentsInChildren2.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[num]); } Animation[] componentsInChildren3 = cache.GetComponentsInChildren<Animation>(true); for (int num = 0; num < componentsInChildren3.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[num]); } Renderer[] componentsInChildren4 = cache.GetComponentsInChildren<Renderer>(true); for (int num = 0; num < componentsInChildren4.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[num]); } MeshFilter[] componentsInChildren5 = cache.GetComponentsInChildren<MeshFilter>(true); for (int num = 0; num < componentsInChildren5.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren5[num]); } Collider[] componentsInChildren6 = cache.GetComponentsInChildren<Collider>(true); for (int num = 0; num < componentsInChildren6.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren6[num]); } GameObject val6 = new GameObject("ProvisionCacheModel", new Type[2] { typeof(MeshFilter), typeof(MeshRenderer) }); val6.layer = cache.layer; val6.transform.SetParent(cache.transform, false); val6.transform.localScale = Vector3.one * num3; val6.GetComponent<MeshFilter>().sharedMesh = mesh; ((Renderer)val6.GetComponent<MeshRenderer>()).sharedMaterial = val; BoxCollider obj = cache.AddComponent<BoxCollider>(); Bounds bounds = mesh.bounds; obj.center = ((Bounds)(ref bounds)).center * num3; bounds = mesh.bounds; obj.size = ((Bounds)(ref bounds)).size * num3; WearNTear component2 = cache.GetComponent<WearNTear>(); component2.m_new = (component2.m_worn = (component2.m_broken = val6)); Plugin.Instance.ReportModel("Custom cache model: " + mesh.vertexCount + " vertices; Valheim material " + ((Object)val).name); } internal static Mesh ReadMesh(Stream stream) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016d: 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_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown using (stream) { if (stream == null) { throw new InvalidDataException("Embedded cache model is missing."); } using BinaryReader binaryReader = new BinaryReader(stream); if (binaryReader.ReadInt32() != 827147088) { throw new InvalidDataException("Invalid cache model header."); } int num = binaryReader.ReadInt32(); int num2 = binaryReader.ReadInt32(); if (num <= 0 || num2 <= 0 || num2 % 3 != 0 || stream.Length != 12 + (long)num * 32L + (long)num2 * 4L) { throw new InvalidDataException("Invalid cache model data."); } Vector3[] array = (Vector3[])(object)new Vector3[num]; Vector3[] array2 = (Vector3[])(object)new Vector3[num]; Vector2[] array3 = (Vector2[])(object)new Vector2[num]; Color[] array4 = (Color[])(object)new Color[num]; int[] array5 = new int[num2]; for (int i = 0; i < num; i++) { array[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array2[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array3[i] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle()); array4[i] = Color.white; } for (int j = 0; j < num2; j++) { array5[j] = binaryReader.ReadInt32(); if (array5[j] < 0 || array5[j] >= num) { throw new InvalidDataException("Invalid cache model triangle."); } } Mesh val = new Mesh { name = "ProvisionCache", indexFormat = (IndexFormat)(num > 65535), vertices = array, normals = array2, uv = array3, colors = array4, triangles = array5 }; val.RecalculateBounds(); val.RecalculateTangents(); val.UploadMeshData(true); return val; } } } public sealed class CacheModelScale : MonoBehaviour { public Vector3 BaseScale = Vector3.one; private void Awake() { ApplyScale(); } private void LateUpdate() { ApplyScale(); } internal void ApplyScale() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Plugin.Instance)) { Vector3 val = BaseScale * Plugin.Instance.ModelScale; if (((Component)this).transform.localScale != val) { ((Component)this).transform.localScale = val; } } } } internal static class CacheOwner { internal const string NameKey = "pc.account.ownerName"; internal static string OnlineName(long owner) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (owner == 0L) { return ""; } Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && localPlayer.GetPlayerID() == owner) { return localPlayer.GetPlayerName(); } if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZDOMan.instance == null) { return ""; } foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { ZDO zDO = ZDOMan.instance.GetZDO(player.m_characterID); if (zDO != null && zDO.GetLong(ZDOVars.s_playerID, 0L) == owner) { return player.m_name; } } return ""; } internal static void Remember(ZDO account, ZDO piece) { string text = OnlineName(account.GetLong("pc.account.owner", 0L)); if (string.IsNullOrWhiteSpace(text)) { text = piece.GetString("pc.account.ownerName", ""); } if (string.IsNullOrWhiteSpace(text)) { text = account.GetString("pc.account.ownerName", ""); } if (!string.IsNullOrWhiteSpace(text)) { account.Set("pc.account.ownerName", text); piece.Set("pc.account.ownerName", text); } } internal static string Name(ZDO piece) { if (piece == null) { return "Unknown owner"; } string text = piece.GetString("pc.account.ownerName", ""); if (string.IsNullOrWhiteSpace(text)) { text = OnlineName(piece.GetLong("pc.account.owner", piece.GetLong("creator", 0L))); } if (string.IsNullOrWhiteSpace(text)) { return "Unknown owner"; } text = text.Replace('<', '‹').Replace('>', '›').Replace('\r', ' ') .Replace('\n', ' ') .Trim(); if (text.Length <= 64) { return text; } return text.Substring(0, 61) + "…"; } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] internal static class CachePlacement { private static bool Prefix(Player __instance, Piece piece, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)piece) || !Object.op_Implicit((Object)(object)((Component)piece).GetComponent<CacheInteractable>()) || !MultiplayerCache.HasPlacedCache(__instance.GetPlayerID())) { return true; } ((Character)__instance).Message((MessageType)2, "You already have a Provisioning Cache. Remove it before building another.", 0, (Sprite)null, false); __result = false; return false; } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] internal static class CachePlacementScale { internal static void Prefix(GameObject ___m_placementGhost) { if (Object.op_Implicit((Object)(object)___m_placementGhost)) { CacheModelScale component = ___m_placementGhost.GetComponent<CacheModelScale>(); if (Object.op_Implicit((Object)(object)component)) { component.ApplyScale(); } } } } internal static class CacheScrollList { internal const float RowWidth = 822f; internal static ScrollRect Create(Transform parent, float y, float height, float contentHeight) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) Image obj = Image(parent, "Inset list border", 24f, y, 852f, height, new Color(0.38f, 0.34f, 0.26f, 0.8f)); Image(((Component)obj).transform, "Inset list", 1f, 1f, 850f, height - 2f, new Color(0.055f, 0.06f, 0.05f, 0.98f)); Image val = Image(((Component)obj).transform, "Viewport", 6f, 6f, 822f, height - 12f, Color.clear); ((Graphic)val).raycastTarget = true; ((Component)val).gameObject.AddComponent<RectMask2D>(); RectTransform content = Rect(((Component)val).transform, "Scrollable rows", 0f, 0f, 822f, Mathf.Max(height - 12f, contentHeight)); Image obj2 = Image(((Component)obj).transform, "Scroll track", 834f, 8f, 12f, height - 16f, new Color(0.18f, 0.19f, 0.16f)); ((Graphic)obj2).raycastTarget = true; Image val2 = Image((Transform)(object)Rect(((Component)obj2).transform, "Sliding area", 2f, 2f, 8f, height - 20f), "Scroll thumb", 0f, 0f, 8f, height - 20f, Color.white); ((Graphic)val2).rectTransform.anchorMin = Vector2.zero; ((Graphic)val2).rectTransform.anchorMax = Vector2.one; RectTransform rectTransform = ((Graphic)val2).rectTransform; Vector2 offsetMin = (((Graphic)val2).rectTransform.offsetMax = Vector2.zero); rectTransform.offsetMin = offsetMin; ((Graphic)val2).raycastTarget = true; Scrollbar val3 = ((Component)obj2).gameObject.AddComponent<Scrollbar>(); val3.handleRect = ((Graphic)val2).rectTransform; ((Selectable)val3).targetGraphic = (Graphic)(object)val2; val3.direction = (Direction)2; ColorBlock colors = ((Selectable)val3).colors; ((ColorBlock)(ref colors)).normalColor = new Color(0.58f, 0.48f, 0.32f); ((ColorBlock)(ref colors)).highlightedColor = new Color(0.94f, 0.73f, 0.36f); ((ColorBlock)(ref colors)).pressedColor = new Color(1f, 0.81f, 0.45f); ((ColorBlock)(ref colors)).selectedColor = new Color(0.68f, 0.56f, 0.36f); ((ColorBlock)(ref colors)).disabledColor = new Color(0.38f, 0.35f, 0.27f); ((ColorBlock)(ref colors)).colorMultiplier = 1f; ((ColorBlock)(ref colors)).fadeDuration = 0.1f; ((Selectable)val3).colors = colors; ((Selectable)val3).interactable = contentHeight > height - 12f; ScrollRect obj3 = ((Component)obj).gameObject.AddComponent<ScrollRect>(); obj3.viewport = ((Graphic)val).rectTransform; obj3.content = content; obj3.horizontal = false; obj3.vertical = true; obj3.movementType = (MovementType)2; obj3.inertia = false; obj3.scrollSensitivity = 630f; obj3.verticalScrollbar = val3; obj3.verticalScrollbarVisibility = (ScrollbarVisibility)0; return obj3; } private static RectTransform Rect(Transform parent, string name, float x, float y, float width, float height) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 1f); component.pivot = val; Vector2 anchorMin = (component.anchorMax = val); component.anchorMin = anchorMin; component.anchoredPosition = new Vector2(x, 0f - y); component.sizeDelta = new Vector2(width, height); return component; } private static Image Image(Transform parent, string name, float x, float y, float width, float height, Color color) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)Rect(parent, name, x, y, width, height)).gameObject.AddComponent<Image>(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } } internal sealed class CacheSession { private MultiplayerCache Network => Plugin.Instance.Network; private Player LocalPlayer => Player.m_localPlayer; internal CacheState State => Network.Snapshot; internal bool CanManage { get { if (!Network.IsOwner) { return Network.AdminOverride; } return true; } } internal bool IsOwner => Network.IsOwner; internal bool AdminOverride => Network.AdminOverride; internal string OwnerName => Network.OwnerName; internal bool Busy => Network.Busy; internal static bool Supported { get { if (Object.op_Implicit((Object)(object)ZNet.instance)) { return ZDOMan.instance != null; } return false; } } internal int Coins => Count("Coins"); internal bool Bind(ZDO cache, out string error) { return Network.Select(cache, out error); } internal void Tick() { Network.Refresh(); } private static GameObject Item(string id) { if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { return null; } return ObjectDB.instance.GetItemPrefab(id); } private static string SharedName(string id) { GameObject obj = Item(id); if (obj == null) { return null; } return obj.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_name; } internal int Count(string id) { string text = SharedName(id); if (!Object.op_Implicit((Object)(object)LocalPlayer) || text == null) { return 0; } return ((Humanoid)LocalPlayer).GetInventory().CountItems(text, -1, true); } internal string Reason(Offer offer) { if (CanManage) { if (!Busy) { return Upgrades.BlockReason(State, offer, Coins, (string boss) => Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetGlobalKey(boss), Count); } return "Waiting for the server…"; } return "Only the owner can upgrade."; } internal string Purchase(string id) { if (!Supported || State == null || !Object.op_Implicit((Object)(object)LocalPlayer)) { return "Cache unavailable."; } Tick(); Offer offer = Upgrades.Offers(State).Find((Offer o) => o.Id == id); if (offer == null) { return "Upgrade already purchased."; } string text = Reason(offer); if (text.Length > 0) { return text; } string result = Network.Send("purchase", id); if (!Network.Busy) { return result; } Inventory inventory = ((Humanoid)LocalPlayer).GetInventory(); inventory.RemoveItem(SharedName("Coins"), offer.Coins, -1, true); if (offer.SampleCount > 0) { inventory.RemoveItem(SharedName(offer.Sample), offer.SampleCount, -1, true); } return result; } internal string Allocate(IReadOnlyDictionary<string, int> draft) { if (!Supported || State == null) { return "Cache unavailable."; } if (!CanManage) { return "Only the owner can change allocation."; } return Network.Send("allocate", "", new Dictionary<string, int>(draft)); } internal string Collect() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown if (!Supported || State == null || !Object.op_Implicit((Object)(object)LocalPlayer)) { return "Cache unavailable."; } if (Busy) { return "Waiting for the server…"; } Tick(); Inventory inventory = ((Humanoid)LocalPlayer).GetInventory(); Inventory val = new Inventory("Cache collection preview", (Sprite)null, inventory.GetWidth(), inventory.GetHeight()); foreach (ItemData allItem in inventory.GetAllItems()) { val.GetAllItems().Add(allItem.Clone()); } Dictionary<string, int> dictionary = new Dictionary<string, int>(); Resource[] resources = Catalog.Resources; foreach (Resource resource in resources) { ItemData val2 = CacheInventory.CreateItem(resource.Id); if (val2 == null) { continue; } int j; for (j = 0; j < State.Resources[resource.Id].Stored && j < 100000; j++) { ItemData val3 = val2.Clone(); if (!val.CanAddItem(val3, 1) || !val.AddItem(val3)) { break; } } if (j > 0) { dictionary.Add(resource.Id, j); } } if (dictionary.Count != 0) { return Network.Send("collect", "", dictionary); } return "No items fit in your inventory, or the cache is empty."; } } internal sealed class CacheWindow { private enum Tab { Production, Upgrades, Licenses } private const float Width = 900f; private const float Height = 740f; private const float ProductionRowStep = 76f; private const float PurchaseRowStep = 86f; private const float TierHeadingStep = 34f; private static readonly Vector2 TopLeft = new Vector2(0f, 1f); private static readonly Color Ink = new Color(0.95f, 0.92f, 0.83f); private static readonly Color Muted = new Color(0.77f, 0.75f, 0.69f); private static readonly Color Gold = new Color(0.94f, 0.73f, 0.36f); private static readonly Color Green = new Color(0.66f, 0.81f, 0.6f); private static readonly Color Inset = new Color(0.075f, 0.085f, 0.075f, 0.94f); private GameObject panel; private GameObject content; private CacheInteractable target; private Text subtitle; private Text ownerLabel; private Text wallet; private Text speed; private Text storage; private Text status; private Text total; private Text draftHint; private Button apply; private Button collect; private Text tierCostLabel; private Image storageBar; private readonly Button[] tabs = (Button[])(object)new Button[3]; private readonly Image[] tabUnderlines = (Image[])(object)new Image[3]; private readonly Dictionary<string, int> draft = new Dictionary<string, int>(); private readonly Dictionary<string, Text> liveRows = new Dictionary<string, Text>(); private readonly Dictionary<string, Image> progressBars = new Dictionary<string, Image>(); private readonly Dictionary<string, Image> activityMarks = new Dictionary<string, Image>(); private readonly Dictionary<string, Button> increaseButtons = new Dictionary<string, Button>(); private readonly List<Tuple<Button, Offer>> purchaseButtons = new List<Tuple<Button, Offer>>(); private Tab currentTab; private bool inputBlocked; private ScrollRect listScroll; private Tab scrollTab; private readonly Dictionary<Tab, float> scrollOffsets = new Dictionary<Tab, float>(); private float nextRefresh; private CacheSession Session => Plugin.Instance.Session; private CacheState State => Session.State; private bool HasDraft { get { if (State != null) { return draft.Any((KeyValuePair<string, int> p) => p.Value != State.Resources[p.Key].Percent); } return false; } } internal bool IsOpen => Object.op_Implicit((Object)(object)panel); internal void Open(CacheInteractable cache) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) Close(); if (!Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront)) { return; } target = cache; panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 900f, 740f, false); Surface(panel.transform, "Tint", 12f, 12f, 876f, 716f, new Color(0.1f, 0.09f, 0.07f, 0.87f)); Label(panel.transform, "Provisioning Cache", 28f, 23f, 650f, 36f, 28, Ink, bold: true, (TextAnchor)3); subtitle = Label(panel.transform, "", 30f, 62f, 430f, 24f, 17, Gold, bold: false, (TextAnchor)3); ownerLabel = Label(panel.transform, "", 474f, 66f, 396f, 24f, 17, Ink, bold: false, (TextAnchor)5); ownerLabel.supportRichText = false; ownerLabel.horizontalOverflow = (HorizontalWrapMode)1; ownerLabel.resizeTextForBestFit = true; ownerLabel.resizeTextMinSize = 12; ownerLabel.resizeTextMaxSize = 17; Button(panel.transform, "Close", 786f, 27f, 86f, Close); Surface(panel.transform, "Summary", 24f, 98f, 852f, 60f, Inset); Label(panel.transform, "COINS", 40f, 103f, 165f, 18f, 13, Muted, bold: false, (TextAnchor)3); wallet = Label(panel.transform, "", 40f, 123f, 165f, 29f, 23, Gold, bold: false, (TextAnchor)3); Surface(panel.transform, "Divider", 220f, 110f, 1f, 36f, new Color(1f, 1f, 1f, 0.12f)); Label(panel.transform, "PRODUCTION SPEED", 242f, 103f, 210f, 18f, 13, Muted, bold: false, (TextAnchor)3); speed = Label(panel.transform, "", 242f, 123f, 210f, 29f, 23, null, bold: false, (TextAnchor)3); Surface(panel.transform, "Divider", 470f, 110f, 1f, 36f, new Color(1f, 1f, 1f, 0.12f)); Label(panel.transform, "STORAGE", 492f, 102f, 350f, 18f, 13, Muted, bold: false, (TextAnchor)3); storage = Label(panel.transform, "", 492f, 121f, 362f, 24f, 17, null, bold: false, (TextAnchor)3); storageBar = ProgressBar(panel.transform, 492f, 148f, 360f, 4f); for (int i = 0; i < tabs.Length; i++) { Tab tab = (Tab)i; float x = 28 + i * 177; tabs[i] = Button(panel.transform, (tab == Tab.Licenses) ? "Resources" : tab.ToString(), x, 171f, 165f, delegate { SwitchTab(tab); }); tabUnderlines[i] = Surface(panel.transform, "Active " + tab.ToString() + " tab", x, 212f, 165f, 3f, Gold); } status = Label(panel.transform, "Esc to close", 30f, 706f, 840f, 24f, 14, Muted, bold: false, (TextAnchor)3); draft.Clear(); foreach (KeyValuePair<string, ResourceState> resource in State.Resources) { draft[resource.Key] = resource.Value.Percent; } currentTab = Tab.Production; BuildContent(); Refresh(); ScaleToScreen(); GUIManager.BlockInput(true); inputBlocked = true; } internal void NetworkChanged(string message, bool resetDraft) { if (!Object.op_Implicit((Object)(object)panel) || State == null) { return; } if (resetDraft) { draft.Clear(); foreach (KeyValuePair<string, ResourceState> resource in State.Resources) { draft[resource.Key] = resource.Value.Percent; } BuildContent(); } Refresh(); Notify(message); } internal void Close() { if (Object.op_Implicit((Object)(object)panel)) { Object.Destroy((Object)(object)panel); } panel = null; content = null; target = null; listScroll = null; scrollOffsets.Clear(); tierCostLabel = null; liveRows.Clear(); progressBars.Clear(); activityMarks.Clear(); increaseButtons.Clear(); purchaseButtons.Clear(); if (inputBlocked) { GUIManager.BlockInput(false); } inputBlocked = false; } internal void Update() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)panel)) { if (inputBlocked) { Close(); } return; } bool remote = Plugin.Instance.Network.Remote; if ((!remote && !Object.op_Implicit((Object)(object)target)) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || ((Character)Player.m_localPlayer).IsDead() || !CacheSession.Supported || State == null || !Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront) || (!remote && (Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)target).transform.position) > 5f || !PrivateArea.CheckAccess(((Component)target).transform.position, 0f, false, false)))) { Close(); return; } if (Input.GetKeyDown((KeyCode)27)) { Close(); return; } ScaleToScreen(); if (Time.unscaledTime >= nextRefresh) { nextRefresh = Time.unscaledTime + 0.25f; Refresh(); } RefreshProgress(); } private void ScaleToScreen() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) //IL_0049: Unknown result type (might be due to invalid IL or missing references) Rect rect = GUIManager.CustomGUIFront.GetComponent<RectTransform>().rect; panel.transform.localScale = Vector3.one * Mathf.Min(1f, Mathf.Min(((Rect)(ref rect)).width / 924f, ((Rect)(ref rect)).height / 764f)); } private void SwitchTab(Tab tab) { currentTab = tab; BuildContent(); Refresh(); } private void BuildContent() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)listScroll)) { scrollOffsets[scrollTab] = listScroll.content.anchoredPosition.y; } listScroll = null; if (Object.op_Implicit((Object)(object)content)) { content.SetActive(false); Object.Destroy((Object)(object)content); } content = new GameObject("CacheContent", new Type[1] { typeof(RectTransform) }); RectTransform component = content.GetComponent<RectTransform>(); ((Transform)component).SetParent(panel.transform, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; Vector2 offsetMin = (component.offsetMax = Vector2.zero); component.offsetMin = offsetMin; liveRows.Clear(); progressBars.Clear(); activityMarks.Clear(); increaseButtons.Clear(); purchaseButtons.Clear(); total = null; draftHint = null; apply = null; collect = null; tierCostLabel = null; for (int i = 0; i < tabs.Length; i++) { bool flag = currentTab == (Tab)i; ((Component)tabUnderlines[i]).gameObject.SetActive(flag); TintButton(tabs[i], flag); } if (currentTab == Tab.Production) { BuildProduction(); } else { BuildPurchases(); } if (Object.op_Implicit((Object)(object)listScroll)) { Canvas.ForceUpdateCanvases(); Rect rect = listScroll.content.rect; float height = ((Rect)(ref rect)).height; rect = listScroll.viewport.rect; float num = Mathf.Max(0f, height - ((Rect)(ref rect)).height); listScroll.content.anchoredPosition = new Vector2(0f, Mathf.Clamp(scrollOffsets.TryGetValue(currentTab, out var value) ? value : 0f, 0f, num)); listScroll.StopMovement(); } } private void BuildProduction() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) List<Resource> list = (from resource in Catalog.Resources where State.Resources[resource.Id].Unlocked orderby State.Resources[resource.Id].Percent > 0 descending, 60.0 * State.Speed * (double)State.Resources[resource.Id].Percent / (100.0 * resource.Work) descending select resource).ToList(); Label(content.transform, "RESOURCE / NEXT ITEM", 102f, 222f, 330f, 20f, 13, Muted, bold: false, (TextAnchor)3); Label(content.transform, "ALLOCATION", 504f, 222f, 170f, 20f, 13, Muted, bold: false, (TextAnchor)4); Label(content.transform, "READY", 753f, 222f, 76f, 20f, 13, Muted, bold: false, (TextAnchor)4); Transform val = CreateList(246f, 394f, list.Count, 76f); int num = 0; foreach (Resource r in list) { float num2 = (float)num++ * 76f; Surface(val, r.Name + " row", 0f, num2, 822f, 70f, Inset); activityMarks[r.Id] = Surface(val, "Activity", 0f, num2 + 8f, 3f, 54f, Gold); ItemIcon(val, r.Id, 14f, num2 + 14f, 42f); Label(val, r.Name, 72f, num2 + 5f, 345f, 25f, 20, Ink, bold: true, (TextAnchor)3); liveRows[r.Id] = Label(val, "", 72f, num2 + 31f, 340f, 23f, 16, Muted, bold: false, (TextAnchor)3); progressBars[r.Id] = ProgressBar(val, 72f, num2 + 62f, 325f, 4f); if (State.AllocationUnlocked) { GameObject val2 = GUIManager.Instance.CreateInputField(val, TopLeft, TopLeft, new Vector2(546f, 0f - num2 - 35f), (ContentType)2, "0", 19, 70f, 38f); InputField input = val2.GetComponent<InputField>(); input.characterLimit = 3; input.textComponent.alignment = (TextAnchor)4; input.SetTextWithoutNotify(draft[r.Id].ToString()); ((UnityEvent<string>)(object)input.onValueChanged).AddListener((UnityAction<string>)delegate(string value) { draft[r.Id] = (int.TryParse(value, out var result) ? result : (-1)); UpdateTotal(); }); Button(val, "−", 460f, num2 + 15f, 42f, delegate { input.text = Math.Max(0, draft[r.Id] - 5).ToString(); }); increaseButtons[r.Id] = Button(val, "+", 602f, num2 + 15f, 42f, delegate { input.text = Math.Min(100, draft[r.Id] + 5).ToString(); }); Label(val, "%", 655f, num2 + 20f, 25f, 27f, 17, Muted, bold: false, (TextAnchor)3); } else { Button(val, "Produce only", 460f, num2 + 15f, 205f, delegate { foreach (string item in draft.Keys.ToList()) { draft[item] = ((item == r.Id) ? Math.Min(100, State.MaxAllocation) : 0); } Notify(Session.Allocate(draft)); BuildContent(); Refresh(); }); } liveRows[r.Id + "_stock"] = Label(val, "", 723f, num2 + 15f, 76f, 40f, 26, Ink, bold: true, (TextAnchor)4); } ListFooter(list.Count, "resources"); Surface(content.transform, "Allocation footer", 24f, 658f, 852f, 40f, Inset); total = Label(content.transform, "", 40f, 662f, 378f, 20f, 16, null, bold: false, (TextAnchor)3); draftHint = Label(content.transform, "", 40f, 680f, 378f, 18f, 12, Muted, bold: false, (TextAnchor)3); if (State.AllocationUnlocked) { apply = Button(content.transform, "Apply changes", 468f, 658f, 202f, delegate { Notify(Session.Allocate(draft)); BuildContent(); Refresh(); }); } collect = Button(content.transform, "Collect all", 690f, 658f, 170f, delegate { Notify(Session.Collect()); Refresh(); }); TintButton(collect, prominent: true); UpdateTotal(); } private void BuildPurchases() { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) bool licenses = currentTab == Tab.Licenses; List<Offer> list = (from o in Upgrades.Offers(State) where Catalog.Find(o.Id) != null == licenses orderby o.Tier, (Session.Reason(o).Length != 0) ? 1 : 0 select o).ToList(); Offer offer = (licenses ? null : list.Find((Offer o) => o.Id == "tier")); if (offer != null) { list.Remove(offer); } Label(content.transform, licenses ? "RESOURCE LICENSES" : ((offer != null) ? "NEXT CACHE TIER" : "CACHE UPGRADES"), 30f, 222f, 810f, 20f, 13, (offer != null) ? Gold : Muted, bold: false, (TextAnchor)3); if (offer != null) { PurchaseRow(content.transform, offer, 246f, prominent: true); } float height = ((offer != null) ? 302 : 394); int headings = (licenses ? list.Select((Offer o) => o.Tier).Distinct().Count() : 0); Transform parent = CreateList((offer != null) ? 338 : 246, height, list.Count, 86f, headings); float num = 0f; int num2 = -1; foreach (Offer item in list) { if (licenses && item.Tier != num2) { Label(parent, "TIER " + item.Tier, 14f, num + 4f, 110f, 23f, 15, Muted, bold: true, (TextAnchor)3); Surface(parent, "Tier divider", 124f, num + 16f, 682f, 1f, new Color(Muted.r, Muted.g, Muted.b, 0.22f)); num += 34f; num2 = item.Tier; } PurchaseRow(parent, item, num); num += 86f; } if (list.Count == 0) { Label(parent, licenses ? "All resource licenses purchased." : "All available rank upgrades purchased.", 16f, 24f, 790f, 60f, 22, Gold, bold: false, (TextAnchor)3); } ListFooter(list.Count, licenses ? "licenses" : "rank upgrades"); Label(content.transform, licenses ? "Unlock resources with Coins and five samples from your inventory." : "Upgrades use Coins from your inventory.", 30f, 669f, 835f, 27f, 15, Muted, bold: false, (TextAnchor)3); } private void PurchaseRow(Transform parent, Offer offer, float y, bool prominent = false) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) float num = (prominent ? 24 : 0); if (prominent) { Surface(parent, "Cache tier border", num, y, 852f, 80f, new Color(Gold.r, Gold.g, Gold.b, 0.7f)); Surface(parent, "Cache tier inset", num + 2f, y + 2f, 848f, 76f, new Color(0.14f, 0.12f, 0.075f, 0.98f)); Surface(parent, "Cache tier accent", num, y, 4f, 80f, Gold); } else { Surface(parent, offer.Name + " row", num, y, 822f, 80f, Inset); } object obj; if (!prominent) { obj = null; } else if (!Object.op_Implicit((Object)(object)target)) { GameObject prefab = PrefabManager.Instance.GetPrefab("pc_provisioning_cache"); obj = ((prefab != null) ? prefab.GetComponent<Piece>() : null); } else { obj = ((Component)target).GetComponent<Piece>(); } Piece val = (Piece)obj; if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.m_icon)) { Image obj2 = Surface(parent, "Cache tier icon", num + 14f, y + 19f, 42f, 42f, Color.white); obj2.sprite = val.m_icon; obj2.preserveAspect = true; } else { string prefab2 = ((offer.Sample.Length > 0) ? offer.Sample : ((offer.Id == "storage") ? "Wood" : "Hammer")); ItemIcon(parent, prefab2, num + 14f, y + 19f, 42f); } Label(parent, offer.Name, num + 72f, y + 4f, 550f, 25f, 19, prominent ? Gold : Ink, bold: true, (TextAnchor)3); liveRows[offer.Id + "_detail"] = Label(parent, "", num + 72f, y + 32f, 550f, 22f, 16, Muted, bold: false, (TextAnchor)3); liveRows[offer.Id] = Label(parent, "", num + 72f, y + 56f, 550f, 21f, 15, null, bold: false, (TextAnchor)3); Action action = delegate { Notify(Session.Purchase(offer.Id)); BuildContent(); Refresh(); }; Button item = (prominent ? TierButton(parent, offer, y, action) : Button(parent, offer.Coins + " Coins", 648f, y + 20f, 158f, action)); purchaseButtons.Add(Tuple.Create<Button, Offer>(item, offer)); } private Button TierButton(Transform parent, Offer offer, float y, Action purchase) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) tierCostLabel = Label(parent, offer.Coins + " Coins", 702f, y + 6f, 158f, 22f, 16, Gold, bold: true, (TextAnchor)4); return Button(parent, "Upgrade Tier", 702f, y + 32f, 158f, purchase); } private Transform CreateList(float y, float height, int count, float rowStep, int headings = 0) { float contentHeight = Mathf.Max(0f, (float)count * rowStep + (float)headings * 34f - 6f); listScroll = CacheScrollList.Create(content.transform, y, height, contentHeight); scrollTab = currentTab; return (Transform)(object)listScroll.content; } private void ListFooter(int count, string noun) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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) Rect rect = listScroll.content.rect; float height = ((Rect)(ref rect)).height; rect = listScroll.viewport.rect; if (height > ((Rect)(ref rect)).height) { Label(content.transform, "Mouse wheel to scroll", 30f, 641f, 460f, 16f, 13, Muted, bold: false, (TextAnchor)3); } Label(content.transform, count + " " + noun, 664f, 641f, 200f, 16f, 13, Muted, bold: false, (TextAnchor)5); } private void Notify(string message) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) status.text = message; ((Graphic)status).color = Gold; } private void UpdateTotal() { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)total)) { return; } foreach (KeyValuePair<string, Button> increaseButton in increaseButtons) { ((Selectable)increaseButton.Value).interactable = draft[increaseButton.Key] < 100; TintButton(increaseButton.Value, prominent: false); } int num = draft.Values.Sum(); bool flag = num <= State.MaxAllocation && draft.Values.All((int v) => v >= 0 && v <= 100); total.text = (State.AllocationUnlocked ? ("Allocated " + num + "% / " + State.MaxAllocation + "%") : (num + "% / " + State.MaxAllocation + "% · Single resource")); ((Graphic)total).color = (Color)(flag ? Ink : new Color(0.97f, 0.64f, 0.46f)); draftHint.text = ((!State.AllocationUnlocked) ? "Upgrade Allocation to split your production." : ((!flag) ? ("Each resource ≤100%; total ≤" + State.MaxAllocation + "%.") : (HasDraft ? "Unsaved changes · apply when ready" : ("Saved · " + (State.MaxAllocation - num) + "% unassigned")))); ((Graphic)draftHint).color = ((flag && !HasDraft) ? Green : Muted); if (Object.op_Implicit((Object)(object)apply)) { ((Selectable)apply).interactable = Session.CanManage && !Session.Busy && flag && HasDraft; TintButton(apply, flag && HasDraft); } } private void Refresh() { //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_017c: 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_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_0548: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)panel) || State == null) { return; } subtitle.text = Catalog.TierNames[State.Tier - 1] + " Cache · Tier " + State.Tier; ownerLabel.text = "Owner: " + Session.OwnerName + (Session.AdminOverride ? " (Admin)" : (Session.IsOwner ? " (You)" : "")); wallet.text = Session.Coins.ToString("N0"); speed.text = State.Speed.ToString("0.##") + "×"; bool flag = State.UsedWork >= State.Capacity - 0.0001; storage.text = Mathf.Clamp((float)(State.UsedWork / State.Capacity * 100.0), 0f, 100f).ToString("0.#") + "% full" + (flag ? " · FULL" : ""); ((Graphic)storage).color = (flag ? Gold : Ink); ((Graphic)storageBar).rectTransform.anchorMax = new Vector2(Mathf.Clamp01((float)(State.UsedWork / State.Capacity)), 1f); ((Graphic)storageBar).color = Gold; if (currentTab != Tab.Production) { foreach (Tuple<Button, Offer> purchaseButton in purchaseButtons) { Offer item = purchaseButton.Item2; string text = Session.Reason(item); bool flag2 = text.Length == 0; ((Selectable)purchaseButton.Item1).interactable = flag2; if (item.Id == "tier") { TintButton(purchaseButton.Item1, flag2); ((Graphic)tierCostLabel).color = (flag2 ? Gold : Muted); } else { TintButton(purchaseButton.Item1, flag2); } Text obj = liveRows[item.Id]; obj.text = ((text.Length == 0) ? "Ready to purchase" : text); ((Graphic)obj).color = ((text.Length == 0) ? Green : Gold); Resource resource = Catalog.Find(item.Sample); liveRows[item.Id + "_detail"].text = ((resource != null) ? ((60.0 * State.Speed / resource.Work).ToString("0.##") + "/hr at 100% · Samples " + Session.Count(item.Sample) + "/" + item.SampleCount) : ((item.Id == "tier") ? "Unlock the next resource tier · +10% total allocation." : ((item.Id == "max_allocation") ? (State.MaxAllocation + "% → " + (State.MaxAllocation + 5) + "% total allocation") : item.Description))); } } else { Resource[] resources = Catalog.Resources; foreach (Resource resource2 in resources) { if (liveRows.TryGetValue(resource2.Id, out var value)) { ResourceState resourceState = State.Resources[resource2.Id]; double num = State.Speed * (double)resourceState.Percent / 100.0; value.text = ((num <= 0.0) ? "Idle" : ((60.0 * num / resource2.Work).ToString("0.##") + "/hr · " + resourceState.Percent + "% active" + (flag ? " · Full" : ""))); ((Graphic)value).color = (Color)((num > 0.0) ? Muted : new Color(0.6f, 0.61f, 0.57f)); Text obj2 = liveRows[resource2.Id + "_stock"]; obj2.text = resourceState.Stored.ToString("N0"); ((Graphic)obj2).color = ((resourceState.Stored > 0) ? Gold : Muted); ((Graphic)activityMarks[resource2.Id]).color = ((num > 0.0) ? Gold : Color.clear); } } if (Object.op_Implicit((Object)(object)collect)) { ((Selectable)collect).interactable = !Session.Busy && State.Resources.Values.Any((ResourceState r) => r.Stored > 0); } UpdateTotal(); } RefreshProgress(); } private void RefreshProgress() { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if (State == null || currentTab != Tab.Production || !Object.op_Implicit((Object)(object)ZNet.instance)) { return; } double num = Math.Max(0.0, ZNet.instance.GetTimeSeconds() - State.LastWorldSeconds); double num2 = ((State.AssignedMultiplier == 0.0) ? 0.0 : Math.Min(num / 60.0 * State.Speed, Math.Max(0.0, State.Capacity - State.UsedWork) / State.AssignedMultiplier)); foreach (KeyValuePair<string, Image> progressBar in progressBars) { ResourceState resourceState = State.Resources[progressBar.Key]; float num3 = Mathf.Clamp01((float)((resourceState.Progress + num2 * (double)resourceState.Percent / 100.0) / Catalog.Find(progressBar.Key).Work)); ((Graphic)progressBar.Value).rectTransform.anchorMax = new Vector2(num3, 1f); ((Graphic)progressBar.Value).color = (Color)((resourceState.Percent > 0) ? Gold : new Color(0.39f, 0.41f, 0.37f)); } } private static Image Surface(Transform parent, string name, float x, float y, float width, float height, Color color) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); Vector2 val2 = (component.pivot = TopLeft); Vector2 anchorMin = (component.anchorMax = val2); component.anchorMin = anchorMin; component.anchoredPosition = new Vector2(x, 0f - y); component.sizeDelta = new Vector2(width, height); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = color; ((Graphic)component2).raycastTarget = false; return component2; } private static Image ProgressBar(Transform parent, float x, float y, float width, float height) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) Image val = Surface(((Component)Surface(parent, "Progress track", x, y, width, height, new Color(0.25f, 0.26f, 0.23f))).transform, "Progress", 0f, 0f, 0f, 0f, Gold); ((Graphic)val).rectTransform.anchorMin = Vector2.zero; ((Graphic)val).rectTransform.anchorMax = new Vector2(0f, 1f); RectTransform rectTransform = ((Graphic)val).rectTransform; Vector2 offsetMin = (((Graphic)val).rectTransform.offsetMax = Vector2.zero); rectTransform.offsetMin = offsetMin; return val; } private static void ItemIcon(Transform parent, string prefab, float x, float y, float size) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) object obj; if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { obj = null; } else { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } ItemDrop val = (ItemDrop)obj; if (Object.op_Implicit((Object)(object)val)) { Sprite icon = val.m_itemData.GetIcon(); if (Object.op_Implicit((Object)(object)icon)) { Image obj2 = Surface(parent, prefab + " icon", x, y, size, size, Color.white); obj2.sprite = icon; obj2.preserveAspect = true; } } } private static Text Label(Transform parent, string text, float x, float y, float width, float height, int size, Color? color = null, bool bold = false, TextAnchor alignment = (TextAnchor)3) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) Text component = GUIManager.Instance.CreateText(text, parent, TopLeft, TopLeft, new Vector2(x + width / 2f, 0f - y - height / 2f), bold ? GUIManager.Instance.AveriaSerifBold : GUIManager.Instance.AveriaSerif, size, (Color)(((??)color) ?? Ink), false, Color.black, width, height, false).GetComponent<Text>(); component.alignment = alignment; ((Graphic)component).raycastTarget = false; component.horizontalOverflow = (HorizontalWrapMode)0; return component; } private static Button Button(Transform parent, string label, float x, float y, float width, Action action) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_005e: Expected O, but got Unknown Button component = GUIManager.Instance.CreateButton(label, parent, TopLeft, TopLeft, new Vector2(x + width / 2f, 0f - y - 20f), width, 40f).GetComponent<Button>(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { action(); }); TintButton(component, prominent: false); return component; } private static void TintButton(Button button, bool prominent) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Text componentInChildren = ((Component)button).GetComponentInChildren<Text>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { ((Graphic)componentInChildren).color = ((!((Selectable)button).interactable) ? Muted : (prominent ? Gold : Ink)); componentInChildren.fontSize = 17; } ColorBlock colors = ((Selectable)button).colors; ((ColorBlock)(ref colors)).normalColor = (prominent ? new Color(1f, 0.94f, 0.8f) : new Color(0.78f, 0.8f, 0.76f)); ((ColorBlock)(ref colors)).highlightedColor = Color.white; ((ColorBlock)(ref colors)).disabledColor = new Color(0.52f, 0.54f, 0.5f, 0.8f); ((Selectable)button).colors = colors; } } internal sealed class MultiplayerCache { private sealed class Command { internal long World; internal long Nonce; internal ZDOID Cache; internal string Action; internal string Argument; internal CacheAccess Access; internal int Tier; internal int Speed; internal int Storage; internal int Allocation; internal Dictionary<string, int> Counts = new Dictionary<string, int>(); internal ZPackage Encode() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00aa: Expected O, but got Unknown ZPackage val = new ZPackage(); string text = ((Access == CacheAccess.AdminRemote) ? "admin_" : ((Access == CacheAccess.OwnerRemote) ? "remote_" : "")); val.Write(World); val.Write(Cache); val.Write(Nonce); val.Write(text + Action); val.Write(Argument); val.Write(Tier); val.Write(Speed); val.Write(Storage); val.Write(Allocation); WriteCounts(val, Counts); return val; } internal static Command Read(ZPackage p) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Command command = new Command { World = p.ReadLong(), Cache = p.ReadZDOID(), Nonce = p.ReadLong(), Action = p.ReadString(), Argument = p.ReadString(), Tier = p.ReadInt(), Speed = p.ReadInt(), Storage = p.ReadInt(), Allocation = p.ReadInt(), Counts = ReadCounts(p) }; if (command.Nonce <= 0 || command.Argument.Length > 32768 || command.Action.Length > 32) { throw new InvalidDataException("Invalid cache request."); } if (command.Action.StartsWith("admin_", StringComparison.Ordinal)) { command.Access = CacheAccess.AdminRemote; command.Action = command.Action.Substring(6); } else if (command.Action.StartsWith("remote_", StringComparison.Ordinal)) { command.Access = CacheAccess.OwnerRemote; command.Action = command.Action.Substring(7); } return command; } } internal const string StateKey = "pc.mp.state"; private const string RequestRpc = "PC_Request_v2"; private const string ReplyRpc = "PC_Reply_v2"; private const string PlacementRpc = "PC_PlacementRejected"; internal const string DuplicateMessage = "You already have a Provisioning Cache. Remove it before building another."; private ZRoutedRpc registered; private ZDOMan world; private readonly List<ZDO> caches = new List<ZDO>(); private readonly List<ZDO> accountRecords = new List<ZDO>(); private readonly Dictionary<long, ZDO> owners = new Dictionary<long, ZDO>(); private CacheAccounts accounts; private int scan; private int accountScan; private bool scannedCaches; private bool scannedAccounts; private bool ready; private float nextScan; private float retry; private float nextRefund; internal bool Busy; internal ZDOID Selected; internal CacheState Snapshot; private long snapshotRevision; private long requestId; private string pending = ""; private Player escrowPlayer; private const string RemoteRequestRpc = "PC_RemoteOpen"; private const string RemoteReplyRpc = "PC_RemoteSnapshot"; private CacheAccess selectedAccess; private long remoteOwner; private long remoteRequest; private string remoteOwnerName = ""; private bool remoteAwaiting; private bool remoteOpening; private float nextRemoteSnapshot; private float remoteTimeout; private Terminal remoteTerminal; private static string WorldKey => ZNet.instance.GetWorldUID().ToString(); private static string EscrowKey => "pc.mp.pending.v1." + WorldKey; private static string DeliveryKey => "pc.mp.delivery.v1." + WorldKey; private static string RefundKey => "pc.mp.refund.v1." + WorldKey; private static long ServerId { get { if (!ZNet.instance.IsServer()) { return ZNet.instance.GetServerPeer()?.m_uid ?? 0; } return ZNet.GetUID(); } } internal bool IsOwner { get { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { long? obj2; if (!Remote) { ZDOMan obj = world; if (obj == null) { obj2 = null; } else { ZDO zDO = obj.GetZDO(Selected); obj2 = ((zDO != null) ? new long?(zDO.GetLong("creator", 0L)) : ((long?)null)); } } else { obj2 = remoteOwner; } return obj2 == Player.m_localPlayer.GetPlayerID(); } return false; } } internal string OwnerName { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!Remote) { ZDOMan obj = world; return CacheOwner.Name((obj != null) ? obj.GetZDO(Selected) : null); } return remoteOwnerName; } } internal bool Remote => selectedAccess != CacheAccess.Nearby; internal bool AdminOverride => selectedAccess == CacheAccess.AdminRemote; internal void Update() { //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZRoutedRpc.instance == null || ZDOMan.instance == null) { registered = null; world = null; ready = false; return; } if (registered != ZRoutedRpc.instance) { registered = ZRoutedRpc.instance; registered.Register<ZPackage>("PC_Request_v2", (Action<long, ZPackage>)Request); registered.Register<ZPackage>("PC_Reply_v2", (Action<long, ZPackage>)Reply); registered.Register<string>("PC_PlacementRejected", (Action<long, string>)PlacementRejected); registered.Register<ZPackage>("PC_RemoteOpen", (Action<long, ZPackage>)RemoteRequest); registered.Register<ZPackage>("PC_RemoteSnapshot", (Action<long, ZPackage>)RemoteReply); } if (world != ZDOMan.instance) { world = ZDOMan.instance; accounts = new CacheAccounts(world); caches.Clear(); accountRecords.Clear(); owners.Clear(); scan = (accountScan = 0); scannedCaches = (scannedAccounts = (ready = false)); nextScan = 0f; Snapshot = null; Selected = ZDOID.None; snapshotRevision = 0L; pending = ""; Busy = false; escrowPlayer = null; ResetRemote(); } if (ZNet.instance.IsServer() && Object.op_Implicit((Object)(object)ObjectDB.instance) && Time.unscaledTime >= nextScan) { if (!scannedCaches) { if (scan == 0) { caches.Clear(); } scannedCaches = world.GetAllZDOsWithPrefabIterative("pc_provisioning_cache", caches, ref scan); } if (!scannedAccounts) { if (accountScan == 0) { accountRecords.Clear(); } scannedAccounts = world.GetAllZDOsWithPrefabIterative("pc_cache_account", accountRecords, ref accountScan); } if (scannedCaches && scannedAccounts) { Reconcile(); ready = true; scan = (accountScan = 0); scannedCaches = (scannedAccounts = false); nextScan = Time.unscaledTime + 2f; } } Player localPlayer = Player.m_localPlayer; UpdateRemote(); if (Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)escrowPlayer != (Object)(object)localPlayer) { escrowPlayer = localPlayer; pending = (localPlayer.m_customData.TryGetValue(EscrowKey, out var value) ? value : ""); Busy = pending.Length > 0; retry = 0f; } if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && Object.op_Implicit((Object)(object)ObjectDB.instance) && Time.unscaledTime >= nextRefund) { nextRefund = Time.unscaledTime + 1f; FlushRefunds(); } if (!Object.op_Implicit((Object)(object)localPlayer) || !Busy || pending.Length <= 0 || ServerId == 0L || !(Time.unscaledTime >= retry)) { return; } retry = Time.unscaledTime + 3f; try { registered.InvokeRoutedRPC(ServerId, "PC_Request_v2", new object[1] { (object)new ZPackage(Convert.FromBase64String(pending)) }); } catch (Exception ex) { Plugin.Instance.ReportError("Cache request retry: " + ex.Message); } } private void Reconcile() { accounts.Load(accountRecords); owners.Clear(); foreach (ZDO item in from z in caches orderby z.GetString("pc.mp.state", "").Length > 0 descending, ((ZDOID)(ref z.m_uid)).UserID, ((ZDOID)(ref z.m_uid)).ID select z) { long num = item.GetLong("creator", 0L); if (num == 0L) { continue; } if (owners.ContainsKey(num)) { item.SetOwner(ZNet.GetUID()); item.Set("pc.mp.duplicate", true); try { DropBuildRefund(item, "Wood", 20); DropBuildRefund(item, "Stone", 10); world.DestroyZDO(item); NotifyPlacementRejected(num); } catch (Exception ex) { Plugin.Instance.ReportError("Duplicate cache refund will retry: " + ex.Message); } } else { owners.Add(num, item); try { accounts.Attach(accounts.GetOrCreate(num, item), item); } catch (Exception ex2) { Plugin.Instance.ReportError("Cache data preserved: " + ex2.Message); } } } foreach (ZDO item2 in accounts.Records.Where((ZDO a) => !owners.ContainsKey(a.GetLong("pc.account.owner", 0L)))) { try { accounts.Pause(item2); } catch (Exception ex3) { Plugin.Instance.ReportError("Unplaced cache account preserved: " + ex3.Message); } } } internal bool Select(ZDO z, out string error) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (z.GetBool("pc.mp.duplicate", false)) { error = "You already have a Provisioning Cache. Remove it before building another. Building materials are being returned beside it."; return false; } ResetRemote(); Selected = z.m_uid; snapshotRevision = z.GetLong("pc.mp.revision", 0L); string text = z.GetString("pc.mp.state", ""); if (text.Length == 0 || z.GetZDOID("pc.mp.account") == ZDOID.None) { error = "Server is registering this cache. Try again shortly."; return false; } try { Snapshot = StateCodec.Decode(text); } catch (Exception ex) { error = "Cache data could not be read."; Plugin.Instance.ReportError(ex.ToString()); return false; } if (IsOwner && !Busy && z.GetInt("pc.mp.used", 0) == 0) { Send("initialize", ""); } error = ""; return true; } internal void Refresh() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (Busy || world == null) { return; } if (Remote) { RefreshRemote(); return; } ZDO zDO = world.GetZDO(Selected); if (zDO == null) { Snapshot = null; return; } string text = zDO.GetString("pc.mp.state", ""); long num = zDO.GetLong("pc.mp.revision", 0L); if (num < snapshotRevision || text.Length == 0) { return; } try { Snapshot = StateCodec.Decode(text); snapshotRevision = num; } catch (Exception ex) { Plugin.Instance.ReportError("Cache snapshot: " + ex.Message); } } internal string Send(string action, string argument, Dictionary<string, int> counts = null) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (Busy) { return "Waiting for the server…"; } if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || Snapshot == null) { return "Cache unavailable."; } requestId = Math.Max(DateTime.UtcNow.Ticks, requestId + 1); SetPending(new Command { World = ZNet.instance.GetWorldUID(), Cache = Selected, Nonce = requestId, Action = action, Argument = argument, Access = selectedAccess, Tier = Snapshot.Tier, Speed = Snapshot.SpeedRank, Storage = Snapshot.StorageRank, Allocation = Snapshot.AllocationRank, Counts = (counts ?? new Dictionary<string, int>()) }); return "Waiting for the server…"; } private void SetPending(Command command) { pending = Convert.ToBase64String(command.Encode().GetArray()); Busy = true; retry = 0f; Player.m_localPlayer.m_customData[EscrowKey] = pending; } private void Request(long sender, ZPackage p) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) if (!ZNet.instance.IsServer() || !ready) { return; } try { Command command = Command.Read(p); if (command.World != ZNet.instance.GetWorldUID() || !GetActor(sender, out var playerId, out var playerZdo, out var isAdmin)) { return; } ZDO zDO = world.GetZDO(command.Cache); ZDO val = accounts.FindForPiece(command.Cache); if (val == null) { Respond(sender, command, null, "Cache is unavailable; pending payments will be returned."); return; } CacheState cacheState = StateCodec.Decode(val.GetString("pc.mp.state", "")); CollectionLedger collectionLedger = CollectionLedger.Decode(val.GetString("pc.mp.collections", ""), cacheState); CollectionReservation collectionReservation = collectionLedger.Find(playerId); if (command.Action == "collect_ack") { if (collectionReservation == null || collectionReservation.Request != command.Nonce) { Respond(sender, command, val, "Collection receipt not found."); return; } accounts.Advance(val, cacheState); collectionLedger.Acknowledge(cacheState, playerId, command.Nonce, command.Counts); accounts.Save(val, cacheState, collectionLedger); Record(val, playerId, command, CollectionMessage(collectionReservation), paid: false); Respond(sender, command, val, CollectionMessage(collectionReservation)); return; } if (command.Action == "collect" && collectionReservation?.Request == command.Nonce) { Respond(sender, command, val, collectionReservation.Complete ? CollectionMessage(collectionReservation) : "Adding items to inventory…", paid: false, collectionReservation.Complete ? null : collectionReservation.Granted); return; } string text = "pc.receipt." + playerId; long num = val.GetLong(text, 0L); if (!NetworkPolicy.IsNewRequest(command.Nonce, num)) { Respond(sender, command, val, (command.Nonce == num) ? val.GetString(text + ".result", "") : "Stale request rejected.", command.Nonce == num && val.GetInt(text + ".paid", 0) == 1); return; } if (zDO == null || zDO.GetPrefab() != StringExtensionMethods.GetStableHashCode("pc_provisioning_cache")) { Record(val, playerId, command, "Cache was removed; progress is preserved. Pending payments will be returned.", paid: false); Respond(sender, command, val, "Cache was removed; progress is preserved. Pending payments will be returned."); return; } long num2 = val.GetLong("pc.account.owner", 0L); string error = NetworkPolicy.Authorize(playerId, num2, (playerZdo == null) ? double.PositiveInfinity : ((double)Vector3.Distance(playerZdo.GetPosition(), zDO.GetPosition())), command.Action, command.Access, isAdmin); if (val.GetInt("pc.mp.used", 0) == 0 && playerId != num2 && !(command.Access == CacheAccess.AdminRemote && isAdmin)) { error = "The owner must open this cache before visitors can collect."; } if (!owners.TryGetValue(num2, out var value) || value.m_uid != command.Cache) { error = "Only one cache per player is allowed."; } bool flag = error.Length == 0; bool paid = false; accounts.Advance(val, cacheState); if (flag && command.Action == "collect") { Dictionary<string, int> wanted = command.Counts.Where((KeyValuePair<string, int> pair) => Object.op_Implicit((Object)(object)ObjectDB.instance.GetItemPrefab(pair.Key))).ToDictionary((KeyValuePair<string, int> pair) => pair.Key, (KeyValuePair<string, int> pair) => pair.Value); collectionReservation = collectionLedger.Reserve(cacheState, playerId, command.Nonce, wanted); if (playerId == num2 || command.Access == CacheAccess.AdminRemote) { val.Set("pc.mp.used", 1); } accounts.Save(val, cacheState, collectionLedger); if (collectionReservation.Complete) { Record(val, playerId, command, CollectionMessage(collectionReservation), paid: false); } Respond(sender, command, val, collectionReservation.Complete ? CollectionMessage(collectionReservation) : "Adding items to inventory…", paid: false, collectionReservation.Complete ? null : collectionReservation.Granted); return; } if (flag && command.Action == "initialize") { error = "Cache ready. Visitors can now collect."; } else if (flag && command.Action == "allocate") { Production.Allocate(cacheState, command.Counts, out error); } else if (flag && command.Action == "purchase") { Offer offer = Upgrades.Offers(cacheState).Find((Offer o) => o.Id == command.Argument); error = ((offer == null) ? "Already purchased." : ((!NetworkPolicy.QuoteMatches(cacheState, command.Tier, command.Speed, command.Storage, command.Allocation)) ? "Upgrade changed; try again." : Upgrades.BlockReason(cacheState, offer, int.MaxValue, (string key) => ZoneSystem.instance.GetGlobalKey(key), (string _) => int.MaxValue))); if (error.Length == 0) { Upgrades.Apply(cacheState, offer); paid = true; error = offer.Name + " purchased."; } } if (flag && (playerId == num2 || command.Access == CacheAccess.AdminRemote)) { val.Set("pc.mp.used", 1); } accounts.Save(val, cacheState); Record(val, playerId, command, error, paid); Respond(sender, command, val, error, paid); } catch (Exception ex) { Plugin.Instance.ReportError("Cache server request failed: " + ex); } } private static string CollectionMessage(CollectionReservation receipt) { int num = receipt.Accepted.Values.Sum(); return "Collected " + num + " items." + ((num < receipt.Granted.Values.Sum()) ? " Remaining items stayed in the cache." : ""); } private static void Record(ZDO z, long player, Command command, string message, bool paid) { string text = "pc.receipt." + player; if (command.Nonce >= z.GetLong(text, 0L)) { z.Set(text, command.Nonce); z.Set(text + ".result", message); z.Set(text + ".paid", paid ? 1 : 0); } } private void Respond(long sender, Command command, ZDO z, string message, bool paid = false, Dictionary<string, int> grant = null) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(command.Nonce); val.Write(command.Cache); val.Write(((z != null) ? z.GetString("pc.mp.state", "") : null) ?? ""); val.Write(message); val.Write(paid); val.Write((z != null) ? z.GetLong("pc.mp.revision", 0L) : 0); val.Write(grant != null); WriteCounts(val, grant); registered.InvokeRoutedRPC(sender, "PC_Reply_v2", new object[1] { val }); } private void Reply(long sender, ZPackage p) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_00a6: Unknown result type (might be due to invalid IL or missing references) if (sender != ServerId || !Busy || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } try { long num = p.ReadLong(); ZDOID val = p.ReadZDOID(); string text = p.ReadString(); string text2 = p.ReadString(); bool flag = p.ReadBool(); long num2 = p.ReadLong(); bool flag2 = p.ReadBool(); Dictionary<string, int> granted = ReadCounts(p); Command command = Command.Read(new ZPackage(Convert.FromBase64String(pending))); if (command.Nonce != num || command.Cache != val) { return; } CacheState cacheState = ((text.Length > 0) ? StateCodec.Decode(text) : null); bool flag3 = val == Selected || (cacheState != null && cacheState.BoundUser == ((ZDOID)(ref Selected)).UserID && cacheState.BoundId == ((ZDOID)(ref Selected)).ID); if (flag3 && cacheState != null && num2 >= snapshotRevision) { Snapshot = cacheState; snapshotRevision = num2; } if (flag2) { if (!(command.Action != "collect") || !(command.Action != "collect_ack")) { ReceiveGrant(command, granted); } return; } if (command.Action == "purchase" && !flag) { QueueRefund(command); } Busy = false; pending = ""; Player.m_localPlayer.m_customData.Remove(EscrowKey); if (command.Action == "collect" || command.Action == "collect_ack") { Player.m_localPlayer.m_customData.Remove(DeliveryKey); } if (flag3) { Plugin.Instance.Window.NetworkChanged(text2, command.Action != "collect" && command.Action != "collect_ack"); } ((Character)Player.m_localPlayer).Message((MessageType)2, text2, 0, (Sprite)null, false); } catch (Exception ex) { Plugin.Instance.ReportError("Cache reply preserved for retry: " + ex); } } private void ReceiveGrant(Command command, Dictionary<string, int> granted) { Player player = Player.m_localPlayer; if (((Character)player).IsDead()) { return; } CollectionDelivery delivery; if (player.m_customData.TryGetValue(DeliveryKey, out var value)) { delivery = CollectionDelivery.Decode(value); if (delivery.Request != command.Nonce || !delivery.Matches(granted)) { throw new InvalidDataException("Collection grant changed."); } } else { delivery = new CollectionDelivery { Request = command.Nonce }; foreach (KeyValuePair<string, int> item in granted) { delivery.Granted.Add(item.Key, item.Value); } player.m_customData[DeliveryKey] = delivery.Encode(); } Dictionary<string, int> received = new Dictionary<string, int>(); delivery.Deliver(delegate(string id) { if (!CacheInventory.TryAddOne(id)) { return false; } received[id] = ((!received.TryGetValue(id, out var value2)) ? 1 : (value2 + 1)); return true; }, delegate { player.m_customData[DeliveryKey] = delivery.Encode(); }); command.Action = "collect_ack"; command.Argument = ""; command.Counts = new Dictionary<string, int>(delivery.Accepted); SetPending(command); CacheInventory.ShowPickups(received); } private static void QueueRefund(Command command) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown Dictionary<string, string> customData = Player.m_localPlayer.m_customData; string value; long result; long num = ((customData.TryGetValue(RefundKey + ".last", out value) && long.TryParse(value, out result)) ? result : 0); checked { if (command.Nonce > num) { Offer offer = Upgrades.Offers(new CacheState { Tier = command.Tier, SpeedRank = command.Speed, StorageRank = command.Storage, AllocationRank = command.Allocation }).Find((Offer o) => o.Id == command.Argument); if (offer == null) { throw new InvalidDataException("Cannot reconstruct upgrade refund."); } string value2; Dictionary<string, int> dictionary = (customData.TryGetValue(RefundKey, out value2) ? ReadCounts(new ZPackage(Convert.FromBase64String(value2)), refunds: true) : new Dictionary<string, int>()); dictionary["Coins"] = (dictionary.TryGetValue("Coins", out var value3) ? value3 : 0) + offer.Coins; if (offer.SampleCount > 0) { dictionary[offer.Sample] = (dictionary.TryGetValue(offer.Sample, out var value4) ? value4 : 0) + offer.SampleCount; } StoreRefunds(dictionary); customData[RefundKey + ".last"] = command.Nonce.ToString(); } } } private static void Store