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 balrond twinstones v1.0.0
plugins/BalrondTwinStones.dll
Decompiled 17 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using HarmonyLib; using LitJson2; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("BalrondTwinStones")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BalrondTwinStones")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("cde312a0-cf19-4264-8616-e1c74774beed")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace BalrondTwinStones { public class BalrondPortalPairPiece : MonoBehaviour, Hoverable, Interactable, TextReceiver { private const string ZdoKeyPortalId = "bpp_portal_id"; private const string ZdoKeyLinkedPortalId = "bpp_linked_portal_id"; private const string ZdoKeyPortalName = "bpp_portal_name"; private const string ZdoKeyPendingPlayerId = "bpp_pending_player_id"; private static readonly Dictionary<string, BalrondPortalPairPiece> PortalRegistry = new Dictionary<string, BalrondPortalPairPiece>(); private static readonly Dictionary<long, float> LastTeleportTime = new Dictionary<long, float>(); private ZNetView _nview; private Piece _piece; private GameObject _connectionEffect; private bool _lastLinkedState; private bool _lastPendingState; private string _cachedPortalId = string.Empty; private string _cachedLinkedPortalId = string.Empty; [Header("Link")] public float m_maxLinkDistance = 100f; [Header("Teleport")] public Transform m_exitPoint; public Vector3 m_exitOffset = new Vector3(0f, 0.5f, 1.5f); public float m_teleportCooldown = 1.5f; [Header("Teleport Cost")] public ItemDrop m_fuel = null; public int m_fuelConsume = 0; public bool m_shouldConsumeItem = false; [Header("Visuals")] public GameObject m_visualConnected; public GameObject m_visualUnconnected; public GameObject m_visualPending; [Header("Connection Effect")] public GameObject m_connectionPrefab; public Vector3 m_connectionOffset = Vector3.zero; public float m_connectionEffectTimeout = 0.35f; [Header("Naming")] public int m_nameCharacterLimit = 32; private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _piece = ((Component)this).GetComponent<Piece>(); if ((Object)(object)_nview == (Object)null || _nview.GetZDO() == null) { ((Behaviour)this).enabled = false; return; } EnsurePortalId(); _cachedPortalId = ReadPortalIdFromZDO(); _cachedLinkedPortalId = ReadLinkedPortalIdFromZDO(); RegisterSelf(); UpdateVisualStateImmediate(); } private void OnDestroy() { StopConnectionEffect(); string cachedPortalId = _cachedPortalId; string cachedLinkedPortalId = _cachedLinkedPortalId; ClearPendingState(); if (!string.IsNullOrEmpty(cachedPortalId)) { PortalRegistry.Remove(cachedPortalId); PortalPendingLinkManager.ClearByPortalId(cachedPortalId); } if (!string.IsNullOrEmpty(cachedPortalId) && !string.IsNullOrEmpty(cachedLinkedPortalId)) { BalrondPortalPairPiece balrondPortalPairPiece = FindPortalById(cachedLinkedPortalId); if (IsPortalUsable(balrondPortalPairPiece) && balrondPortalPairPiece.GetLinkedPortalId() == cachedPortalId) { balrondPortalPairPiece.ClaimOwnershipIfNeeded(); balrondPortalPairPiece.SetLinkedPortalId(string.Empty); balrondPortalPairPiece.UpdateCachedLinkedPortalId(); balrondPortalPairPiece.UpdateVisualStateImmediate(); balrondPortalPairPiece.StopConnectionEffect(); } } } private void Update() { UpdateCachedLinkedPortalId(); UpdateVisualState(); } public static void ClearPendingForPlayer(Player player, bool showMessage) { if ((Object)(object)player == (Object)null) { return; } long playerID = player.GetPlayerID(); if (PortalPendingLinkManager.TryGet(playerID, out var portalId)) { ClearPendingStateByPortalId(portalId); } if (PortalPendingLinkManager.Has(playerID)) { PortalPendingLinkManager.Clear(playerID); if (showMessage) { ((Character)player).Message((MessageType)2, "$tag_pending_connection", 0, (Sprite)null); } } } public string GetHoverName() { string text = GetText(); if (!string.IsNullOrEmpty(text)) { return text; } return ((Object)(object)_piece != (Object)null) ? Localization.instance.Localize(_piece.m_name) : "Portal"; } public string GetHoverText() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) string text = GetHoverName(); if ((Object)(object)m_fuel != (Object)null) { text = text + " Cost: " + GetFuelCostText(); } if (!HasLinkedPortal()) { text += "\n[$tag_unlinked_portal]"; text += "\n[<color=green><b>Shift+$KEY_Use</b></color>] $tag_link_portal"; text += "\n[<color=red><b>Ctrl+$KEY_Use</b></color>] $tag_cancel_portal"; text += "\n[<color=yellow><b>Alt+$KEY_Use</b></color>] $tag_rename_portal"; return Localization.instance.Localize(text); } BalrondPortalPairPiece balrondPortalPairPiece = FindPortalById(GetLinkedPortalId()); if (!IsPortalUsable(balrondPortalPairPiece)) { text += "\n[$tag_missingtarget_portal]"; text += "\n[<color=yellow><b>Shift+$KEY_Use</b></color>] $tag_relink_portal"; text += "\n[<color=red><b>Ctrl+$KEY_Use</b></color>] $tag_disconnect_portal"; text += "\n[<color=yellow><b>Alt+$KEY_Use</b></color>] $tag_rename_portal"; return Localization.instance.Localize(text); } PokeConnectionEffect(); balrondPortalPairPiece.PokeConnectionEffect(); int num = Mathf.RoundToInt(Vector3.Distance(((Component)this).transform.position, ((Component)balrondPortalPairPiece).transform.position)); text = text + "\n[<color=green><b>$KEY_Use</b></color>] $tag_target_portal: " + balrondPortalPairPiece.GetHoverName() + "\n$tag_distance_portal: " + num + "/" + m_maxLinkDistance + "m"; text += "\n[<color=yellow><b>Shift+$KEY_Use</b></color>] $tag_relink_portal"; text += "\n[<color=red><b>Ctrl+$KEY_Use</b></color>] $tag_disconnect_portal"; text += "\n[<color=blue><b>Alt+$KEY_Use</b></color>] $tag_rename_portal"; return Localization.instance.Localize(text); } public bool Interact(Humanoid user, bool hold, bool alt) { if (hold) { return false; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null) { return false; } if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || _nview.GetZDO() == null) { return false; } ValidatePendingLink(val.GetPlayerID(), val); if (IsPendingForOtherPlayer(val.GetPlayerID())) { ((Character)val).Message((MessageType)2, "$tag_pending_connection", 0, (Sprite)null); return true; } if (IsAltHeld()) { TextInput.instance.RequestText((TextReceiver)(object)this, "Portal name", m_nameCharacterLimit); return true; } if (IsCtrlHeld()) { HandleCtrl(val); return true; } if (IsShiftHeld()) { HandleShift(val); return true; } HandleTeleport(val); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } public string GetText() { if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || _nview.GetZDO() == null) { return string.Empty; } return _nview.GetZDO().GetString("bpp_portal_name", string.Empty); } public void SetText(string text) { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.GetZDO() != null) { ClaimOwnershipIfNeeded(); _nview.GetZDO().Set("bpp_portal_name", text ?? string.Empty); } } private void HandleShift(Player player) { //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || _nview.GetZDO() == null) { return; } long playerID = player.GetPlayerID(); string portalId = GetPortalId(); if (string.IsNullOrEmpty(portalId)) { return; } if (!PortalPendingLinkManager.TryGet(playerID, out var portalId2)) { if (IsPendingForOtherPlayer(playerID)) { ((Character)player).Message((MessageType)2, "$tag_pending_connection", 0, (Sprite)null); return; } PortalPendingLinkManager.Set(playerID, portalId); SetPendingPlayerId(playerID); ((Character)player).Message((MessageType)2, "$tag_link_started", 0, (Sprite)null); return; } if (portalId2 == portalId) { ClearPendingState(); PortalPendingLinkManager.Clear(playerID); ((Character)player).Message((MessageType)2, "$tag_link_canceled", 0, (Sprite)null); return; } if (IsPendingForOtherPlayer(playerID)) { ((Character)player).Message((MessageType)2, "$tag_pending_connection", 0, (Sprite)null); return; } BalrondPortalPairPiece balrondPortalPairPiece = FindPortalById(portalId2); if (!IsPortalUsable(balrondPortalPairPiece)) { PortalPendingLinkManager.Clear(playerID); ClearPendingStateByPortalId(portalId2); ((Character)player).Message((MessageType)2, "$tag_pending_cleared", 0, (Sprite)null); return; } float num = Vector3.Distance(((Component)balrondPortalPairPiece).transform.position, ((Component)this).transform.position); if (num > m_maxLinkDistance) { ((Character)player).Message((MessageType)2, "$tag_tofar", 0, (Sprite)null); return; } LinkPortals(balrondPortalPairPiece, this); balrondPortalPairPiece.ClearPendingState(); PortalPendingLinkManager.Clear(playerID); ((Character)player).Message((MessageType)2, "$tag_linked", 0, (Sprite)null); } private void HandleCtrl(Player player) { long playerID = player.GetPlayerID(); if (PortalPendingLinkManager.TryGet(playerID, out var portalId)) { ClearPendingStateByPortalId(portalId); PortalPendingLinkManager.Clear(playerID); ((Character)player).Message((MessageType)2, "$tag_canceled", 0, (Sprite)null); } else if (HasLinkedPortal()) { UnlinkPortal(this); ((Character)player).Message((MessageType)2, "$tag_disconnected", 0, (Sprite)null); } } private void HandleTeleport(Player player) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (!HasLinkedPortal()) { ((Character)player).Message((MessageType)2, "$tag_not_linked", 0, (Sprite)null); return; } long playerID = player.GetPlayerID(); if (LastTeleportTime.TryGetValue(playerID, out var value) && Time.time - value < m_teleportCooldown) { return; } if (!CanPayTeleportCost(player)) { ((Character)player).Message((MessageType)2, GetMissingCostText(), 0, (Sprite)null); return; } BalrondPortalPairPiece balrondPortalPairPiece = FindPortalById(GetLinkedPortalId()); if (!IsPortalUsable(balrondPortalPairPiece)) { UnlinkPortal(this); ((Character)player).Message((MessageType)2, "$tag_linkedportal_missing", 0, (Sprite)null); return; } ConsumeTeleportCost(player); balrondPortalPairPiece.GetExitPosition(out var pos, out var rot); LastTeleportTime[playerID] = Time.time; ((Character)player).TeleportTo(pos, rot, false); } private bool CanPayTeleportCost(Player player) { if ((Object)(object)player == (Object)null) { return false; } if ((Object)(object)m_fuel == (Object)null || m_fuelConsume <= 0) { return true; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return false; } return inventory.CountItems(m_fuel.m_itemData.m_shared.m_name, -1, true) >= m_fuelConsume; } private void ConsumeTeleportCost(Player player) { if (m_shouldConsumeItem && !((Object)(object)player == (Object)null) && !((Object)(object)m_fuel == (Object)null) && m_fuelConsume > 0) { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory != null) { inventory.RemoveItem(m_fuel.m_itemData.m_shared.m_name, m_fuelConsume, -1, true); } } } private string GetFuelCostText() { if ((Object)(object)m_fuel == (Object)null || m_fuelConsume <= 0) { return ""; } string text = ((Localization.instance != null) ? Localization.instance.Localize(m_fuel.m_itemData.m_shared.m_name) : m_fuel.m_itemData.m_shared.m_name); if (m_shouldConsumeItem) { return text + " x" + m_fuelConsume; } if (m_fuelConsume <= 1) { return text + "$tag_required"; } return text + " x" + m_fuelConsume + "$tag_required"; } private string GetMissingCostText() { if ((Object)(object)m_fuel == (Object)null || m_fuelConsume <= 0) { return string.Empty; } string text = ((Localization.instance != null) ? Localization.instance.Localize(m_fuel.m_itemData.m_shared.m_name) : m_fuel.m_itemData.m_shared.m_name); if (m_shouldConsumeItem) { return "Need " + text + " x" + m_fuelConsume; } if (m_fuelConsume <= 1) { return "Need " + text + " in inventory"; } return "Need " + text + " x" + m_fuelConsume + " in inventory"; } private void GetExitPosition(out Vector3 pos, out Quaternion rot) { //IL_003e: 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_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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_exitPoint != (Object)null) { pos = m_exitPoint.position; rot = m_exitPoint.rotation; } else { pos = ((Component)this).transform.TransformPoint(m_exitOffset); rot = ((Component)this).transform.rotation; } } private void EnsurePortalId() { if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null) { ClaimOwnershipIfNeeded(); if (string.IsNullOrEmpty(ReadPortalIdFromZDO())) { _nview.GetZDO().Set("bpp_portal_id", Guid.NewGuid().ToString("N")); } } } private void RegisterSelf() { string portalId = GetPortalId(); if (!string.IsNullOrEmpty(portalId)) { PortalRegistry[portalId] = this; } } private void ClaimOwnershipIfNeeded() { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && !_nview.IsOwner()) { _nview.ClaimOwnership(); } } public string GetPortalId() { string text = ReadPortalIdFromZDO(); if (!string.IsNullOrEmpty(text)) { _cachedPortalId = text; } return _cachedPortalId; } public string GetLinkedPortalId() { string text = ReadLinkedPortalIdFromZDO(); _cachedLinkedPortalId = text ?? string.Empty; return _cachedLinkedPortalId; } private void SetLinkedPortalId(string id) { if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null) { _nview.GetZDO().Set("bpp_linked_portal_id", id ?? string.Empty); _cachedLinkedPortalId = id ?? string.Empty; } } private long GetPendingPlayerId() { if ((Object)(object)_nview == (Object)null || _nview.GetZDO() == null) { return 0L; } return _nview.GetZDO().GetLong("bpp_pending_player_id", 0L); } private void SetPendingPlayerId(long playerId) { if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null) { ClaimOwnershipIfNeeded(); _nview.GetZDO().Set("bpp_pending_player_id", playerId); UpdateVisualStateImmediate(); } } private void ClearPendingState() { SetPendingPlayerId(0L); } private static void ClearPendingStateByPortalId(string portalId) { BalrondPortalPairPiece balrondPortalPairPiece = FindPortalById(portalId); if (IsPortalUsable(balrondPortalPairPiece)) { balrondPortalPairPiece.ClearPendingState(); } } private bool IsPending() { return GetPendingPlayerId() != 0; } private bool IsPendingForOtherPlayer(long playerId) { long pendingPlayerId = GetPendingPlayerId(); return pendingPlayerId != 0L && pendingPlayerId != playerId; } public bool HasLinkedPortal() { return !string.IsNullOrEmpty(GetLinkedPortalId()); } private void UpdateVisualState() { bool flag = HasLinkedPortal(); bool flag2 = IsPending(); if (flag != _lastLinkedState || flag2 != _lastPendingState) { UpdateVisualStateImmediate(); } } private void UpdateVisualStateImmediate() { bool flag = HasLinkedPortal(); bool flag2 = IsPending(); _lastLinkedState = flag; _lastPendingState = flag2; if ((Object)(object)m_visualPending != (Object)null) { m_visualPending.SetActive(flag2); } if ((Object)(object)m_visualConnected != (Object)null) { m_visualConnected.SetActive(flag && !flag2); } if ((Object)(object)m_visualUnconnected != (Object)null) { m_visualUnconnected.SetActive(!flag && !flag2); } } public static void LinkPortals(BalrondPortalPairPiece a, BalrondPortalPairPiece b) { if (IsPortalUsable(a) && IsPortalUsable(b)) { a.ClaimOwnershipIfNeeded(); b.ClaimOwnershipIfNeeded(); string portalId = a.GetPortalId(); string portalId2 = b.GetPortalId(); if (!string.IsNullOrEmpty(portalId) && !string.IsNullOrEmpty(portalId2)) { a.ClearPendingState(); b.ClearPendingState(); a.SetLinkedPortalId(portalId2); b.SetLinkedPortalId(portalId); a.UpdateVisualStateImmediate(); b.UpdateVisualStateImmediate(); } } } public static void UnlinkPortal(BalrondPortalPairPiece p) { if (IsPortalUsable(p)) { BalrondPortalPairPiece balrondPortalPairPiece = FindPortalById(p.GetLinkedPortalId()); p.ClaimOwnershipIfNeeded(); p.SetLinkedPortalId(string.Empty); p.UpdateVisualStateImmediate(); p.StopConnectionEffect(); if (IsPortalUsable(balrondPortalPairPiece)) { balrondPortalPairPiece.ClaimOwnershipIfNeeded(); balrondPortalPairPiece.SetLinkedPortalId(string.Empty); balrondPortalPairPiece.UpdateVisualStateImmediate(); balrondPortalPairPiece.StopConnectionEffect(); } } } public static BalrondPortalPairPiece FindPortalById(string id) { if (string.IsNullOrEmpty(id)) { return null; } PortalRegistry.TryGetValue(id, out var value); return value; } private static bool IsPortalUsable(BalrondPortalPairPiece p) { return (Object)(object)p != (Object)null && (Object)(object)p._nview != (Object)null && p._nview.IsValid() && p._nview.GetZDO() != null; } private void PokeConnectionEffect() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (HasLinkedPortal()) { BalrondPortalPairPiece balrondPortalPairPiece = FindPortalById(GetLinkedPortalId()); if (IsPortalUsable(balrondPortalPairPiece)) { StartConnectionEffect(balrondPortalPairPiece.GetConnectionPoint()); } } } private void StartConnectionEffect(Vector3 target) { //IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_connectionPrefab == (Object)null) { return; } Vector3 connectionPoint = GetConnectionPoint(); Vector3 val = target - connectionPoint; if (!(((Vector3)(ref val)).sqrMagnitude <= 0.0001f)) { if ((Object)(object)_connectionEffect == (Object)null) { _connectionEffect = Object.Instantiate<GameObject>(m_connectionPrefab); } _connectionEffect.transform.position = connectionPoint; _connectionEffect.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized); _connectionEffect.transform.localScale = new Vector3(1f, 1f, ((Vector3)(ref val)).magnitude); ((MonoBehaviour)this).CancelInvoke("StopConnectionEffect"); ((MonoBehaviour)this).Invoke("StopConnectionEffect", m_connectionEffectTimeout); } } private void StopConnectionEffect() { if ((Object)(object)_connectionEffect != (Object)null) { Object.Destroy((Object)(object)_connectionEffect); _connectionEffect = null; } } private Vector3 GetConnectionPoint() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) return ((Component)this).transform.TransformPoint(m_connectionOffset); } private string ReadPortalIdFromZDO() { if ((Object)(object)_nview == (Object)null || _nview.GetZDO() == null) { return _cachedPortalId; } return _nview.GetZDO().GetString("bpp_portal_id", string.Empty); } private string ReadLinkedPortalIdFromZDO() { if ((Object)(object)_nview == (Object)null || _nview.GetZDO() == null) { return _cachedLinkedPortalId; } return _nview.GetZDO().GetString("bpp_linked_portal_id", string.Empty); } private void UpdateCachedLinkedPortalId() { _cachedLinkedPortalId = ReadLinkedPortalIdFromZDO(); } private static bool IsShiftHeld() { return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); } private static bool IsCtrlHeld() { return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); } private static bool IsAltHeld() { return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); } public static void ValidatePendingLink(long id, Player player) { if (!PortalPendingLinkManager.TryGet(id, out var portalId)) { return; } BalrondPortalPairPiece p = FindPortalById(portalId); if (!IsPortalUsable(p)) { PortalPendingLinkManager.Clear(id); ClearPendingStateByPortalId(portalId); if ((Object)(object)player != (Object)null) { ((Character)player).Message((MessageType)2, "$tag_pending_connection", 0, (Sprite)null); } } } } public class BalrondTranslator { public static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>(); public static Dictionary<string, string> getLanguage(string language) { if (string.IsNullOrEmpty(language)) { return null; } if (translations.TryGetValue(language, out var value)) { return value; } return null; } } internal class BuildPieceList { public static string[] buildPieces = new string[1] { "piece_obeliskPortal_bal" }; } public class DatabaseAddMethods { public void AddItems(List<GameObject> items) { foreach (GameObject item in items) { AddItem(item); } } public void AddRecipes(List<Recipe> recipes) { foreach (Recipe recipe in recipes) { AddRecipe(recipe); } } public void AddStatuseffects(List<StatusEffect> statusEffects) { foreach (StatusEffect statusEffect in statusEffects) { AddStatus(statusEffect); } } private bool IsObjectDBValid() { return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0 && ObjectDB.instance.m_recipes.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null; } private void AddStatus(StatusEffect status) { if (!IsObjectDBValid()) { return; } if ((Object)(object)status != (Object)null) { if ((Object)(object)ObjectDB.instance.GetStatusEffect(status.m_nameHash) == (Object)null) { ObjectDB.instance.m_StatusEffects.Add(status); } else { Debug.Log((object)(Launch.projectName + ": " + ((Object)status).name + " - Status already in the game")); } } else { Debug.LogError((object)(Launch.projectName + ": " + ((Object)status).name + " - Status not found")); } } private void AddRecipe(Recipe recipe) { if (!IsObjectDBValid()) { return; } if ((Object)(object)recipe != (Object)null) { if ((Object)(object)ObjectDB.instance.m_recipes.Find((Recipe x) => ((Object)x).name == ((Object)recipe).name) == (Object)null) { if ((Object)(object)recipe.m_item != (Object)null) { ObjectDB.instance.m_recipes.Add(recipe); } } else { Debug.Log((object)(Launch.projectName + ": " + ((Object)recipe).name + " - Recipe with this name already in the Game")); } } else { Debug.LogError((object)(Launch.projectName + ": " + ((Object)recipe).name + " - Recipe not found")); } } private void AddItem(GameObject newPrefab) { if (!IsObjectDBValid()) { return; } ItemDrop component = newPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { if ((Object)(object)ObjectDB.instance.GetItemPrefab(((Object)newPrefab).name) == (Object)null) { ObjectDB.instance.m_items.Add(newPrefab); Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)typeof(ObjectDB).GetField("m_itemByHash", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ObjectDB.instance); dictionary[((Object)newPrefab).name.GetHashCode()] = newPrefab; } else { Debug.LogWarning((object)(Launch.projectName + ": " + ((Object)newPrefab).name + " - ItemDrop already exist")); } } else { Debug.LogError((object)(Launch.projectName + ": " + ((Object)newPrefab).name + " - ItemDrop not found on prefab")); } } } public class ModResourceLoader { public AssetBundle assetBundle; public List<GameObject> buildPrefabs = new List<GameObject>(); public List<GameObject> plantPrefabs = new List<GameObject>(); public List<GameObject> itemPrefabs = new List<GameObject>(); public List<GameObject> monsterPrefabs = new List<GameObject>(); public List<GameObject> vegetationPrefabs = new List<GameObject>(); public List<GameObject> clutterPrefabs = new List<GameObject>(); public List<GameObject> locationPrefabs = new List<GameObject>(); public List<GameObject> roomPrefabs = new List<GameObject>(); public List<GameObject> vfxPrefabs = new List<GameObject>(); public List<Texture2D> texturePrefabs = new List<Texture2D>(); public List<Recipe> recipes = new List<Recipe>(); public List<StatusEffect> statusEffects = new List<StatusEffect>(); public StatusEffect newBarleyStatus = null; public ShaderReplacment shaderReplacment = new ShaderReplacment(); public Sprite newLogo = null; public void loadAssets() { assetBundle = GetAssetBundleFromResources("balrondtwinstones"); string basePath = "Assets/Custom/BalrondTwinStones/"; loadPieces(basePath); loadItems(basePath); loadOther(basePath); } public void AddPrefabsToZnetScene(ZNetScene zNetScene) { zNetScene.m_prefabs.AddRange(vegetationPrefabs); foreach (GameObject gm in itemPrefabs) { GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == ((Object)gm).name); if ((Object)(object)val == (Object)null) { zNetScene.m_prefabs.Add(gm); } else { Debug.LogWarning((object)("Object exists: " + ((Object)gm).name)); } } foreach (GameObject gm2 in buildPrefabs) { GameObject val2 = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == ((Object)gm2).name); if ((Object)(object)val2 == (Object)null) { zNetScene.m_prefabs.Add(gm2); } else { Debug.LogWarning((object)("Object exists: " + ((Object)gm2).name)); } } foreach (GameObject gm3 in vfxPrefabs) { GameObject val3 = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == ((Object)gm3).name); if ((Object)(object)val3 == (Object)null) { zNetScene.m_prefabs.Add(gm3); } else { Debug.LogWarning((object)("Object exists: " + ((Object)gm3).name)); } } zNetScene.m_prefabs.RemoveAll((GameObject x) => (Object)(object)x == (Object)null); setupNewPortal(zNetScene); addPlantstoCultivator(zNetScene); setupBuildPiecesList(zNetScene); } private void setupNewPortal(ZNetScene zNetScene) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) GameObject val = buildPrefabs.Find((GameObject x) => ((Object)x).name == "piece_obeliskPortal_bal"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)"[Portal] prefab piece_obeliskPortal_bal not found"); return; } Smelter component = val.GetComponent<Smelter>(); if ((Object)(object)component == (Object)null) { Debug.LogError((object)"[Portal] Smelter missing on piece_obeliskPortal_bal"); return; } StationExtension component2 = val.GetComponent<StationExtension>(); if ((Object)(object)component2 == (Object)null) { Debug.LogError((object)"[Portal] StationExtension missing on piece_obeliskPortal_bal"); return; } BalrondPortalPairPiece balrondPortalPairPiece = val.GetComponent<BalrondPortalPairPiece>(); if ((Object)(object)balrondPortalPairPiece == (Object)null) { balrondPortalPairPiece = val.AddComponent<BalrondPortalPairPiece>(); } balrondPortalPairPiece.m_exitPoint = component.m_outputPoint; balrondPortalPairPiece.m_visualConnected = component.m_enabledObject; balrondPortalPairPiece.m_visualUnconnected = component.m_disabledObject; balrondPortalPairPiece.m_visualPending = component.m_haveFuelObject; balrondPortalPairPiece.m_fuel = null; balrondPortalPairPiece.m_fuelConsume = 0; balrondPortalPairPiece.m_shouldConsumeItem = true; balrondPortalPairPiece.m_maxLinkDistance = 50f; balrondPortalPairPiece.m_connectionPrefab = component2.m_connectionPrefab; balrondPortalPairPiece.m_connectionOffset = new Vector3(0f, 1f, 0f); Object.DestroyImmediate((Object)(object)component); Object.DestroyImmediate((Object)(object)component2); } private void setupBuildPiecesList(ZNetScene zNetScene) { string[] array = new string[4] { "Hammer", "HammerIron", "HammerDverger", "HammerBlackmetal" }; GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == "Hammer"); PieceTable buildPieces = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces; string[] array2 = array; foreach (string name in array2) { addBuildpiecesToOtherHammer(name, buildPieces, zNetScene); } List<GameObject> pieces = buildPieces.m_pieces; foreach (GameObject buildPrefab in buildPrefabs) { setupRavenGuide(buildPrefab, zNetScene.m_prefabs); AddToBuildList(buildPrefab, pieces); } } private void addBuildpiecesToOtherHammer(string name, PieceTable pieceTable, ZNetScene zNetScene) { GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == name); if (!((Object)(object)val == (Object)null)) { val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces = pieceTable; } } public void setupRavenGuide(GameObject gameObject, List<GameObject> gameObjects) { GameObject val = null; Transform val2 = gameObject.transform.Find("GuidePoint"); if ((Object)(object)val2 == (Object)null) { return; } GameObject val3 = gameObjects.Find((GameObject x) => ((Object)x).name == "piece_workbench"); if ((Object)(object)val3 != (Object)null) { GameObject gameObject2 = ((Component)val3.transform.Find("GuidePoint")).gameObject; if ((Object)(object)gameObject2 != (Object)null) { GuidePoint component = gameObject2.GetComponent<GuidePoint>(); if ((Object)(object)component != (Object)null) { val = component.m_ravenPrefab; } } } if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)"Ravens not found"); } else { ((Component)val2).GetComponent<GuidePoint>().m_ravenPrefab = val; } } public void setupBuildPiecesListDB() { GameObject val = ObjectDB.instance.m_items.Find((GameObject x) => ((Object)x).name == "Hammer"); List<GameObject> pieces = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces.m_pieces; foreach (GameObject buildPrefab in buildPrefabs) { AddToBuildList(buildPrefab, pieces); } } private void AddToBuildList(GameObject prefab, List<GameObject> buildPieces) { if ((Object)(object)buildPieces.Find((GameObject x) => ((Object)x).name == ((Object)prefab).name) == (Object)null) { buildPieces.Add(prefab); } } private void addPlantstoCultivator(ZNetScene zNetScene) { GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == "Cultivator"); PieceTable buildPieces = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces; List<GameObject> pieces = buildPieces.m_pieces; foreach (GameObject plantPrefab in plantPrefabs) { pieces.Add(plantPrefab); } } private void loadItems(string basePath) { string mainPath = basePath + "Items/"; string[] nameList = new string[0]; addNewPrefabToCollection(nameList, mainPath, itemPrefabs, "item"); } private void addNewPrefabToCollection(string[] nameList, string mainPath, List<GameObject> prefabList, string typeName) { foreach (string text in nameList) { GameObject val = assetBundle.LoadAsset<GameObject>(mainPath + text + ".prefab"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Could not find " + typeName + " with name: " + text)); } else if (Object.op_Implicit((Object)(object)val.GetComponent<ZNetView>()) || typeName == "clutter") { ShaderReplacment.Replace(val); prefabList.Add(val); } else { Debug.LogWarning((object)("Prefab with name has no ZNetView could not been removed: " + text)); } } } private AssetBundle GetAssetBundleFromResources(string filename) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(filename)); using Stream stream = executingAssembly.GetManifestResourceStream(name); return AssetBundle.LoadFromStream(stream); } private void loadPlants(string basePath) { string text = basePath + "Plants/"; string[] array = new string[0]; string[] array2 = array; foreach (string text2 in array2) { GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Could not find plant with name: " + text2)); continue; } ShaderReplacment.Replace(val); plantPrefabs.Add(val); } } private void loadPieces(string basePath) { string text = basePath + "Pieces/"; string[] buildPieces = BuildPieceList.buildPieces; string[] array = buildPieces; foreach (string text2 in array) { GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Could not find piece with name: " + text2)); continue; } ShaderReplacment.Replace(val); buildPrefabs.Add(val); } } private void loadVegetation(string basePath) { string text = basePath + "Vegetation/"; string[] array = new string[0]; string[] array2 = array; foreach (string text2 in array2) { GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Could not find vegegation with name: " + text2)); continue; } ShaderReplacment.Replace(val); vegetationPrefabs.Add(val); } } private void loadOther(string basePath) { string text = basePath + "Other/"; string[] array = new string[0]; string[] array2 = array; foreach (string text2 in array2) { GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Could not find object with name: " + text2)); continue; } ShaderReplacment.Replace(val); vfxPrefabs.Add(val); } } private void prepareOtherEffects(string mainPath) { string[] array = new string[0]; string[] array2 = array; foreach (string text in array2) { StatusEffect val = (StatusEffect)(object)assetBundle.LoadAsset<SE_Stats>(mainPath + "Status/" + text + ".asset"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Status not found: " + text)); } else { statusEffects.Add(val); } } } } public class ShaderReplacment { public static List<GameObject> prefabsToReplaceShader = new List<GameObject>(); public static List<Material> materialsInPrefabs = new List<Material>(); public string[] shaderlist = new string[49] { "Custom/AlphaParticle", "Custom/Blob", "Custom/Bonemass", "Custom/Clouds", "Custom/Creature", "Custom/Decal", "Custom/Distortion", "Custom/Flow", "Custom/FlowOpaque", "Custom/Grass", "Custom/GuiScroll", "Custom/Heightmap", "Custom/icon", "Custom/InteriorSide", "Custom/LitGui", "Custom/LitParticles", "Custom/mapshader", "Custom/ParticleDecal", "Custom/Piece", "Custom/Player", "Custom/Rug", "Custom/ShadowBlob", "Custom/SkyboxProcedural", "Custom/SkyObject", "Custom/StaticRock", "Custom/Tar", "Custom/Trilinearmap", "Custom/UI/BGBlur", "Custom/Vegetation", "Custom/Water", "Custom/WaterBottom", "Custom/WaterMask", "Custom/Yggdrasil", "Custom/Yggdrasil/root", "Hidden/BlitCopyHDRTonemap", "Hidden/Dof/DepthOfFieldHdr", "Hidden/Dof/DX11Dof", "Hidden/Internal-Loading", "Hidden/Internal-UIRDefaultWorld", "Hidden/SimpleClear", "Hidden/SunShaftsComposite", "Lux Lit Particles/ Bumped", "Lux Lit Particles/ Tess Bumped", "Particles/Standard Surface2", "Particles/Standard Unlit2", "Standard TwoSided", "ToonDeferredShading2017", "Unlit/DepthWrite", "Unlit/Lighting" }; public static List<Shader> shaders = new List<Shader>(); private static readonly HashSet<Shader> CachedShaders = new HashSet<Shader>(); public static bool debug = true; public static Shader findShader(string name) { Shader[] array = Resources.FindObjectsOfTypeAll<Shader>(); if (array.Length == 0) { Debug.LogWarning((object)"SHADER LIST IS EMPTY!"); return null; } if (debug) { } return shaders.Find((Shader x) => ((Object)x).name == name); } public static Shader GetShaderByName(string name) { return shaders.Find((Shader x) => ((Object)x).name == name.Trim()); } public static void debugShaderList(List<Shader> shadersRes) { foreach (Shader shadersRe in shadersRes) { Debug.LogWarning((object)("SHADER NAME IS: " + ((Object)shadersRe).name)); } debug = false; } public static void Replace(GameObject gameObject) { prefabsToReplaceShader.Add(gameObject); GetMaterialsInPrefab(gameObject); } public static void GetMaterialsInPrefab(GameObject gameObject) { Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { continue; } Material[] array2 = sharedMaterials; foreach (Material val2 in array2) { if ((Object)(object)val2 != (Object)null) { materialsInPrefabs.Add(val2); } } } } public static void getMeShaders() { AssetBundle[] array = Resources.FindObjectsOfTypeAll<AssetBundle>(); AssetBundle[] array2 = array; foreach (AssetBundle val in array2) { IEnumerable<Shader> enumerable3; try { IEnumerable<Shader> enumerable2; if (!val.isStreamedSceneAssetBundle || !Object.op_Implicit((Object)(object)val)) { IEnumerable<Shader> enumerable = val.LoadAllAssets<Shader>(); enumerable2 = enumerable; } else { enumerable2 = from shader in ((IEnumerable<string>)val.GetAllAssetNames()).Select((Func<string, Shader>)val.LoadAsset<Shader>) where (Object)(object)shader != (Object)null select shader; } enumerable3 = enumerable2; } catch (Exception) { continue; } if (enumerable3 == null) { continue; } foreach (Shader item in enumerable3) { CachedShaders.Add(item); } } } public static void runMaterialFix() { getMeShaders(); shaders.AddRange(CachedShaders); foreach (Material materialsInPrefab in materialsInPrefabs) { Shader shader = materialsInPrefab.shader; if (!((Object)(object)shader == (Object)null)) { string name = ((Object)shader).name; if (!(name == "Standard") && name.Contains("Balrond")) { setProperValue(materialsInPrefab, name); } } } } private static void setProperValue(Material material, string shaderName) { string name = shaderName.Replace("Balrond", "Custom"); name = checkNaming(name); Shader shaderByName = GetShaderByName(name); if ((Object)(object)shaderByName == (Object)null) { Debug.LogWarning((object)("Shader not found " + name)); } else { material.shader = shaderByName; } } private static string checkNaming(string name) { string result = name; if (name.Contains("Bumped")) { result = name.Replace("Custom", "Lux Lit Particles"); } if (name.Contains("Tess Bumped")) { result = name.Replace("Custom", "Lux Lit Particles"); } if (name.Contains("Standard Surface")) { result = name.Replace("Custom", "Particles"); result = result.Replace("Standard Surface2", "Standard Surface"); } if (name.Contains("Standard Unlit")) { result = name.Replace("Custom", "Particles"); result = result.Replace("Standard Unlit", "Standard Unlit2"); result = result.Replace("Standard Unlit22", "Standard Unlit2"); } return result; } } public class JsonLoader { public string defaultPath = string.Empty; public void loadJson() { LoadTranslations(); justDefaultPath(); } public void justDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "BalrondTwinStones-translation/"); defaultPath = text; } public void createDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "BalrondTwinStones-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("BalrondTwinStones: Folder already exists: " + text)); } defaultPath = text; } private string[] jsonFilePath(string folderName, string extension) { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "BalrondTwinStones-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("BalrondTwinStones: Folder already exists: " + text)); } string[] files = Directory.GetFiles(text, extension); Debug.Log((object)("BalrondTwinStones:" + folderName + " Json Files Found: " + files.Length)); return files; } private static void CreateFolder(string path) { try { Directory.CreateDirectory(path); Debug.Log((object)"BalrondTwinStones: Folder created successfully."); } catch (Exception ex) { Debug.Log((object)("BalrondTwinStones: Error creating folder: " + ex.Message)); } } private void LoadTranslations() { int num = 0; string[] array = jsonFilePath("Translation", "*.json"); foreach (string text in array) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string json = File.ReadAllText(text); JsonData jsonData = JsonMapper.ToObject(json); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string key in jsonData.Keys) { dictionary[key] = jsonData[key].ToString(); } if (dictionary != null) { BalrondTranslator.translations.Add(fileNameWithoutExtension, dictionary); Debug.Log((object)("BalrondTwinStones: Json Files Language: " + fileNameWithoutExtension)); num++; } else { Debug.LogError((object)("BalrondTwinStones: Loading FAILED file: " + text)); } } Debug.Log((object)("BalrondTwinStones: Translation JsonFiles Loaded: " + num)); } } [BepInPlugin("balrond.astafaraios.BalrondTwinStones", "BalrondTwinStones", "1.0.0")] public class Launch : BaseUnityPlugin { [HarmonyPatch(typeof(AudioMan), "Awake")] private static class AudioMan_Awake_Patch { private static void Postfix(AudioMan __instance) { List<List<GameObject>> list = new List<List<GameObject>> { modResourceLoader.itemPrefabs, modResourceLoader.buildPrefabs, modResourceLoader.monsterPrefabs, modResourceLoader.vfxPrefabs, modResourceLoader.vegetationPrefabs }; foreach (List<GameObject> item in list) { foreach (GameObject item2 in item) { AudioSource[] componentsInChildren = item2.GetComponentsInChildren<AudioSource>(true); foreach (AudioSource val in componentsInChildren) { val.outputAudioMixerGroup = __instance.m_masterMixer.outputAudioMixerGroup; } } } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] public static class Object_CopyOtherDB_Path { public static void Postfix() { if (IsObjectDBValid()) { modResourceLoader.setupBuildPiecesListDB(); modResourceLoader.recipes = recipeFactory.createRecipes(ObjectDB.instance.m_items, modResourceLoader.itemPrefabs); databaseAddMethods.AddItems(modResourceLoader.itemPrefabs); databaseAddMethods.AddStatuseffects(modResourceLoader.statusEffects); databaseAddMethods.AddRecipes(modResourceLoader.recipes); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] public static class ObjectDB_Awake_Path { public static void Postfix() { if (IsObjectDBValid()) { modResourceLoader.setupBuildPiecesListDB(); modResourceLoader.recipes = recipeFactory.createRecipes(ObjectDB.instance.m_items, modResourceLoader.itemPrefabs); databaseAddMethods.AddItems(modResourceLoader.itemPrefabs); databaseAddMethods.AddStatuseffects(modResourceLoader.statusEffects); databaseAddMethods.AddRecipes(modResourceLoader.recipes); ObjectDB.instance.m_recipes.Sort(SortByScore); } } private static int SortByScore(Recipe p1, Recipe p2) { if ((Object)(object)p1.m_item == (Object)null) { return 0; } if ((Object)(object)p2.m_item == (Object)null) { return 1; } return ((Object)p1.m_item).name.CompareTo(((Object)p2.m_item).name); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class ZNetScene_Awake_Path { public static void Prefix(ZNetScene __instance) { if ((Object)(object)__instance == (Object)null) { Debug.LogWarning((object)(projectName + ": No ZnetScene found")); return; } modResourceLoader.AddPrefabsToZnetScene(__instance); if (!hasSpawned) { buildPieceBuilder.SetupBuildPieces(__instance.m_prefabs); hasSpawned = true; if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) { ShaderReplacment.runMaterialFix(); } } } } [HarmonyPatch] public static class PortalPatches { [HarmonyPatch(typeof(Player), "OnDeath")] [HarmonyPrefix] private static void Player_OnDeath_Prefix(Player __instance) { if (!((Object)(object)__instance == (Object)null)) { BalrondPortalPairPiece.ClearPendingForPlayer(__instance, showMessage: true); } } [HarmonyPatch(typeof(Player), "OnDestroy")] [HarmonyPrefix] private static void Player_OnDestroy_Prefix(Player __instance) { if (!((Object)(object)__instance == (Object)null)) { BalrondPortalPairPiece.ClearPendingForPlayer(__instance, showMessage: false); } } } [HarmonyPatch(typeof(SEMan), "RemoveStatusEffect", new Type[] { typeof(int), typeof(bool) })] public static class SEMan_RemoveStatusEffect_PowerJumpToSlowFall { private static readonly int PowerJumpHash = StringExtensionMethods.GetStableHashCode("SE_PowerJump_bal"); private static readonly int SlowFallHash = StringExtensionMethods.GetStableHashCode("SE_PowerJumpSlowFall_bal"); private static void Prefix(SEMan __instance, int nameHash, bool quiet) { try { if (nameHash == PowerJumpHash) { Character character = __instance.m_character; if (!((Object)(object)character == (Object)null) && character.IsPlayer() && character.IsOwner() && !character.IsDead()) { __instance.AddStatusEffect(SlowFallHash, true, 0, 0f); } } } catch (Exception ex) { Debug.LogError((object)("[BalrondTwinStones] Failed PowerJump -> SlowFall handoff: " + ex)); } } } private readonly Harmony harmony = new Harmony("balrond.astafaraios.BalrondTwinStones"); public const string PluginGUID = "balrond.astafaraios.BalrondTwinStones"; public const string PluginName = "BalrondTwinStones"; public const string PluginVersion = "1.0.0"; public static ModResourceLoader modResourceLoader = new ModResourceLoader(); public static DatabaseAddMethods databaseAddMethods = new DatabaseAddMethods(); public static BuildPieceBuilder buildPieceBuilder = new BuildPieceBuilder(); public static string projectName = "BalrondTwinStones"; public static GameObject RootObject; public static GameObject PrefabContainer; public static bool hasSpawned = false; public static JsonLoader jsonLoader = new JsonLoader(); public static RecipeFactory recipeFactory = new RecipeFactory(); public static Vector2 sizeDelta; public static bool addedWidth = false; private void Awake() { jsonLoader.loadJson(); createPrefabContainer(); modResourceLoader.loadAssets(); harmony.PatchAll(); } public void createPrefabContainer() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown RootObject = new GameObject("_ValheimReforgedRoot"); Object.DontDestroyOnLoad((Object)(object)RootObject); PrefabContainer = new GameObject("Prefabs"); PrefabContainer.transform.parent = RootObject.transform; PrefabContainer.SetActive(false); } public static GameObject cloneMe(GameObject source, string name) { GameObject val = Object.Instantiate<GameObject>(source, PrefabContainer.transform); ((Object)val).name = name; fixMaterials(val, source); val.SetActive(true); return val; } public static GameObject fixMaterials(GameObject clone, GameObject source) { MeshRenderer[] componentsInChildren = source.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { MeshRenderer[] componentsInChildren2 = clone.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val2 in componentsInChildren2) { if (((Object)val).name == ((Object)val2).name) { ((Renderer)val2).materials = ((Renderer)val).sharedMaterials; ((Renderer)val2).sharedMaterials = ((Renderer)val).sharedMaterials; break; } } } return clone; } private void OnDestroy() { harmony.UnpatchSelf(); } private static bool IsObjectDBValid() { return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0 && ObjectDB.instance.m_recipes.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null; } } public static class PortalPendingLinkManager { private static readonly Dictionary<long, string> PendingLinks = new Dictionary<long, string>(); public static bool TryGet(long playerId, out string portalId) { return PendingLinks.TryGetValue(playerId, out portalId); } public static void Set(long playerId, string portalId) { if (string.IsNullOrEmpty(portalId)) { PendingLinks.Remove(playerId); } else { PendingLinks[playerId] = portalId; } } public static bool Has(long playerId) { return PendingLinks.ContainsKey(playerId); } public static void Clear(long playerId) { PendingLinks.Remove(playerId); } public static void ClearByPortalId(string portalId) { if (string.IsNullOrEmpty(portalId)) { return; } List<long> list = new List<long>(); foreach (KeyValuePair<long, string> pendingLink in PendingLinks) { if (pendingLink.Value == portalId) { list.Add(pendingLink.Key); } } for (int i = 0; i < list.Count; i++) { PendingLinks.Remove(list[i]); } } public static void ClearAll() { PendingLinks.Clear(); } } public class RecipeFactory { private List<GameObject> pieces; private List<GameObject> items; private List<GameObject> newItems; public List<Recipe> recipes = new List<Recipe>(); private Dictionary<string, GameObject> _itemCache = new Dictionary<string, GameObject>(); private readonly string[] toRecipe = new string[2] { "CartBundleItemPower_bal", "CartBundleItemCargo_bal" }; public List<Recipe> createRecipes(List<GameObject> items, List<GameObject> newItems) { this.items = items; this.newItems = newItems; pieces = ObjectDB.instance.GetItemPrefab("Hammer").GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces.m_pieces; TableMapper.setupTables(null, pieces); CraftingStation forge = TableMapper.forge; int minStationLevel = 3; foreach (GameObject newItem in newItems) { if (toRecipe.Contains(((Object)newItem).name)) { if (((Object)newItem).name == "SledgeStagbreakerNEW") { Debug.LogWarning((object)"I found new Stagbreaker"); } Recipe val = ScriptableObject.CreateInstance<Recipe>(); val.m_craftingStation = forge; val.m_repairStation = forge; val.m_minStationLevel = minStationLevel; val = createResources(newItem, val); recipes.Add(val); } } return recipes; } private Recipe createResources(GameObject item, Recipe newRecipe) { ((Object)newRecipe).name = "Recipe_" + ((Object)item).name; newRecipe.m_item = item.GetComponent<ItemDrop>(); newRecipe.m_amount = 1; newRecipe.m_enabled = true; List<Requirement> list = new List<Requirement>(); string name = ((Object)item).name; string text = name; if (!(text == "CartBundleItemPower_bal")) { if (text == "CartBundleItemCargo_bal") { newRecipe.m_craftingStation = TableMapper.forge; newRecipe.m_minStationLevel = 1; newRecipe.m_amount = 1; list.Add(createReq("IronNails", 80, 0)); list.Add(createReq("FineWood", 10, 0)); list.Add(createReq("Wood", 12, 0)); list.Add(createReq("GreydwarfEye", 2, 0)); } } else { newRecipe.m_craftingStation = TableMapper.forge; newRecipe.m_minStationLevel = 1; newRecipe.m_amount = 1; list.Add(createReq("IronNails", 40, 0)); list.Add(createReq("FineWood", 10, 0)); list.Add(createReq("SurtlingCore", 2, 0)); list.Add(createReq("GreydwarfEye", 4, 0)); } newRecipe.m_repairStation = newRecipe.m_craftingStation; if (list.Count == 0) { } newRecipe.m_resources = list.ToArray(); return newRecipe; } private Requirement createReq(string name, int amount, int amountPerLevel, GameObject commonReference = null) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown object obj2; if (!((Object)(object)commonReference != (Object)null)) { GameObject obj = FindItem(name); obj2 = ((obj != null) ? obj.GetComponent<ItemDrop>() : null); } else { obj2 = commonReference.GetComponent<ItemDrop>(); } ItemDrop val = (ItemDrop)obj2; if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("createReq failed: ItemDrop missing for \"" + name + "\"")); return null; } return new Requirement { m_resItem = val, m_amount = amount, m_amountPerLevel = amountPerLevel, m_recover = true }; } private GameObject FindItem(string name) { if (_itemCache.TryGetValue(name, out var value)) { return value; } GameObject val = ObjectDB.instance.GetItemPrefab(name); if ((Object)(object)val == (Object)null && newItems != null) { val = newItems.Find((GameObject x) => ((Object)x).name == name); } if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("FindItem: \"" + name + "\" not found, using fallback \"Wood\"")); val = ObjectDB.instance.GetItemPrefab("Wood"); } if ((Object)(object)val != (Object)null) { _itemCache[name] = val; } return val; } private Recipe AddRecipe(Recipe newRecipe, int amount, CraftingStation station, int stationLevel, List<Tuple<string, int, int>> ingredients) { newRecipe.m_craftingStation = station; newRecipe.m_minStationLevel = stationLevel; newRecipe.m_amount = amount; List<Requirement> list = new List<Requirement>(); HashSet<ItemDrop> hashSet = new HashSet<ItemDrop>(); foreach (Tuple<string, int, int> ingredient in ingredients) { Requirement val = createReq(ingredient.Item1, ingredient.Item2, ingredient.Item3); if (val == null) { Debug.LogWarning((object)("Requirement skipped: " + ingredient.Item1 + " is null or invalid.")); continue; } if (hashSet.Contains(val.m_resItem)) { Debug.LogWarning((object)("Duplicate ingredient skipped: " + ((Object)val.m_resItem).name)); continue; } list.Add(val); hashSet.Add(val.m_resItem); } newRecipe.m_resources = list.ToArray(); if (list.Count == 0) { Debug.LogWarning((object)("No valid requirements found for recipe: " + ((Object)newRecipe).name)); return null; } return newRecipe; } } public class BuildPieceBuilder { private List<GameObject> list; private string[] piecesNames = BuildPieceList.buildPieces; private CraftingStation workbench; private CraftingStation tannery; private CraftingStation runeForge; private CraftingStation alchemyLab; private CraftingStation grill; private CraftingStation fletcher; private CraftingStation blackforge; private CraftingStation forge; private CraftingStation cauldron; private CraftingStation stonecutter; public void SetupBuildPieces(List<GameObject> list) { setupTables(list); this.list = list; string[] array = piecesNames; foreach (string name in array) { GameObject val = list.Find((GameObject x) => ((Object)x).name == name); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Cant find buildpiece with name: " + name)); } else { EditBuildPiece(val); } } } private void EditBuildPiece(GameObject gameObject) { //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) Piece component = gameObject.gameObject.GetComponent<Piece>(); component.m_resources = (Requirement[])(object)new Requirement[0]; SetStation(component, workbench); switch (((Object)gameObject).name) { case "railtrackSwitchRight_bal": case "railtrackSwitchLeft_bal": case "railtrack4m_bal": SetStation(component, forge); component.m_resources = (Requirement[])(object)new Requirement[0]; AddResources(component, "IronNails", 8); AddResources(component, "Wood", 8); AddResources(component, "GreydwarfEye", 2); component.m_category = (PieceCategory)0; break; case "railtrackRamp_bal": case "railtrackRamp45_bal": case "railtrack_bal": SetStation(component, forge); component.m_resources = (Requirement[])(object)new Requirement[0]; AddResources(component, "IronNails", 4); AddResources(component, "Wood", 4); AddResources(component, "GreydwarfEye", 2); component.m_category = (PieceCategory)0; break; case "RailPowerWagon_bal": SetStation(component, forge); component.m_resources = (Requirement[])(object)new Requirement[0]; AddResources(component, "CartBundleItemPower_bal", 1); component.m_category = (PieceCategory)0; break; case "RailCargoWagon_bal": SetStation(component, forge); component.m_resources = (Requirement[])(object)new Requirement[0]; AddResources(component, "CartBundleItemCargo_bal", 1); component.m_category = (PieceCategory)0; break; case "piece_obeliskPortal_bal": SetStation(component, stonecutter); component.m_resources = (Requirement[])(object)new Requirement[0]; AddResources(component, "Stone", 10); AddResources(component, "Thunderstone", 2); AddResources(component, "GreydwarfEye", 4); AddResources(component, "Iron", 2); component.m_category = (PieceCategory)0; break; } } private void setFireplaceFuelItem(Piece piece, string name, int startFuel = -1, int maxFuel = -1, float secPerFuel = -1f) { Fireplace component = ((Component)piece).GetComponent<Fireplace>(); component.m_fuelItem = FindItem(list, name).GetComponent<ItemDrop>(); component.m_startFuel = ((startFuel != -1) ? ((float)startFuel) : component.m_startFuel); component.m_maxFuel = ((maxFuel != -1) ? ((float)maxFuel) : component.m_maxFuel); component.m_secPerFuel = ((secPerFuel != -1f) ? secPerFuel : component.m_secPerFuel); } private void SetStation(Piece piece, CraftingStation station) { piece.m_craftingStation = station; } private void EditResource(Piece piece, string itemName, int amount, bool remove = false) { if (remove) { List<Requirement> list = new List<Requirement>(); Requirement[] resources = piece.m_resources; foreach (Requirement val in resources) { if (((Object)((Component)val.m_resItem).gameObject).name != itemName) { list.Add(val); } } piece.m_resources = list.ToArray(); return; } Requirement[] resources2 = piece.m_resources; foreach (Requirement val2 in resources2) { if (((Object)((Component)val2.m_resItem).gameObject).name == itemName) { val2.m_amount = amount; } } } private void AddResources(Piece piece, string itemName, int amount, int amountPerLevel = 0, string altItem = "", int altAmount = 0, int altAmountPerLevel = 0) { List<Requirement> list = new List<Requirement>(); list.AddRange(piece.m_resources); Requirement item = createReq(itemName, amount, amountPerLevel, altItem, altAmount, altAmountPerLevel); list.Add(item); piece.m_resources = list.ToArray(); } private Requirement createReq(string name, int amount, int amountPerLevel, string altItem = "", int altAmount = 0, int altAmountPerLevel = 0) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown Requirement val = new Requirement(); val.m_recover = true; GameObject val2 = list.Find((GameObject x) => ((Object)x).name == name); if ((Object)(object)val2 != (Object)null) { ItemDrop component = val2.GetComponent<ItemDrop>(); val.m_amount = amount; val.m_amountPerLevel = amountPerLevel; val.m_resItem = component; } else { val2 = FindItem(list, altItem); ItemDrop component2 = val2.GetComponent<ItemDrop>(); val.m_amount = altAmount; val.m_amountPerLevel = altAmountPerLevel; val.m_resItem = component2; } return val; } private GameObject FindItem(List<GameObject> list, string name, bool isStation = false) { GameObject val = list.Find((GameObject x) => ((Object)x).name == name); if ((Object)(object)val != (Object)null) { return val; } if ((Object)(object)val == (Object)null && isStation) { return null; } Debug.LogWarning((object)(Launch.projectName + ": Item Not Found - " + name + ", Replaced With Wood")); return list.Find((GameObject x) => ((Object)x).name == "Wood"); } private CraftingStation FindStation(List<GameObject> list, string name) { GameObject val = FindItem(list, name, isStation: true); if ((Object)(object)val != (Object)null) { return val.GetComponent<CraftingStation>(); } return null; } private void getSignToWork(Piece newSign) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) GameObject val = list.Find((GameObject x) => ((Object)x).name == "Sign"); if ((Object)(object)val != (Object)null) { Debug.LogWarning((object)"Fixing sign values"); TextMeshProUGUI textWidget = val.GetComponent<Sign>().m_textWidget; TextMeshProUGUI textWidget2 = ((Component)newSign).GetComponent<Sign>().m_textWidget; ((TMP_Text)textWidget2).font = ((TMP_Text)textWidget).font; ((Graphic)textWidget2).color = ((Graphic)textWidget).color; ((TMP_Text)textWidget2).fontSize = ((TMP_Text)textWidget).fontSize; ((TMP_Text)textWidget2).fontStyle = ((TMP_Text)textWidget).fontStyle; ((TMP_Text)textWidget2).fontSizeMax = ((TMP_Text)textWidget).fontSizeMax; ((TMP_Text)textWidget2).fontFeatures = ((TMP_Text)textWidget).fontFeatures; ((TMP_Text)textWidget2).fontSharedMaterial = ((TMP_Text)textWidget).fontSharedMaterial; ((TMP_Text)textWidget2).fontSharedMaterials = ((TMP_Text)textWidget).fontSharedMaterials; ((TMP_Text)textWidget2).fontMaterial = ((TMP_Text)textWidget).fontMaterial; ((TMP_Text)textWidget2).fontMaterials = ((TMP_Text)textWidget).fontMaterials; } } private void setupTables(List<GameObject> list) { workbench = FindStation(list, "piece_workbench"); if ((Object)(object)workbench == (Object)null) { Debug.LogWarning((object)"Did not foundpiece_workbench"); } tannery = FindStation(list, "piece_tannery"); if ((Object)(object)tannery == (Object)null) { tannery = workbench; } blackforge = FindStation(list, "blackforge"); if ((Object)(object)blackforge == (Object)null) { Debug.LogWarning((object)"Did not foundblackforge"); } forge = FindStation(list, "forge"); if ((Object)(object)forge == (Object)null) { Debug.LogWarning((object)"Did not foundforge"); } cauldron = FindStation(list, "piece_cauldron"); if ((Object)(object)cauldron == (Object)null) { Debug.LogWarning((object)"Did not foundpiece_cauldron"); } runeForge = FindStation(list, "piece_runeforge"); if ((Object)(object)runeForge == (Object)null) { runeForge = forge; } alchemyLab = FindStation(list, "piece_alchemylab"); if ((Object)(object)alchemyLab == (Object)null) { alchemyLab = cauldron; } grill = FindStation(list, "piece_grill"); if ((Object)(object)grill == (Object)null) { grill = cauldron; } fletcher = FindStation(list, "piece_fletcher"); if ((Object)(object)fletcher == (Object)null) { fletcher = workbench; } stonecutter = FindStation(list, "piece_stonecutter"); if ((Object)(object)stonecutter == (Object)null) { Debug.LogWarning((object)"Did not foundpiece_stonecutter"); stonecutter = workbench; } } } public class Resource { public int amount = 1; public int amountPerLevel = 0; public bool recovery = true; public ItemDrop itemDrop; public Requirement pieceConfig; public string item = "Wood"; public Resource() { } public Resource(string item, int amount, int amountPerLevel = 0, bool recovery = true) { this.item = item; this.amount = amount; this.amountPerLevel = amountPerLevel; this.recovery = recovery; } public void setItemDrop(GameObject prefab) { if ((Object)(object)prefab.GetComponent<ItemDrop>() != (Object)null) { itemDrop = prefab.GetComponent<ItemDrop>(); } else { Debug.LogWarning((object)("DVERGER FURNITURE: NO ITEM DROP FOUND on prefab name: " + ((Object)prefab).name)); } } public Requirement getPieceConfig() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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: Expected O, but got Unknown //IL_003e: Expected O, but got Unknown Requirement val = new Requirement { m_resItem = itemDrop, m_amount = amount, m_amountPerLevel = amountPerLevel, m_recover = recovery }; Requirement result = val; pieceConfig = val; return result; } } public class TableMapper { public static CraftingStation cauldron; public static CraftingStation workbench; public static CraftingStation heavyWorkbench; public static CraftingStation forge; public static CraftingStation ironworks; public static CraftingStation blackforge; public static CraftingStation stoneCutter; public static CraftingStation artisian; public static CraftingStation magetable; public static CraftingStation runeforge; public static CraftingStation tannery; public static CraftingStation fletcher; public static CraftingStation grill; public static CraftingStation alchemylab; public static CraftingStation shamantable; public static CraftingStation foodtable; public static CraftingStation smeltworks; public static ZNetScene zNetScene; public static List<GameObject> list = new List<GameObject>(); public static void setupTables(ZNetScene zNetScene = null, List<GameObject> list = null) { TableMapper.zNetScene = zNetScene; TableMapper.list = list; prepareTables(); } private static GameObject FindPrefabInZnet(string name, ZNetScene zNetScene) { GameObject value = null; zNetScene.m_namedPrefabs.TryGetValue(StringExtensionMethods.GetStableHashCode(name), out value); if ((Object)(object)value == (Object)null) { value = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == name); } return value; } private static CraftingStation FindStation(string name) { GameObject val = null; val = (GameObject)((!((Object)(object)zNetScene != (Object)null)) ? ((object)list.Find((GameObject x) => ((Object)x).name == name)) : ((object)FindPrefabInZnet(name, zNetScene))); if ((Object)(object)val != (Object)null) { return val.GetComponent<CraftingStation>(); } Debug.LogWarning((object)("TableMapper - Station not found: " + name)); return null; } private static void prepareTables() { cauldron = FindStation("piece_cauldron"); workbench = FindStation("piece_workbench"); heavyWorkbench = FindStation("piece_heavy_workbench_bal"); forge = FindStation("forge"); ironworks = FindStation("piece_metalworks_bal"); blackforge = FindStation("blackforge"); stoneCutter = FindStation("piece_stonecutter"); artisian = FindStation("piece_artisanstation"); runeforge = FindStation("piece_runeforge_bal"); magetable = FindStation("piece_magetable"); fletcher = FindStation("piece_fletcher_bal"); shamantable = FindStation("piece_shamantable_bal"); foodtable = FindStation("piece_preptable"); grill = FindStation("piece_grill_bal"); alchemylab = FindStation("piece_MeadCauldron"); smeltworks = FindStation("piece_scrapsmelter_bal"); } } [HarmonyPatch] internal static class TranslationPatches { [HarmonyPatch(typeof(FejdStartup), "SetupGui")] private class FejdStartup_SetupGUI { private static void Postfix() { string selectedLanguage = Localization.instance.GetSelectedLanguage(); Dictionary<string, string> translations = GetTranslations(selectedLanguage); AddTranslations(translations); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(Localization), "SetupLanguage")] private class Translation_SetupLanguage { private static void Prefix(Localization __instance, string language) { Dictionary<string, string> translations = GetTranslations(language); AddTranslations(translations, __instance); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(Localization), "LoadCSV")] private class Translation_LoadCSV { private static void Prefix(Localization __instance, string language) { Dictionary<string, string> translations = GetTranslations(language); AddTranslations(translations, __instance); } } private static Dictionary<string, string> GetTranslations(string language) { Dictionary<string, string> result = BalrondTranslator.getLanguage("English"); if (!string.Equals(language, "English", StringComparison.OrdinalIgnoreCase)) { Dictionary<string, string> language2 = BalrondTranslator.getLanguage(language); if (language2 != null) { result = language2; } else { Debug.Log((object)("BalrondTwinStones: Did not find translation file for '" + language + "', loading English")); } } return result; } private static void AddTranslations(Dictionary<string, string> translations, Localization localizationInstance = null) { if (translations == null) { Debug.LogWarning((object)"BalrondTwinStones: No translation file found!"); return; } if (localizationInstance != null) { foreach (KeyValuePair<string, string> translation in translations) { localizationInstance.AddWord(translation.Key, translation.Value); } return; } foreach (KeyValuePair<string, string> translation2 in translations) { Localization.instance.AddWord(translation2.Key, translation2.Value); } } } } namespace LitJson2 { internal enum JsonType { None, Object, Array, String, Int, Long, Double, Boolean } internal interface IJsonWrapper : IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable { bool IsArray { get; } bool IsBoolean { get; } bool IsDouble { get; } bool IsInt { get; } bool IsLong { get; } bool IsObject { get; } bool IsString { get; } bool GetBoolean(); double GetDouble(); int GetInt(); JsonType GetJsonType(); long GetLong(); string GetString(); void SetBoolean(bool val); void SetDouble(double val); void SetInt(int val); void SetJsonType(JsonType type); void SetLong(long val); void SetString(string val); string ToJson(); void ToJson(JsonWriter writer); } internal class JsonData : IJsonWrapper, IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable, IEquatable<JsonData> { private IList<JsonData> inst_array; private bool inst_boolean; private double inst_double; private int inst_int; private long inst_long; private IDictionary<string, JsonData> inst_object; private string inst_string; private string json; private JsonType type; private IList<KeyValuePair<string, JsonData>> object_list; public int Count => EnsureCollection().Count; public bool IsArray => type == JsonType.Array; public bool IsBoolean => type == JsonType.Boolean; public bool IsDouble => type == JsonType.Double; public bool IsInt => type == JsonType.Int; public bool IsLong => type == JsonType.Long; public bool IsObject => type == JsonType.Object; public bool IsString => type == JsonType.String; public ICollection<string> Keys { get { EnsureDictionary(); return inst_object.Keys; } } int ICollection.Count => Count; bool ICollection.IsSynchronized => EnsureCollection().IsSynchronized; object ICollection.SyncRoot => EnsureCollection().SyncRoot; bool IDictionary.IsFixedSize => EnsureDictionary().IsFixedSize; bool IDictionary.IsReadOnly => EnsureDictionary().IsReadOnly; ICollection IDictionary.Keys { get { EnsureDictionary(); IList<string> list = new List<string>(); foreach (KeyValuePair<string, JsonData> item in object_list) { list.Add(item.Key); } return (ICollection)list; } } ICollection IDictionary.Values { get { EnsureDictionary(); IList<JsonData> list = new List<JsonData>(); foreach (KeyValuePair<string, JsonData> item in object_list) { list.Add(item.Value); } return (ICollection)list; } } bool IJsonWrapper.IsArray => IsArray; bool IJsonWrapper.IsBoolean => IsBoolean; bool IJsonWrapper.IsDouble => IsDouble; bool IJsonWrapper.IsInt => IsInt; bool IJsonWrapper.IsLong => IsLong; bool IJsonWrapper.IsObject => IsObject; bool IJsonWrapper.IsString => IsString; bool IList.IsFixedSize => EnsureList().IsFixedSize; bool IList.IsReadOnly => EnsureList().IsReadOnly; object IDictionary.this[object key] { get { return EnsureDictionary()[key]; } set { if (!(key is string)) { throw new ArgumentException("The key has to be a string"); } JsonData value2 = ToJsonData(value); this[(string)key] = value2; } } object IOrderedDictionary.this[int idx] { get { EnsureDictionary(); return object_list[idx].Value; } set { EnsureDictionary(); JsonData value2 = ToJsonData(value); KeyValuePair<string, JsonData> keyValuePair = object_list[idx]; inst_object[keyValuePair.Key] = value2; KeyValuePair<string, JsonData> value3 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value2); object_list[idx] = value3; } } object IList.this[int index] { get { return EnsureList()[index]; } set { EnsureList(); JsonData value2 = ToJsonData(value); this[index] = value2; } } public JsonData this[string prop_name] { get { EnsureDictionary(); return inst_object[prop_name]; } set { EnsureDictionary(); KeyValuePair<string, JsonData> keyValuePair = new KeyValuePair<string, JsonData>(prop_name, value); if (inst_object.ContainsKey(prop_name)) { for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == prop_name) { object_list[i] = keyValuePair; break; } } } else { object_list.Add(keyValuePair); } inst_object[prop_name] = value; json = null; } } public JsonData this[int index] { get { EnsureCollection(); if (type == JsonType.Array) { return inst_array[index]; } return object_list[index].Value; } set { EnsureCollection(); if (type == JsonType.Array) { inst_array[index] = value; } else { KeyValuePair<string, JsonData> keyValuePair = object_list[index]; KeyValuePair<string, JsonData> value2 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value); object_list[index] = value2; inst_object[keyValuePair.Key] = value; } json = null; } } public JsonData() { } public JsonData(bool boolean) { type = JsonType.Boolean; inst_boolean = boolean; } public JsonData(double number) { type = JsonType.Double; inst_double = number; } public JsonData(int number) { type = JsonType.Int; inst_int = number; } public JsonData(long number) { type = JsonType.Long; inst_long = number; } public JsonData(object obj) { if (obj is bool) { type = JsonType.Boolean; inst_boolean = (bool)obj; return; } if (obj is double) { type = JsonType.Double; inst_double = (double)obj; return; } if (obj is int) { type = JsonType.Int; inst_int = (int)obj; return; } if (obj is long) { type = JsonType.Long; inst_long = (long)obj; return; } if (obj is string) { type = JsonType.String; inst_string = (string)obj; return; } throw new ArgumentException("Unable to wrap the given object with JsonData"); } public JsonData(string str) { type = JsonType.String; inst_string = str; } public static implicit operator JsonData(bool data) { return new JsonData(data); } public static implicit operator JsonData(double data) { return new JsonData(data); } public static implicit operator JsonData(int data) { return new JsonData(data); } public static implicit operator JsonData(long data) { return new JsonData(data); } public static implicit operator JsonData(string data) { return new JsonData(data); } public static explicit operator bool(JsonData data) { if (data.type != JsonType.Boolean) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_boolean; } public static explicit operator double(JsonData data) { if (data.type != JsonType.Double) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_double; } public static explicit operator int(JsonData data) { if (data.type != JsonType.Int) { throw new InvalidCastException("Instance of JsonData doesn't hold an int"); } return data.inst_int; } public static explicit operator long(JsonData data) { if (data.type != JsonType.Long) { throw new InvalidCastException("Instance of JsonData doesn't hold an int"); } return data.inst_long; } public static explicit operator string(JsonData data) { if (data.type != JsonType.String) { throw new InvalidCastException("Instance of JsonData doesn't hold a string"); } return data.inst_string; } void ICollection.CopyTo(Array array, int index) { EnsureCollection().CopyTo(array, index); } void IDictionary.Add(object key, object value) { JsonData value2 = ToJsonData(value); EnsureDictionary().Add(key, value2); KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>((string)key, value2); object_list.Add(item); json = null; } void IDictionary.Clear() { EnsureDictionary().Clear(); object_list.Clear(); json = null; } bool IDictionary.Contains(object key) { return EnsureDictionary().Contains(key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return ((IOrderedDictionary)this).GetEnumerator(); } void IDictionary.Remove(object key) { EnsureDictionary().Remove(key); for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == (string)key) { object_list.RemoveAt(i); break; } } json = null; } IEnumerator IEnumerable.GetEnumerator() { return EnsureCollection().GetEnumerator(); } bool IJsonWrapper.GetBoolean() { if (type != JsonType.Boolean) { throw new InvalidOperationException("JsonData instance doesn't hold a boolean"); } return inst_boolean; } double IJsonWrapper.GetDouble() { if (type != JsonType.Double) { throw new InvalidOperationException("JsonData instance doesn't hold a double"); } return inst_double; } int IJsonWrapper.GetInt() { if (type != JsonType.Int) { throw new InvalidOperationException("JsonData instance doesn't hold an int"); } return inst_int; } long IJsonWrapper.GetLong() { if (type != JsonType.Long) { throw new InvalidOperationException("JsonData instance doesn't hold a long"); } return inst_long; } string IJsonWrapper.GetString() { if (type != JsonType.String) { throw new InvalidOperationException("JsonData instance doesn't hold a string"); } return inst_string; } void IJsonWrapper.SetBoolean(bool val) { type = JsonType.Boolean; inst_boolean = val; json = null; } void IJsonWrapper.SetDouble(double val) { type = JsonType.Double; inst_double = val; json = null; } void IJsonWrapper.SetInt(int val) { type = JsonType.Int; inst_int = val; json = null; } void IJsonWrapper.SetLong(long val) { type = JsonType.Long; inst_long = val; json = null; } void IJsonWrapper.SetString(string val) { type = JsonType.String; inst_string = val; json = null; } string IJsonWrapper.ToJson() { return ToJson(); } void IJsonWrapper.ToJson(JsonWriter writer) { ToJson(writer); } int IList.Add(object value) { return Add(value); } void IList.Clear() { EnsureList().Clear(); json = null; } bool IList.Contains(object value) { return EnsureList().Contains(value); } int IList.IndexOf(object value) { return EnsureList().IndexOf(value); } void IList.Insert(int index, object value) { EnsureList().Insert(index, value); json = null; } void IList.Remove(object value) { EnsureList().Remove(value); json = null; } void IList.RemoveAt(int index) { EnsureList().RemoveAt(index); json = null; } IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { EnsureDictionary(); return new OrderedDictionaryEnumerator(object_list.GetEnumerator()); } void IOrderedDictionary.Insert(int idx, object key, object value) { string text = (string)key; JsonData value2 = (this[text] = ToJsonData(value)); KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>(text, value2); object_list.Insert(idx, item); } void IOrderedDictionary.RemoveAt(int idx) { EnsureDictionary(); inst_object.Remove(object_list[idx].Key); object_list.RemoveAt(idx); } private ICollection EnsureCollection() { if (type == JsonType.Array) { return (ICollection)inst_array; } if (type == JsonType.Object) { return (ICollection)inst_object; } throw new InvalidOperationException("The JsonData instance has to be initialized first"); } private IDictionary EnsureDictionary() { if (type == JsonType.Object) { return (IDictionary)inst_object; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a dictionary"); } type = JsonType.Object; inst_object = new Dictionary<string, JsonData>(); object_list = new List<KeyValuePair<string, JsonData>>(); return (IDictionary)inst_object; } private IList EnsureList() { if (type == JsonType.Array) { return (IList)inst_array; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a list"); } type = JsonType.Array; inst_array = new List<JsonData>(); return (IList)inst_array; } private JsonData ToJsonData(object obj) { if (obj == null) { return null; } if (obj is JsonData) { return (JsonData)obj; } return new JsonData(obj); } private static void WriteJson(IJsonWrapper obj, JsonWriter writer) { if (obj == null) { writer.Write(null); } else if (obj.IsString) { writer.Write(obj.GetString()); } else if (obj.IsBoolean) { writer.Write(obj.GetBoolean()); } else if (obj.IsDouble) { writer.Write(obj.GetDouble()); } else if (obj.IsInt) { writer.Write(obj.GetInt()); } else if (obj.IsLong) { writer.Write(obj.GetLong()); } else if (obj.IsArray) { writer.WriteArrayStart(); foreach (object item in (IEnumerable)obj) { WriteJson((JsonData)item, writer); } writer.WriteArrayEnd(); } else { if (!obj.IsObject) { return; } writer.WriteObjectStart(); foreach (DictionaryEntry item2 in (IDictionary)obj) { writer.WritePropertyName((string)item2.Key); WriteJson((JsonData)item2.Value, writer); } writer.WriteObjectEnd(); } } public int Add(object value) { JsonData value2 = ToJsonData(value); json = null; return EnsureList().Add(value2); } public void Clear() { if (IsObject) { ((IDictionary)this).Clear(); } else if (IsArray) { ((IList)this).Clear(); } } public bool Equals(JsonData x) { if (x == null) { return false; } if (x.type != type) { return false; } return type switch { JsonType.None => true, JsonType.Object => inst_object.Equals(x.inst_object), JsonType.Array => inst_array.Equals(x.inst_array), JsonType.String => inst_string.Equals(x.inst_string), JsonType.Int => inst_int.Equals(x.inst_int), JsonType.Long => inst_long.Equals(x.inst_long), JsonType.Double => inst_double.Equals(x.inst_double), JsonType.Boolean => inst_boolean.Equals(x.inst_boolean), _ => false, }; } public JsonType GetJsonType() { return type; } public void SetJsonType(JsonType type) { if (this.type != type) { switch (type) { case JsonType.Object: inst_object = new Dictionary<string, JsonData>(); object_list = new List<KeyValuePair<string, JsonData>>(); break; case JsonType.Array: inst_array = new List<JsonData>(); break; case JsonType.String: inst_string = null; break; case JsonType.Int: inst_int = 0; break; case JsonType.Long: inst_long = 0L; break; case JsonType.Double: inst_double = 0.0; break; case JsonType.Boolean: inst_boolean = false; break; } this.type = type; } } public string ToJson() { if (json != null) { return json; } StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); jsonWriter.Validate = false; WriteJson(this, jsonWriter); json = stringWriter.ToString(); return json; } public void ToJson(JsonWriter writer) { bool validate = writer.Validate; writer.Validate = false; WriteJson(this, writer); writer.Validate = validate; } public override string ToString() { return type switch { JsonType.Array => "JsonData array", JsonType.Boolean => inst_boolean.ToString(), JsonType.Double => inst_double.ToString(), JsonType.Int => inst_int.ToString(), JsonType.Long => inst_long.ToString(), JsonType.Object => "JsonData object", JsonType.String => inst_string, _ => "Uninitialized JsonData", }; } } internal class OrderedDictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private IEnumerator<KeyValuePair<string, JsonData>> list_enumerator; public object Current => Entry; public DictionaryEntry Entry { get { KeyValuePair<string, JsonData> current = list_enumerator.Current; return new DictionaryEntry(current.Key, current.Value); } } public object Key => list_enumerator.Current.Key; public object Value => list_enumerator.Current.Value; public OrderedDictionaryEnumerator(IEnumerator<KeyValuePair<string, JsonData>> enumerator) { list_enumerator = enumerator; } public bool MoveNext() { return list_enumerator.MoveNext(); } public void Reset() { list_enumerator.Reset(); } } internal class JsonException : ApplicationException { public JsonException() { } internal JsonException(ParserToken token) : base($"Invalid token '{token}' in input string") { } internal JsonException(ParserToken token, Exception inner_exception) : base($"Invalid token '{token}' in input string", inner_exception) { } internal JsonException(int c) : base($"Invalid character '{(char)c}' in input string") { } internal JsonException(int c, Exception inner_exception) : base($"Invalid character '{(char)c}' in input string", inner_exception) { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception inner_exception) : base(message, inner_exception) { } } internal struct PropertyMetadata { public MemberInfo Info; public bool IsField; public Type Type; } internal struct ArrayMetadata { private Type element_type; private bool is_array; private bool is_list; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsArray { get { return is_array; } set { is_array = value; } } public bool IsList { get { return is_list; } set { is_list = value; } } } internal struct ObjectMetadata { private Type element_type; private bool is_dictionary; private IDictionary<string, PropertyMetadata> properties; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsDictionary { get { return is_dictionary; } set { is_dictionary = value; } } public IDictionary<string, PropertyMetadata> Properties { get { return properties; } set { properties = value; } } } internal delegate void ExporterFunc(object obj, JsonWriter writer); internal delegate void ExporterFunc<T>(T obj, JsonWriter writer); internal delegate object ImporterFunc(object input); internal delegate TValue ImporterFunc<TJson, TValue>(TJson input); internal delegate IJsonWrapper WrapperFactory(); internal class JsonMapper { private static int max_nesting_depth; private static IFormatProvider datetime_format; private static IDictionary<Type, ExporterFunc> base_exporters_table; private static IDictionary<Type, ExporterFunc> custom_exporters_table; private static IDictionary<Type, IDictionary<Type, ImporterFunc>> base_importers_table; private static IDictionary<Type, IDictionary<Type, ImporterFunc>> custom_importers_table; private static IDictionary<Type, ArrayMetadata> array_metadata; private static readonly object array_metadata_lock; private static IDictionary<Type, IDictionary<Type, MethodInfo>> conv_ops; private static readonly object conv_ops_lock; private static IDictionary<Type, ObjectMetadata> object_metadata; private static readonly object object_metadata_lock; private static IDictionary<Type, IList<PropertyMetadata>> type_properties; private static readonly object type_properties_lock; private static JsonWriter static_writer; private static readonly object static_writer_lock; static JsonMapper() { array_metadata_lock = new object(); conv_ops_lock = new object(); object_metadata_lock = new object(); type_properties_lock = new object(); static_writer_lock = new object(); max_nesting_depth = 100; array_metadata = new Dictionary<Type, ArrayMetadata>(); conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>(); object_metadata = new Dictionary<Type, ObjectMetadata>(); type_properties = new Dictionary<Type, IList<PropertyMetadata>>(); static_writer = new JsonWriter(); datetime_format = DateTimeFormatInfo.InvariantInfo; base_exporters_table = new Dictionary<Type, ExporterFunc>(); custom_exporters_table = new Dictionary<Type, ExporterFunc>(); base_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>(); custom_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>(); RegisterBaseExporters(); RegisterBaseImporters(); } private static void AddArrayMetadata(Type type) { if (array_metadata.ContainsKey(type)) { return; } ArrayMetadata value = default(ArrayMetadata); value.IsArray = type.IsArray; if (type.GetInterface("System.Collections.IList") != null) { value.IsList = true; } PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name != "Item")) { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(int)) { value.ElementType = propertyInfo.PropertyType; } } } lock (array_metadata_lock) { try { array_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddObjectMetadata(Type type) { if (object_metadata.ContainsKey(type)) { return; } ObjectMetadata value = default(ObjectMetadata); if (type.GetInterface("System.Collections.IDictionary") != null) { value.IsDictionary = true; } value.Properties = new Dictionary<string, PropertyMetadata>(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.Name == "Item") { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(string)) { value.ElementType = propertyInfo.PropertyType; } } else { PropertyMetadata value2 = default(PropertyMetadata); value2.Info = propertyInfo; value2.Type = propertyInfo.PropertyType; value.Properties.Add(propertyInfo.Name, value2); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo fieldInfo in fields) { PropertyMetadata value3 = default(PropertyMetadata); value3.Info = fieldInfo; value3.IsField = true; value3.Type = fieldInfo.FieldType; value.Properties.Add(fieldInfo.Name, value3); } lock (object_metadata_lock) { try { object_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddTypeProperties(Type type) { if (type_properties.ContainsKey(type)) { return; } IList<PropertyMetadata> list = new List<PropertyMetadata>(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name == "Item")) { PropertyMetadata item = default(PropertyMetadata); item.Info = propertyInfo; item.IsField = false; list.Add(item); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo info in fields) { PropertyMetadata item2 = default(PropertyMetadata); item2.Info = info; item2.IsField = true; list.Add(item2); } lock (type_properties_lock) { try { type_properties.Add(type, list); } catch (ArgumentException) { } } } private static MethodInfo GetConvOp(Type t1, Type t2) { lock (conv_ops_lock) { if (!conv_ops.ContainsKey(t1)) { conv_ops.Add(t1, new Dictionary<Type, MethodInfo>()); } } if (conv_ops[t1].ContainsKey(t2)) { return conv_ops[t1][t2]; } MethodInfo method = t1.GetMethod("op_Implicit", new Type[1] { t2 }); lock (conv_ops_lock) { try { conv_ops[t1].Add(t2, method); return method; } catch (ArgumentException) { return conv_ops[t1][t2]; } } } private static object ReadValue(Type inst_type, JsonReader reader) { reader.Read(); if (reader.Token == JsonToken.A