Decompiled source of Campfire Building v2.0.0
tony4twentys-Campfire Building.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; using Zorro.Core; using Zorro.Core.Serizalization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyTitle("Campfire Building")] [assembly: AssemblyDescription("BepInEx plugin for PEAK that requires firewood before lighting campfires")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("tony4twentys")] [assembly: AssemblyProduct("Campfire Building")] [assembly: AssemblyCopyright("Copyright © tony4twentys 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("69efbd55-05ad-4c68-8483-6d8e9db0b1c9")] [assembly: AssemblyFileVersion("2.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.0.0")] [module: UnverifiableCode] namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace tony4twentys.Campfire_Building { [BepInPlugin("tony4twentys.Campfire_Building", "Campfire Building", "2.0.0")] [BepInProcess("PEAK.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "tony4twentys.Campfire_Building"; public const string PluginName = "Campfire Building"; public const string PluginVersion = "2.0.0"; internal const string SummitToShoreGuid = "tony4twentys.Summit_to_Shore"; internal const byte EventCode = 159; internal const int ProtocolVersion = 7; internal const string EventMagic = "tony4twentys.Campfire_Building"; internal const int ConfigPayloadLength = 9; internal const string FirewoodPrefabName = "FireWood"; internal const string StonePrefabName = "Stone"; internal const ushort FirewoodItemId = 28; internal const ushort StoneItemId = 72; internal const int DefaultRequiredFirewood = 3; internal const int HighAscentRequiredFirewood = 6; internal const int HighAscentMinimum = 5; internal const string AddFirewoodPrompt = "ADD FIREWOOD ({current}/{required})"; internal const string NeedFirewoodPrompt = "NEED FIREWOOD ({current}/{required})"; internal const string AddStonesPrompt = "ADD STONES ({current}/{required})"; internal const string NeedStonesPrompt = "NEED STONES ({current}/{required})"; internal static ConfigEntry<bool> EnableSpawning; internal static ConfigEntry<bool> EnableDebugLogging; internal static ConfigEntry<bool> Stacking; internal static ConfigEntry<KeyCode> DropOneFromStack; internal static ConfigEntry<int> SpawnsPerSegment; internal static ConfigEntry<float> SpawnCooldown; internal static ConfigEntry<bool> SpawnsInKilnCitadel; internal static ConfigEntry<bool> EnableStones; internal static bool syncedEnableSpawning = true; internal static int syncedSpawnsPerSegment = 60; internal static float syncedSpawnCooldown = 15f; internal static bool syncedSpawnsInKilnCitadel = false; internal static bool syncedEnableStones = true; internal static bool syncedStacking = true; internal static bool SummitToShorePresent; internal static bool isHandshakeValid = true; private Harmony _harmony; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static bool IsGameplayEnabled { get { try { if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient) { return true; } } catch { return isHandshakeValid; } return isHandshakeValid; } } internal static int ItemCap { get { int num = Mathf.Clamp(syncedSpawnsPerSegment, 0, 200); if (!syncedEnableStones) { return num; } return num / 2; } } internal static int CurrentAscent { get { try { return Ascents.currentAscent; } catch { return 0; } } } internal static int RequiredFirewoodCount { get { if (CurrentAscent < 5) { return 3; } return 6; } } internal static int RequiredStoneCount => RequiredFirewoodCount; internal static bool StonesEnabled { get { if (syncedEnableStones) { return IsGameplayEnabled; } return false; } } internal static bool DebugLogs { get { try { return EnableDebugLogging != null && EnableDebugLogging.Value; } catch { return false; } } } private void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfig(); SummitToShorePresent = DetectSummitToShore(); if (SummitToShorePresent) { DebugLog("[Campfire Building] Summit to Shore detected — Kiln/Citadel ping spawns enabled."); } ApplyLocalConfig(); if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient) { isHandshakeValid = true; } _harmony = new Harmony("tony4twentys.Campfire_Building"); PatchAllSafe(); BuildFireNet.Ensure(); ((MonoBehaviour)this).StartCoroutine(FirewoodStack.WatchDropOne()); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { BuildFireNet.OnLocalSettingChanged(); }; Log.LogInfo((object)string.Format("{0} v{1} loaded. Photon {2}.", "Campfire Building", "2.0.0", (byte)159)); } private void BindConfig() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDebugLogging", false, "Local only. Log ping spawns, biome stingers, and handshake details."); Stacking = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Stacking", true, "Host only. Stack sticks and stones in one inventory slot (count on the name, extra carry weight). Off = vanilla inventory, one item per slot, no name/count changes."); DropOneFromStack = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "DropOneFromStack", (KeyCode)122, "Local only. Drop one stick or stone from the held stack. Vanilla drop still throws the whole stack. Does nothing if you are holding a single item."); EnableSpawning = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "EnableSpawning", true, "Host only. Players ping nearby plants and the host drops sticks and stones beside them, up to SpawnsPerSegment per biome. Turn off if another mod already spawns sticks."); int num = 60; ConfigDefinition val = new ConfigDefinition("Spawning", "FirewoodPerSegment"); if (((BaseUnityPlugin)this).Config.ContainsKey(val)) { try { num = Convert.ToInt32(((BaseUnityPlugin)this).Config[val].BoxedValue); } catch { } ((BaseUnityPlugin)this).Config.Remove(val); } SpawnsPerSegment = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "SpawnsPerSegment", num, "Host only. Max ping-spawns per biome. Split 50/50 when stones are on (60 → 30 stones + 30 sticks). Sticks use the full value if stones are off."); SpawnCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "SpawnCooldown", 15f, "Host only. Seconds between ping-spawns. Host value is synced to the room."); bool flag = false; ConfigDefinition val2 = new ConfigDefinition("Spawning", "SpawnSticksKilnCitadel"); if (((BaseUnityPlugin)this).Config.ContainsKey(val2)) { try { flag = Convert.ToBoolean(((BaseUnityPlugin)this).Config[val2].BoxedValue); } catch { } ((BaseUnityPlugin)this).Config.Remove(val2); } SpawnsInKilnCitadel = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "SpawnsInKilnCitadel", flag, "Host only. Also ping-spawn sticks and stones in Kiln/Citadel. Leave off for a normal climb. Turned on automatically when Summit to Shore is loaded."); EnableStones = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "EnableStones", true, "Host only. Spawn stones and require a stone ring (hologram) before firewood. Turn off to skip stones, holograms, and VFX_Smoke_Off changes."); } internal static void ApplyLocalConfig() { syncedEnableSpawning = EnableSpawning.Value; syncedSpawnsPerSegment = Mathf.Clamp(SpawnsPerSegment.Value, 0, 200); syncedSpawnCooldown = Mathf.Clamp(SpawnCooldown.Value, 0f, 300f); syncedSpawnsInKilnCitadel = SpawnsInKilnCitadel.Value || SummitToShorePresent; syncedEnableStones = EnableStones.Value; syncedStacking = Stacking.Value; CampfireStones.RefreshAll(); } internal static object[] BuildConfigPayload(byte sub) { return new object[9] { "tony4twentys.Campfire_Building", 7, sub, EnableSpawning.Value, SpawnsPerSegment.Value, SpawnsInKilnCitadel.Value || SummitToShorePresent, EnableStones.Value, SpawnCooldown.Value, Stacking.Value }; } internal static void ApplyRemoteConfig(object[] arr) { if (arr == null || arr.Length < 9) { throw new InvalidOperationException("Campfire Building config payload too short."); } syncedEnableSpawning = Convert.ToBoolean(arr[3]); syncedSpawnsPerSegment = Mathf.Clamp(Convert.ToInt32(arr[4]), 0, 200); syncedSpawnsInKilnCitadel = Convert.ToBoolean(arr[5]); syncedEnableStones = Convert.ToBoolean(arr[6]); syncedSpawnCooldown = Mathf.Clamp(Convert.ToSingle(arr[7]), 0f, 300f); syncedStacking = Convert.ToBoolean(arr[8]); CampfireStones.RefreshAll(); } internal static string FormatPrompt(bool holdingFirewood, int current, int required) { return (holdingFirewood ? "ADD FIREWOOD ({current}/{required})" : "NEED FIREWOOD ({current}/{required})").Replace("{current}", current.ToString()).Replace("{required}", required.ToString()); } internal static string FormatStonePrompt(bool holdingStone, int current, int required) { return (holdingStone ? "ADD STONES ({current}/{required})" : "NEED STONES ({current}/{required})").Replace("{current}", current.ToString()).Replace("{required}", required.ToString()); } internal static bool IsFirewoodItemId(ushort itemId) { return itemId == 28; } internal static bool IsStoneItemId(ushort itemId) { return itemId == 72; } internal static void DebugLog(string message) { if (DebugLogs) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)message); } } } internal static void LogOnce(ref bool flag, string message, Exception ex) { if (flag) { return; } flag = true; if (ex != null) { ManualLogSource log = Log; if (log != null) { log.LogError((object)(message + " " + ex)); } } else { ManualLogSource log2 = Log; if (log2 != null) { log2.LogError((object)message); } } } private static bool DetectSummitToShore() { try { return Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("tony4twentys.Summit_to_Shore"); } catch { return false; } } private void PatchAllSafe() { Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { if (!(type == null) && type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0) { try { _harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { Log.LogError((object)("[Campfire Building] Patch failed on " + type.Name + ": " + ex.Message)); } } } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } internal sealed class BuildFireNet : MonoBehaviourPunCallbacks, IOnEventCallback { internal const byte SubConfig = 1; internal const byte SubConfigRequest = 2; internal const byte SubFirewood = 3; internal const byte SubSnapshot = 4; internal const byte SubSnapshotRequest = 5; internal const byte SubPingSpawn = 6; internal const byte SubPingCount = 7; internal const byte SubStones = 8; internal const byte SubStoneSnapshot = 9; internal const byte SubDropOne = 10; private const float HostSyncTimeoutSeconds = 12f; private const float HostSyncRetrySeconds = 2f; internal static bool HostModConfirmed; private Coroutine _debounce; private Coroutine _hostSyncWatch; private bool _syncingFromNet; internal static BuildFireNet Instance { get; private set; } internal static void Ensure() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if ((Object)(object)Instance != (Object)null) { return; } GameObject val = new GameObject("CampfireBuilding_Net"); Object.DontDestroyOnLoad((Object)val); Instance = val.AddComponent<BuildFireNet>(); try { if (PhotonNetwork.InRoom) { Instance.HandleJoinedRoom(); } } catch { } } private void Awake() { Instance = this; } public override void OnEnable() { ((MonoBehaviourPunCallbacks)this).OnEnable(); PhotonNetwork.AddCallbackTarget((object)this); } public override void OnDisable() { PhotonNetwork.RemoveCallbackTarget((object)this); ((MonoBehaviourPunCallbacks)this).OnDisable(); } public override void OnJoinedRoom() { HandleJoinedRoom(); } public override void OnLeftRoom() { StopHostSyncWatch(); HostModConfirmed = false; Plugin.isHandshakeValid = true; Plugin.ApplyLocalConfig(); CampfireWood.ResetAll(); CampfireStones.ResetAll(); FirewoodSpawner.ResetRun(); } public override void OnMasterClientSwitched(Player newMasterClient) { if (PhotonNetwork.IsMasterClient) { HostModConfirmed = true; Plugin.isHandshakeValid = true; Plugin.ApplyLocalConfig(); BroadcastNow(); BroadcastWoodSnapshot(); BroadcastStoneSnapshot(); FirewoodPing.BroadcastAllCounts(); FirewoodPing.Ensure(); StopHostSyncWatch(); } else { HostModConfirmed = false; Plugin.isHandshakeValid = false; RequestHostSync(); RestartHostSyncWatch(); } } public override void OnPlayerEnteredRoom(Player newPlayer) { if (PhotonNetwork.IsMasterClient) { ((MonoBehaviour)this).StartCoroutine(BroadcastAfterDelay(0.5f)); } } public void OnEvent(EventData photonEvent) { //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) if (photonEvent == null || photonEvent.Code != 159 || !(photonEvent.CustomData is object[] array) || array.Length < 3 || !(array[0] is string text) || text != "tony4twentys.Campfire_Building" || ToInt(array[1]) != 7) { return; } byte b = ToByte(array[2]); if (b == 2 && PhotonNetwork.IsMasterClient) { BroadcastNow(); BroadcastWoodSnapshot(); BroadcastStoneSnapshot(); FirewoodPing.BroadcastAllCounts(); return; } if (b == 5 && PhotonNetwork.IsMasterClient) { BroadcastWoodSnapshot(); BroadcastStoneSnapshot(); return; } switch (b) { case 3: if (array.Length >= 5) { CampfireWood.ApplyNetworkCount(ToInt(array[3]), ToInt(array[4])); } break; case 4: if (array.Length >= 5) { CampfireWood.ApplySnapshot(array[3] as int[], array[4] as int[]); } break; case 8: if (array.Length >= 5) { CampfireStones.ApplyNetworkCount(ToInt(array[3]), ToInt(array[4])); } break; case 9: if (array.Length >= 5) { CampfireStones.ApplySnapshot(array[3] as int[], array[4] as int[]); } break; case 6: if (PhotonNetwork.IsMasterClient && array.Length >= 8) { int segment = ToInt(array[3]); Vector3 pos2 = default(Vector3); ((Vector3)(ref pos2))..ctor(ToFloat(array[4]), ToFloat(array[5]), ToFloat(array[6])); bool cactus = Convert.ToBoolean(array[7]); bool flag = array.Length > 8 && Convert.ToBoolean(array[8]); FirewoodPing.TryHonorRequest(stick: (array.Length > 9) ? Convert.ToBoolean(array[9]) : (!flag), segment: segment, pos: pos2, cactus: cactus, stone: flag); } break; case 7: if (array.Length >= 5) { bool stone = array.Length > 5 && Convert.ToBoolean(array[5]); FirewoodPing.ApplyHostCount(ToInt(array[3]), ToInt(array[4]), stone); } break; case 10: if (PhotonNetwork.IsMasterClient && array.Length >= 8) { ushort itemId = (ushort)ToInt(array[3]); Vector3 pos = default(Vector3); ((Vector3)(ref pos))..ctor(ToFloat(array[4]), ToFloat(array[5]), ToFloat(array[6])); FirewoodStack.HonorWorldDrop(rot: Quaternion.Euler(0f, ToFloat(array[7]), 0f), itemId: itemId, pos: pos); } break; case 1: if (PhotonNetwork.IsMasterClient) { break; } try { _syncingFromNet = true; StopHostSyncWatch(); HostModConfirmed = true; Plugin.isHandshakeValid = true; Plugin.ApplyRemoteConfig(array); Plugin.DebugLog("[Campfire Building] Host config sync applied. Ascent " + Plugin.CurrentAscent + " — campfires need " + (Plugin.syncedEnableStones ? (Plugin.RequiredStoneCount + " stones then ") : "") + Plugin.RequiredFirewoodCount + " firewood."); break; } catch (Exception ex) { Plugin.Log.LogError((object)("[Campfire Building] Config sync failed: " + ex.Message)); break; } finally { _syncingFromNet = false; } } } internal static void OnLocalSettingChanged() { if (!((Object)(object)Instance != (Object)null) || !Instance._syncingFromNet) { if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient) { Plugin.ApplyLocalConfig(); } ScheduleBroadcast(); } } internal static void ScheduleBroadcast() { if (!((Object)(object)Instance == (Object)null) && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) { if (Instance._debounce != null) { ((MonoBehaviour)Instance).StopCoroutine(Instance._debounce); } Instance._debounce = ((MonoBehaviour)Instance).StartCoroutine(Instance.DebounceBroadcast()); } } internal static void BroadcastStones(int viewId, int count) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown if (!PhotonNetwork.InRoom || viewId <= 0) { return; } try { PhotonNetwork.RaiseEvent((byte)159, (object)new object[5] { "tony4twentys.Campfire_Building", 7, (byte)8, viewId, count }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] Stone RaiseEvent failed: " + ex.Message)); } } } internal static void BroadcastStoneSnapshot() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient) { return; } CampfireStones.CopySnapshot(out var viewIds, out var counts); if (viewIds.Length == 0) { return; } try { PhotonNetwork.RaiseEvent((byte)159, (object)new object[5] { "tony4twentys.Campfire_Building", 7, (byte)9, viewIds, counts }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] Stone snapshot RaiseEvent failed: " + ex.Message)); } } } internal static void BroadcastWood(int viewId, int count) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown if (!PhotonNetwork.InRoom || viewId <= 0) { return; } try { PhotonNetwork.RaiseEvent((byte)159, (object)new object[5] { "tony4twentys.Campfire_Building", 7, (byte)3, viewId, count }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] Firewood RaiseEvent failed: " + ex.Message)); } } } internal static void BroadcastWoodSnapshot() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient) { return; } CampfireWood.CopySnapshot(out var viewIds, out var counts); if (viewIds.Length == 0) { return; } try { PhotonNetwork.RaiseEvent((byte)159, (object)new object[5] { "tony4twentys.Campfire_Building", 7, (byte)4, viewIds, counts }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] Snapshot RaiseEvent failed: " + ex.Message)); } } } private void HandleJoinedRoom() { FirewoodSpawner.ResetRun(); FirewoodPing.Ensure(); if (PhotonNetwork.IsMasterClient) { HostModConfirmed = true; Plugin.isHandshakeValid = true; Plugin.ApplyLocalConfig(); Plugin.DebugLog("[Campfire Building] Ascent " + Plugin.CurrentAscent + " — campfires need " + (Plugin.syncedEnableStones ? (Plugin.RequiredStoneCount + " stones then ") : "") + Plugin.RequiredFirewoodCount + " firewood."); BroadcastNow(); StopHostSyncWatch(); FirewoodSpawner.ScheduleCurrentSegment(); } else { HostModConfirmed = false; Plugin.isHandshakeValid = false; RequestHostSync(); RestartHostSyncWatch(); } } private static void RequestHostSync() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { PhotonNetwork.RaiseEvent((byte)159, (object)new object[3] { "tony4twentys.Campfire_Building", 7, (byte)2 }, new RaiseEventOptions { Receivers = (ReceiverGroup)2 }, SendOptions.SendReliable); } } private void RestartHostSyncWatch() { StopHostSyncWatch(); if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { _hostSyncWatch = ((MonoBehaviour)this).StartCoroutine(WatchForHostSync()); } } private void StopHostSyncWatch() { if (_hostSyncWatch != null) { ((MonoBehaviour)this).StopCoroutine(_hostSyncWatch); _hostSyncWatch = null; } } private IEnumerator WatchForHostSync() { WaitForSecondsRealtime tick = new WaitForSecondsRealtime(2f); float elapsed = 0f; while (elapsed < 12f) { if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || HostModConfirmed) { yield break; } yield return tick; elapsed += 2f; if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || HostModConfirmed) { yield break; } RequestHostSync(); } if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient && !HostModConfirmed) { Plugin.isHandshakeValid = false; Plugin.Log.LogWarning((object)"[Campfire Building] Host does not appear to have Campfire Building — vanilla lighting left enabled."); } _hostSyncWatch = null; } private IEnumerator DebounceBroadcast() { yield return (object)new WaitForSeconds(0.25f); BroadcastNow(); _debounce = null; } private IEnumerator BroadcastAfterDelay(float seconds) { yield return (object)new WaitForSeconds(seconds); BroadcastNow(); BroadcastWoodSnapshot(); BroadcastStoneSnapshot(); FirewoodPing.BroadcastAllCounts(); } internal static void RequestStickSpawn(int segment, Vector3 pos, bool cactus, bool stone, bool stick) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient) { return; } try { PhotonNetwork.RaiseEvent((byte)159, (object)new object[10] { "tony4twentys.Campfire_Building", 7, (byte)6, segment, pos.x, pos.y, pos.z, cactus, stone, stick }, new RaiseEventOptions { Receivers = (ReceiverGroup)2 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] Ping spawn request failed: " + ex.Message)); } } } internal static void RequestDropOne(ushort itemId, Vector3 pos, Quaternion rot) { //IL_004c: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || (itemId != 28 && itemId != 72)) { return; } try { PhotonNetwork.RaiseEvent((byte)159, (object)new object[8] { "tony4twentys.Campfire_Building", 7, (byte)10, (int)itemId, pos.x, pos.y, pos.z, ((Quaternion)(ref rot)).eulerAngles.y }, new RaiseEventOptions { Receivers = (ReceiverGroup)2 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] Drop-one request failed: " + ex.Message)); } } } internal static void BroadcastSpawnCount(int segment, int spawned, bool stone) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient) { return; } try { PhotonNetwork.RaiseEvent((byte)159, (object)new object[6] { "tony4twentys.Campfire_Building", 7, (byte)7, segment, spawned, stone }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] Ping count broadcast failed: " + ex.Message)); } } } private static void BroadcastNow() { //IL_001a: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) { PhotonNetwork.RaiseEvent((byte)159, (object)Plugin.BuildConfigPayload(1), new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } } private static int ToInt(object value) { return Convert.ToInt32(value); } private static float ToFloat(object value) { return Convert.ToSingle(value); } private static byte ToByte(object value) { return Convert.ToByte(value); } } internal static class CampfireWood { private static readonly Dictionary<int, int> CountsByViewId = new Dictionary<int, int>(); private static bool _loggedVisualError; internal static void ResetAll() { CountsByViewId.Clear(); CampfireStones.ResetAll(); } internal static bool NeedsBuild(Campfire campfire) { if (!CampfireStones.NeedsStones(campfire)) { return NeedsWood(campfire); } return true; } internal static bool ShouldModify(Campfire campfire) { if ((Object)(object)campfire == (Object)null || !Plugin.IsGameplayEnabled) { return false; } if (campfire.forceLit) { return false; } if (IsPortableStove(campfire)) { return false; } return true; } internal static bool NeedsWood(Campfire campfire) { if (!ShouldModify(campfire) || campfire.Lit) { return false; } if (CampfireStones.NeedsStones(campfire)) { return false; } return GetCount(campfire) < Plugin.RequiredFirewoodCount; } internal static int GetCount(Campfire campfire) { int viewId = GetViewId(campfire); if (viewId > 0 && CountsByViewId.TryGetValue(viewId, out var value)) { return value; } return 0; } internal static void EnsureInitialized(Campfire campfire) { if ((Object)(object)campfire == (Object)null) { return; } CampfireStones.Ensure(campfire); if (!ShouldModify(campfire)) { return; } int viewId = GetViewId(campfire); int value = 0; if (viewId > 0 && CountsByViewId.TryGetValue(viewId, out value)) { ApplyLogVisuals(campfire, value); } else if (!campfire.Lit) { if (viewId > 0) { CountsByViewId[viewId] = 0; } ApplyLogVisuals(campfire, 0); } } internal static bool TryAddFirewood(Campfire campfire, Character interactor) { if ((Object)(object)campfire == (Object)null || (Object)(object)interactor == (Object)null || !interactor.IsLocal) { return false; } if (!NeedsWood(campfire)) { return false; } if (!IsFirewoodItem(((Object)(object)interactor.data != (Object)null) ? interactor.data.currentItem : null)) { return false; } int count = GetCount(campfire) + 1; SetCount(campfire, count, broadcast: true); FirewoodStack.ConsumeOne(interactor); return true; } internal static void SetCount(Campfire campfire, int count, bool broadcast) { if (!((Object)(object)campfire == (Object)null)) { int num = Mathf.Max(0, count); int viewId = GetViewId(campfire); if (viewId > 0) { CountsByViewId[viewId] = num; } ApplyLogVisuals(campfire, num); RefreshPrompt(campfire); if (broadcast && viewId > 0) { BuildFireNet.BroadcastWood(viewId, num); } } } internal static void ApplyNetworkCount(int viewId, int count) { if (viewId > 0) { CountsByViewId[viewId] = Mathf.Max(0, count); Campfire val = FindCampfire(viewId); if ((Object)(object)val != (Object)null) { ApplyLogVisuals(val, CountsByViewId[viewId]); RefreshPrompt(val); } } } internal static void ApplySnapshot(int[] viewIds, int[] counts) { if (viewIds != null && counts != null) { int num = Math.Min(viewIds.Length, counts.Length); for (int i = 0; i < num; i++) { ApplyNetworkCount(viewIds[i], counts[i]); } } } internal static void CopySnapshot(out int[] viewIds, out int[] counts) { viewIds = new int[CountsByViewId.Count]; counts = new int[CountsByViewId.Count]; int num = 0; foreach (KeyValuePair<int, int> item in CountsByViewId) { viewIds[num] = item.Key; counts[num] = item.Value; num++; } } internal static string GetPrompt(Campfire campfire) { if (!ShouldModify(campfire) || campfire.Lit) { return null; } int count = GetCount(campfire); int requiredFirewoodCount = Plugin.RequiredFirewoodCount; if (count >= requiredFirewoodCount) { return null; } return Plugin.FormatPrompt(IsFirewoodItem(((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data != (Object)null) ? Character.localCharacter.data.currentItem : null), count, requiredFirewoodCount); } internal static bool IsFirewoodItem(Item item) { if ((Object)(object)item == (Object)null) { return false; } if (Plugin.IsFirewoodItemId(item.itemID)) { return true; } try { return (Object)(object)((Component)item).GetComponent<FireWoodItem>() != (Object)null; } catch { return false; } } internal static bool IsPortableStove(Campfire fire) { if ((Object)(object)fire == (Object)null) { return false; } if (LooksLikePortableStove(fire.nameOverride)) { return true; } Transform val = ((Component)fire).transform; int num = 0; while ((Object)(object)val != (Object)null && num < 8) { if (LooksLikePortableStove(((Object)val).name)) { return true; } val = val.parent; num++; } try { string name = fire.GetName(); if (!string.IsNullOrEmpty(name) && name.Replace(" ", string.Empty).IndexOf("PORTABLESTOVE", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } catch { } return false; } internal static int GetViewId(Campfire campfire) { if ((Object)(object)campfire == (Object)null) { return 0; } PhotonView val = campfire.view; if ((Object)(object)val == (Object)null) { val = ((Component)campfire).GetComponent<PhotonView>(); } if (!((Object)(object)val != (Object)null)) { return 0; } return val.ViewID; } internal static void ApplyLogVisuals(Campfire campfire, int count) { if ((Object)(object)campfire == (Object)null) { return; } try { Transform val = campfire.logRoot; if ((Object)(object)val == (Object)null) { val = FindLogsRecursive(((Component)campfire).transform, 0); } if ((Object)(object)val == (Object)null) { return; } int childCount = val.childCount; for (int i = 0; i < childCount; i++) { Transform child = val.GetChild(i); if ((Object)(object)child != (Object)null) { ((Component)child).gameObject.SetActive(false); } } if (count <= 0) { return; } if (childCount >= 6 && Plugin.RequiredFirewoodCount >= 6) { int num = Mathf.Min(count, childCount); for (int j = 0; j < num; j++) { SetChildActive(val, j, active: true); } } else if (childCount >= 6) { if (count >= 1) { SetChildActive(val, 0, active: true); SetChildActive(val, 5, active: true); } if (count >= 2) { SetChildActive(val, 2, active: true); SetChildActive(val, 3, active: true); } if (count >= 3) { SetChildActive(val, 1, active: true); SetChildActive(val, 4, active: true); } } else { int num2 = Mathf.Min(count * 2, childCount); for (int k = 0; k < num2; k++) { SetChildActive(val, k, active: true); } } } catch (Exception ex) { Plugin.LogOnce(ref _loggedVisualError, "[Campfire Building] Log visuals failed.", ex); } } private static Campfire FindCampfire(int viewId) { PhotonView val = PhotonView.Find(viewId); if ((Object)(object)val != (Object)null) { Campfire component = ((Component)val).GetComponent<Campfire>(); if ((Object)(object)component != (Object)null) { return component; } } List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES; if (aLL_CAMPFIRES == null) { return null; } for (int i = 0; i < aLL_CAMPFIRES.Count; i++) { Campfire val2 = aLL_CAMPFIRES[i]; if ((Object)(object)val2 != (Object)null && GetViewId(val2) == viewId) { return val2; } } return null; } private static void RefreshPrompt(Campfire campfire) { try { if ((Object)(object)GUIManager.instance != (Object)null && (object)GUIManager.instance.currentInteractable == campfire) { GUIManager.instance.RefreshInteractablePrompt(); } } catch { } } private static bool LooksLikePortableStove(string token) { if (string.IsNullOrEmpty(token)) { return false; } string text = token.Replace(" ", string.Empty); if (text.IndexOf("PORTABLESTOVE", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("PortableStove", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static Transform FindLogsRecursive(Transform parent, int depth) { if ((Object)(object)parent == (Object)null || depth > 3) { return null; } for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name.IndexOf("Logs", StringComparison.OrdinalIgnoreCase) >= 0) { return child; } Transform val = FindLogsRecursive(child, depth + 1); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void SetChildActive(Transform logRoot, int index, bool active) { if (index >= 0 && index < logRoot.childCount) { Transform child = logRoot.GetChild(index); if ((Object)(object)child != (Object)null) { ((Component)child).gameObject.SetActive(active); } } } } internal static class CampfireStones { private const string HologramName = "CB_StoneHologram"; private static readonly Dictionary<int, int> CountsByViewId = new Dictionary<int, int>(); private static bool _loggedHolo; internal static void ResetAll() { CountsByViewId.Clear(); List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES; if (aLL_CAMPFIRES != null) { for (int i = 0; i < aLL_CAMPFIRES.Count; i++) { RestoreVisuals(aLL_CAMPFIRES[i]); } } } internal static void RefreshAll() { List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES; if (aLL_CAMPFIRES != null) { for (int i = 0; i < aLL_CAMPFIRES.Count; i++) { Ensure(aLL_CAMPFIRES[i]); } } } internal static bool NeedsStones(Campfire campfire) { if (!ShouldUse(campfire) || campfire.Lit) { return false; } return GetCount(campfire) < Plugin.RequiredStoneCount; } internal static bool ShouldUse(Campfire campfire) { if ((Object)(object)campfire == (Object)null || !Plugin.StonesEnabled) { return false; } if (campfire.forceLit || CampfireWood.IsPortableStove(campfire)) { return false; } if (FirewoodSpawner.IsPlaneWreckCampfire(((Component)campfire).transform)) { return false; } return true; } internal static int GetCount(Campfire campfire) { int viewId = CampfireWood.GetViewId(campfire); if (viewId > 0 && CountsByViewId.TryGetValue(viewId, out var value)) { return value; } return 0; } internal static void Ensure(Campfire campfire) { if ((Object)(object)campfire == (Object)null) { return; } if (!ShouldUse(campfire) || campfire.Lit) { RestoreVisuals(campfire); return; } int viewId = CampfireWood.GetViewId(campfire); if (viewId > 0 && !CountsByViewId.ContainsKey(viewId)) { CountsByViewId[viewId] = 0; } DisableSmokeOff(((Component)campfire).transform); if (NeedsStones(campfire)) { ShowHologram(campfire); } else { RestoreVisuals(campfire); } } internal static bool TryPlace(Campfire campfire, Character interactor) { if ((Object)(object)campfire == (Object)null || (Object)(object)interactor == (Object)null || !interactor.IsLocal) { return false; } if (!NeedsStones(campfire)) { return false; } if (!IsStoneItem(((Object)(object)interactor.data != (Object)null) ? interactor.data.currentItem : null)) { return false; } if (!FirewoodStack.ConsumeOne(interactor, 72)) { return false; } SetCount(campfire, GetCount(campfire) + 1, broadcast: true); return true; } internal static void SetCount(Campfire campfire, int count, bool broadcast) { if (!((Object)(object)campfire == (Object)null)) { int num = Mathf.Max(0, count); int viewId = CampfireWood.GetViewId(campfire); if (viewId > 0) { CountsByViewId[viewId] = num; } Ensure(campfire); RefreshPrompt(campfire); if (broadcast && viewId > 0) { BuildFireNet.BroadcastStones(viewId, num); } } } internal static void ApplyNetworkCount(int viewId, int count) { if (viewId > 0) { CountsByViewId[viewId] = Mathf.Max(0, count); Campfire val = FindCampfire(viewId); if ((Object)(object)val != (Object)null) { Ensure(val); RefreshPrompt(val); } } } internal static void ApplySnapshot(int[] viewIds, int[] counts) { if (viewIds != null && counts != null) { int num = Math.Min(viewIds.Length, counts.Length); for (int i = 0; i < num; i++) { ApplyNetworkCount(viewIds[i], counts[i]); } } } internal static void CopySnapshot(out int[] viewIds, out int[] counts) { viewIds = new int[CountsByViewId.Count]; counts = new int[CountsByViewId.Count]; int num = 0; foreach (KeyValuePair<int, int> item in CountsByViewId) { viewIds[num] = item.Key; counts[num] = item.Value; num++; } } internal static string GetPrompt(Campfire campfire) { if (!NeedsStones(campfire)) { return null; } int count = GetCount(campfire); int requiredStoneCount = Plugin.RequiredStoneCount; return Plugin.FormatStonePrompt(IsStoneItem(((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data != (Object)null) ? Character.localCharacter.data.currentItem : null), count, requiredStoneCount); } internal static bool IsStoneItem(Item item) { if ((Object)(object)item != (Object)null) { return Plugin.IsStoneItemId(item.itemID); } return false; } private static void ShowHologram(Campfire campfire) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)campfire).transform; DisableSmokeOff(transform); TintAsHologram(campfire); if ((Object)(object)FindHologram(transform) == (Object)null) { new GameObject("CB_StoneHologram").transform.SetParent(transform, false); } } private static void RestoreVisuals(Campfire campfire) { if (!((Object)(object)campfire == (Object)null)) { Transform val = FindHologram(((Component)campfire).transform); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } CampfireHoloState component = ((Component)campfire).GetComponent<CampfireHoloState>(); if ((Object)(object)component != (Object)null) { component.Restore(); Object.Destroy((Object)(object)component); } if (ShouldUse(campfire)) { DisableSmokeOff(((Component)campfire).transform); } CampfireWood.ApplyLogVisuals(campfire, CampfireWood.GetCount(campfire)); } } private static void TintAsHologram(Campfire campfire) { CampfireHoloState campfireHoloState = ((Component)campfire).GetComponent<CampfireHoloState>(); if ((Object)(object)campfireHoloState != (Object)null && campfireHoloState.Applied) { return; } List<Renderer> list = new List<Renderer>(16); CollectRenderers(((Component)campfire).transform, list, 0); if (list.Count == 0) { Plugin.LogOnce(ref _loggedHolo, "[Campfire Building] Stone hologram found no campfire meshes.", null); return; } if ((Object)(object)campfireHoloState == (Object)null) { campfireHoloState = ((Component)campfire).gameObject.AddComponent<CampfireHoloState>(); } if (!campfireHoloState.Apply(list)) { Plugin.LogOnce(ref _loggedHolo, "[Campfire Building] Stone hologram material missing.", null); } } private static void CollectRenderers(Transform t, List<Renderer> list, int depth) { if ((Object)(object)t == (Object)null || depth > 6 || ((Object)t).name == "CB_StoneHologram" || IsVfxName(((Object)t).name) || ((Object)t).name.IndexOf("Logs", StringComparison.OrdinalIgnoreCase) >= 0) { return; } Renderer[] components = ((Component)t).GetComponents<Renderer>(); foreach (Renderer val in components) { if ((Object)(object)val != (Object)null) { list.Add(val); } } int childCount = t.childCount; for (int j = 0; j < childCount; j++) { CollectRenderers(t.GetChild(j), list, depth + 1); } } private static void DisableSmokeOff(Transform root) { if (!((Object)(object)root == (Object)null)) { Transform val = FindNamed(root, "VFX_Smoke_Off", 6); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } } } private static Transform FindHologram(Transform root) { if ((Object)(object)root == (Object)null) { return null; } return root.Find("CB_StoneHologram"); } private static Transform FindNamed(Transform root, string token, int depth) { if ((Object)(object)root == (Object)null || depth < 0) { return null; } if (((Object)root).name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0) { return root; } int childCount = root.childCount; for (int i = 0; i < childCount; i++) { Transform val = FindNamed(root.GetChild(i), token, depth - 1); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static bool IsVfxName(string name) { if (string.IsNullOrEmpty(name)) { return false; } if (name.IndexOf("VFX", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Smoke", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Particle", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static Campfire FindCampfire(int viewId) { PhotonView val = PhotonView.Find(viewId); if ((Object)(object)val != (Object)null) { Campfire component = ((Component)val).GetComponent<Campfire>(); if ((Object)(object)component != (Object)null) { return component; } } List<Campfire> aLL_CAMPFIRES = Campfire.ALL_CAMPFIRES; if (aLL_CAMPFIRES == null) { return null; } for (int i = 0; i < aLL_CAMPFIRES.Count; i++) { Campfire val2 = aLL_CAMPFIRES[i]; if ((Object)(object)val2 != (Object)null && CampfireWood.GetViewId(val2) == viewId) { return val2; } } return null; } private static void RefreshPrompt(Campfire campfire) { try { if ((Object)(object)GUIManager.instance != (Object)null && (object)GUIManager.instance.currentInteractable == campfire) { GUIManager.instance.RefreshInteractablePrompt(); } } catch { } } } internal sealed class CampfireHoloState : MonoBehaviour { private Renderer[] _renderers; private Material[][] _originals; private readonly List<Material> _ghosts = new List<Material>(8); internal bool Applied => _renderers != null; internal bool Apply(List<Renderer> renderers) { if (Applied || renderers == null || renderers.Count == 0) { return Applied; } _renderers = (Renderer[])(object)new Renderer[renderers.Count]; _originals = new Material[renderers.Count][]; bool flag = false; for (int i = 0; i < renderers.Count; i++) { Renderer val = renderers[i]; _renderers[i] = val; if ((Object)(object)val == (Object)null) { continue; } Material[] sharedMaterials = val.sharedMaterials; _originals[i] = CopyMaterials(sharedMaterials); Material[] array = (Material[])(object)new Material[(sharedMaterials == null || sharedMaterials.Length == 0) ? 1 : sharedMaterials.Length]; for (int j = 0; j < array.Length; j++) { Material source = ((sharedMaterials != null && j < sharedMaterials.Length) ? sharedMaterials[j] : null); array[j] = MakeGhost(source); if ((Object)(object)array[j] != (Object)null) { _ghosts.Add(array[j]); flag = true; } } val.sharedMaterials = array; val.enabled = true; } if (!flag) { Restore(); return false; } return true; } internal void Restore() { if (_renderers != null && _originals != null) { int num = Math.Min(_renderers.Length, _originals.Length); for (int i = 0; i < num; i++) { Renderer val = _renderers[i]; if ((Object)(object)val != (Object)null && _originals[i] != null) { val.sharedMaterials = _originals[i]; } } } for (int j = 0; j < _ghosts.Count; j++) { if ((Object)(object)_ghosts[j] != (Object)null) { Object.Destroy((Object)(object)_ghosts[j]); } } _ghosts.Clear(); _renderers = null; _originals = null; } private void OnDestroy() { Restore(); } private static Material[] CopyMaterials(Material[] src) { if (src == null || src.Length == 0) { return src; } Material[] array = (Material[])(object)new Material[src.Length]; Array.Copy(src, array, src.Length); return array; } private static Material MakeGhost(Material source) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Universal Render Pipeline/Unlit"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Unlit/Transparent"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Standard"); } if ((Object)(object)val == (Object)null && (Object)(object)source != (Object)null) { val = source.shader; } if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val); if ((Object)(object)source != (Object)null) { if (source.HasProperty("_BaseMap") && val2.HasProperty("_BaseMap")) { val2.SetTexture("_BaseMap", source.GetTexture("_BaseMap")); } if (source.HasProperty("_MainTex") && val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", source.GetTexture("_MainTex")); } } Color tint = default(Color); ((Color)(ref tint))..ctor(0.35f, 0.9f, 1f, 0.4f); MakeTransparent(val2, tint); return val2; } private static void MakeTransparent(Material mat, Color tint) { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty("_Surface")) { mat.SetFloat("_Surface", 1f); } if (mat.HasProperty("_Blend")) { mat.SetFloat("_Blend", 0f); } if (mat.HasProperty("_Mode")) { mat.SetFloat("_Mode", 3f); } if (mat.HasProperty("_SrcBlend")) { mat.SetFloat("_SrcBlend", 5f); } if (mat.HasProperty("_DstBlend")) { mat.SetFloat("_DstBlend", 10f); } if (mat.HasProperty("_ZWrite")) { mat.SetFloat("_ZWrite", 0f); } mat.DisableKeyword("_ALPHATEST_ON"); mat.DisableKeyword("_ALPHAPREMULTIPLY_ON"); mat.EnableKeyword("_ALPHABLEND_ON"); mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); mat.SetOverrideTag("RenderType", "Transparent"); mat.renderQueue = 3000; if (mat.HasProperty("_BaseColor")) { Color color = mat.GetColor("_BaseColor"); color.a = tint.a; mat.SetColor("_BaseColor", Color.Lerp(color, tint, 0.55f)); } if (mat.HasProperty("_Color")) { Color color2 = mat.GetColor("_Color"); color2.a = tint.a; mat.SetColor("_Color", Color.Lerp(color2, tint, 0.55f)); } mat.color = tint; if (mat.HasProperty("_EmissionColor")) { mat.EnableKeyword("_EMISSION"); mat.SetColor("_EmissionColor", new Color(0.08f, 0.35f, 0.5f, 1f)); } } } internal static class FirewoodSpawner { private struct ClimbSurface { public Vector3 origin; public Vector3 topCenter; public Vector3 xzExtents; public float topY; } internal struct BiomeVeg { public string[] folders; public string[] tokens; public bool berry; public bool tumble; public bool cactus; public bool climbSurfaces; } private const float MaxDropBelowOrigin = 14f; private const float MaxDropThroughCanopy = 72f; private const int NoSegment = int.MinValue; private static readonly List<Vector3> PlacedPoints = new List<Vector3>(80); private static readonly List<Vector3> PlacedStonePoints = new List<Vector3>(80); private static readonly RaycastHit[] RayHits = (RaycastHit[])(object)new RaycastHit[96]; private static readonly List<Renderer> ClimbRenderers = new List<Renderer>(24); private static readonly BiomeVeg VegCaldera = new BiomeVeg { climbSurfaces = true }; private static readonly BiomeVeg VegKiln = new BiomeVeg { folders = new string[4] { "Edges", "Start", "Bridges", "Foundation" }, tokens = new string[4] { "RockFinal", "Rock_Round", "Cliff", "LavaBridge" }, climbSurfaces = true }; private static readonly BiomeVeg VegCitadel = new BiomeVeg { folders = new string[6] { "Spawners", "Floor Small", "Small Architecture", "Loose Bricks", "Floors", "Bridges" }, tokens = new string[6] { "Temple Floor Chunk", "Loose Brick", "Floor Bridge", "Bridge Structure", "Floor partial Bridge", "Bridge Stairs" }, climbSurfaces = true }; private static readonly BiomeVeg VegShore = new BiomeVeg { folders = new string[4] { "PlateauProps", "Palms", "Oasis Palms", "Bushes" }, tokens = new string[1] { "Jungle_PalmTree" }, berry = true }; private static readonly BiomeVeg VegTropics = new BiomeVeg { folders = new string[6] { "Thorny", "Pops_Plat", "Props_Wall", "Palms", "Trees", "Bushes" }, tokens = new string[2] { "Jungle_PalmTree", "Jungle_Willow" }, berry = true }; private static readonly BiomeVeg VegRoots = new BiomeVeg { folders = new string[4] { "PlateauProps", "WallProps", "redwoods", "base Stumps" }, tokens = new string[1] { "Redwood" } }; private static readonly BiomeVeg VegAlpine = new BiomeVeg { folders = new string[5] { "PlateauProps", "WallProps", "Pine", "Trees", "Shrub" }, tokens = new string[3] { "Ice_Pine", "Ice_DeadTree", "Ice_DeadShrub" } }; private static readonly BiomeVeg VegMesa = new BiomeVeg { folders = new string[3] { "Oasis", "Spawns", "Tumblers" }, tokens = new string[2] { "Jungle_PalmTree", "TumbleWeed" }, berry = true, tumble = true, cactus = true }; private static readonly BiomeVeg VegGloom = new BiomeVeg { folders = new string[3] { "Rocks", "Big Rocks", "Small Rocks" }, tokens = new string[3] { "RockFinal_Desert", "Rock_Lil", "RockFinalSmall" }, climbSurfaces = true }; private static int _terrainMask = int.MinValue; private static int _groundMask = int.MinValue; private static Transform _gloomWater; private static float _gloomWaterY = float.MinValue; private static int _gloomWaterSearchFrame = -999; internal static void ResetRun() { PlacedPoints.Clear(); PlacedStonePoints.Clear(); _gloomWater = null; _gloomWaterY = float.MinValue; _gloomWaterSearchFrame = -999; FirewoodPing.Reset(); } internal static void ScheduleCurrentSegment() { FirewoodPing.Ensure(); } internal static void OnBiomeStinger() { FirewoodPing.Ensure(); if (InGameplayLevel()) { int num = CurrentSegmentIndex(); if (num >= 0) { Plugin.DebugLog("[Campfire Building] Stinger — ping biome segment " + num + " (" + DescribeSegment(num) + ")."); } } } internal static int GetCurrentSegment() { return CurrentSegmentIndex(); } internal static bool SkipKiln(int segment) { return ShouldSkipKilnCitadel(segment); } internal static bool GameplayReady() { if (InGameplayLevel()) { return !IsLoading(); } return false; } internal static string SegmentLabel(int segment) { return DescribeSegment(segment); } internal static BiomeVeg GetVeg(int segment) { return GetBiomeVeg(segment); } internal static bool IsLodOrMesh(string name) { return IsMeshOrLodName(name); } internal static bool PingTooClose(Vector3 pos, float spacing, bool stone) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) return TooClose(stone ? PlacedStonePoints : PlacedPoints, pos, spacing); } internal static void PingRemember(Vector3 pos, bool stone) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (stone) { PlacedStonePoints.Add(pos); } else { PlacedPoints.Add(pos); } } internal static bool IsPingPlant(Transform t, BiomeVeg veg, out bool cactus, out bool climb, out string key) { cactus = false; climb = false; key = null; if ((Object)(object)t == (Object)null || string.IsNullOrEmpty(((Object)t).name)) { return false; } string name = ((Object)t).name; if (NameContains(name, "FireWood") || NameContains(name, "Campfire") || NameContains(name, "crashed plane") || NameContains(name, "WaterHazard")) { return false; } cactus = veg.cactus && IsMesaCactusName(name); if (cactus) { key = NormalizePrefabName(name); return true; } if (veg.berry && (Object)(object)((Component)t).GetComponent<BerryBush>() != (Object)null) { key = "BerryBush"; return true; } if (veg.tumble && (Object)(object)((Component)t).GetComponent<TumbleWeed>() != (Object)null) { key = "TumbleWeed"; return true; } climb = veg.climbSurfaces && (IsWalkableSurfaceName(name) || IsNestName(name) || (veg.tokens != null && MatchesToken(name, veg.tokens))); if (climb) { if (IsCalderaMiddleGround(t)) { return false; } key = NormalizePrefabName(name); return true; } if (MatchesToken(name, veg.tokens) && !IsBiomeFolder(name, veg.folders)) { key = NormalizePrefabName(name); return true; } if (veg.berry && NameContains(name, "berrybush")) { key = "BerryBush"; return true; } return false; } internal static bool TrySnapPing(Transform root, bool cactus, bool climb, out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_005f: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; if ((Object)(object)root == (Object)null) { return false; } if (cactus) { if (!TrySnapBesideCactus(root.position, out pos)) { return false; } } else if (climb) { if (!TrySnapClimbTop(PreferClimbSnapRoot(root), out pos)) { return false; } } else if (!TrySnapBesidePlant(root.position, out pos)) { return false; } if (IsBelowGloomWater(pos)) { pos = Vector3.zero; return false; } return true; } internal static bool SpawnStickNow(Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return SpawnLootNow("FireWood", position); } internal static bool SpawnStoneNow(Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return SpawnLootNow("Stone", position); } internal static bool IsPlaneWreckCampfire(Transform t) { if (!HasNamedAncestor(t, "crashed plane")) { return NameContains(((Object)t).name, "crashed plane"); } return true; } internal static bool IsCalderaMiddleGround(Transform t) { bool flag = false; int num = 0; Transform val = t; while ((Object)(object)val != (Object)null && num < 14) { string name = ((Object)val).name; if (!string.IsNullOrEmpty(name)) { if (name.Equals("Middle", StringComparison.OrdinalIgnoreCase)) { flag = true; } if (flag && NameContains(name, "Caldera_Segment")) { return true; } } val = val.parent; num++; } return false; } private static bool IsGloomWaterCollider(Collider col) { if ((Object)(object)col == (Object)null) { return false; } if (!HasNamedAncestor(((Component)col).transform, "WaterHazard")) { return NameContains(((Object)col).name, "WaterHazard"); } return true; } private static bool IsBelowGloomWater(Vector3 pos) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) EnsureGloomWater(); if ((Object)(object)_gloomWater == (Object)null) { return false; } Collider componentInChildren = ((Component)_gloomWater).GetComponentInChildren<Collider>(); if ((Object)(object)componentInChildren != (Object)null) { Bounds bounds = componentInChildren.bounds; if (((Bounds)(ref bounds)).size.y > 4f) { return pos.y <= ((Bounds)(ref bounds)).min.y + 0.5f; } return pos.y <= ((Bounds)(ref bounds)).max.y + 0.75f; } if (_gloomWaterY <= -1000f) { return false; } return pos.y <= _gloomWater.position.y + 0.75f; } private static void EnsureGloomWater() { if ((Object)(object)_gloomWater != (Object)null) { _gloomWaterY = WaterSurfaceY(_gloomWater); } else if (Time.frameCount - _gloomWaterSearchFrame >= 90) { _gloomWaterSearchFrame = Time.frameCount; GameObject val = GameObject.Find("WaterHazard_Swamp"); if (!((Object)(object)val == (Object)null)) { _gloomWater = val.transform; _gloomWaterY = WaterSurfaceY(_gloomWater); } } } private static float WaterSurfaceY(Transform water) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)water == (Object)null) { return float.MinValue; } Collider componentInChildren = ((Component)water).GetComponentInChildren<Collider>(); Bounds bounds; if ((Object)(object)componentInChildren != (Object)null) { bounds = componentInChildren.bounds; return ((Bounds)(ref bounds)).max.y; } Renderer componentInChildren2 = ((Component)water).GetComponentInChildren<Renderer>(); if ((Object)(object)componentInChildren2 != (Object)null) { bounds = componentInChildren2.bounds; return ((Bounds)(ref bounds)).max.y; } return water.position.y; } private static bool SpawnLootNow(string prefabName, Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Quaternion identity = Quaternion.identity; GameObject val = TryInstantiateItemRoom(prefabName, position, identity); if ((Object)(object)val == (Object)null) { val = TryInstantiateRoomObject("0_Items/" + prefabName, position, identity); } return (Object)(object)val != (Object)null; } private static BiomeVeg GetBiomeVeg(int segment) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unknown and I4 //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Invalid comparison between Unknown and I4 //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Invalid comparison between Unknown and I4 //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Invalid comparison between Unknown and I4 string segmentParentName = GetSegmentParentName(segment); if (NameContains(segmentParentName, "Temple_Segment") || NameContains(segmentParentName, "Gloom Temple") || NameContains(segmentParentName, "Citadel") || NameContains(segmentParentName, "Peak_Segment")) { return VegCitadel; } if (NameContains(segmentParentName, "Volcano_Segment") || NameContains(segmentParentName, "Peak_Kiln")) { return VegKiln; } BiomeType val = ResolveBiome(segment); if ((int)val == 3) { return VegCaldera; } if ((int)val == 0) { return VegShore; } if ((int)val == 1) { return VegTropics; } if ((int)val == 7) { return VegRoots; } if ((int)val == 2) { return VegAlpine; } if ((int)val == 6) { return VegMesa; } if ((int)val == 8) { return VegGloom; } if ((int)val == 9) { return VegCitadel; } return default(BiomeVeg); } private static string GetSegmentParentName(int segment) { try { MapHandler instance = Singleton<MapHandler>.Instance; if ((Object)(object)instance != (Object)null && instance.segments != null && segment >= 0 && segment < instance.segments.Length && instance.segments[segment] != null && (Object)(object)instance.segments[segment].segmentParent != (Object)null) { return ((Object)instance.segments[segment].segmentParent).name; } } catch { } return ""; } private static BiomeType ResolveBiome(int segment) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) BiomeType result = (BiomeType)0; string name = ""; try { MapHandler instance = Singleton<MapHandler>.Instance; if ((Object)(object)instance != (Object)null && instance.segments != null && segment >= 0 && segment < instance.segments.Length && instance.segments[segment] != null) { MapSegment val = instance.segments[segment]; result = val._biome; if ((Object)(object)val.segmentParent != (Object)null) { name = ((Object)val.segmentParent).name; } } } catch { } if (NameContains(name, "Beach") || NameContains(name, "Beach_Segment")) { return (BiomeType)0; } if (NameContains(name, "Jungle") || NameContains(name, "Tropics")) { return (BiomeType)1; } if (NameContains(name, "Roots")) { return (BiomeType)7; } if (NameContains(name, "Snow") || NameContains(name, "Alpine")) { return (BiomeType)2; } if (NameContains(name, "Desert") || NameContains(name, "Mesa")) { return (BiomeType)6; } if (NameContains(name, "Caldera") || NameContains(name, "Volcano_Segment")) { return (BiomeType)3; } if (NameContains(name, "Swamp") || (NameContains(name, "Gloom") && !NameContains(name, "Gloom Temple"))) { return (BiomeType)8; } return result; } private static bool MatchesToken(string name, string[] tokens) { if (tokens == null) { return false; } for (int i = 0; i < tokens.Length; i++) { if (NameContains(name, tokens[i])) { return true; } } return false; } private static bool IsBiomeFolder(string name, string[] folders) { if (folders == null) { return false; } string text = StripInstanceSuffix(name); for (int i = 0; i < folders.Length; i++) { if (text.Equals(folders[i], StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static bool TrySnapBesidePlant(Vector3 origin, out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) pos = origin; for (int i = 0; i < 6; i++) { float num = Random.Range(0f, (float)Math.PI * 2f); float num2 = Random.Range(3.5f, 9f); if (TrySnapToGround(origin + new Vector3(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2), origin.y, 72f, out pos)) { return true; } } return TrySnapToGround(origin, origin.y, 72f, out pos); } private static bool TrySnapBesideCactus(Vector3 origin, out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) pos = origin; for (int i = 0; i < 2; i++) { float num = Random.Range(0f, (float)Math.PI * 2f); float num2 = Random.Range(6.5f, 11f); if (TrySnapToGround(origin + new Vector3(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2), origin.y, out var pos2)) { float num3 = pos2.x - origin.x; float num4 = pos2.z - origin.z; if (!(num3 * num3 + num4 * num4 < 30.25f)) { pos = pos2; return true; } } } return TrySnapToGround(JitterXz(origin, 8f), origin.y, out pos); } private static Vector3 JitterXz(Vector3 origin, float spread) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) return origin + new Vector3(Random.Range(0f - spread, spread), 0f, Random.Range(0f - spread, spread)); } private static bool TooClose(List<Vector3> points, Vector3 pos, float minSpacing) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (points == null || minSpacing <= 0f) { return false; } float num = minSpacing * minSpacing; for (int i = 0; i < points.Count; i++) { Vector3 val = points[i] - pos; if (((Vector3)(ref val)).sqrMagnitude < num) { return true; } } return false; } private static Transform PreferClimbSnapRoot(Transform t) { if ((Object)(object)t == (Object)null) { return null; } if (NameContains(((Object)t).name, "Plartform") || NameContains(((Object)t).name, "Cliff") || NameContains(((Object)t).name, "Bridge Structure") || NameContains(((Object)t).name, "Bridge Stairs") || NameContains(((Object)t).name, "Floor partial Bridge") || ((Object)t).name.Equals("Floor", StringComparison.OrdinalIgnoreCase)) { return t; } Transform val = FindNamedDescendant(t, "Plartform", 3); if ((Object)(object)val != (Object)null) { return val; } Transform val2 = FindNamedDescendant(t, "Cliff", 2); if ((Object)(object)val2 != (Object)null) { return val2; } Transform val3 = FindNamedDescendant(t, "Bridge Structure", 3); if ((Object)(object)val3 != (Object)null) { return val3; } Transform val4 = FindNamedDescendant(t, "Bridge Stairs", 3); if ((Object)(object)val4 != (Object)null) { return val4; } Transform val5 = FindNamedDescendant(t, "Floor", 2); if ((Object)(object)val5 != (Object)null && !NameContains(((Object)val5).name, "Floor Small") && !NameContains(((Object)val5).name, "Floors")) { return val5; } return t; } private static Transform FindNamedDescendant(Transform t, string token, int depth) { if ((Object)(object)t == (Object)null || depth < 0) { return null; } int childCount = t.childCount; for (int i = 0; i < childCount; i++) { Transform child = t.GetChild(i); if (!((Object)(object)child == (Object)null)) { if (NameContains(((Object)child).name, token)) { return child; } Transform val = FindNamedDescendant(child, token, depth - 1); if ((Object)(object)val != (Object)null) { return val; } } } return null; } private static bool TrySnapClimbTop(Transform t, out Vector3 pos) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) pos = t.position; if (!TryGetClimbBounds(t, out var bounds)) { return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y, ((Bounds)(ref bounds)).center.z); return TrySnapOnTop(new ClimbSurface { origin = val, topCenter = val, xzExtents = new Vector3(((Bounds)(ref bounds)).extents.x, 0f, ((Bounds)(ref bounds)).extents.z), topY = ((Bounds)(ref bounds)).max.y }, NameContains(((Object)t).name, "Ring"), out pos); } private static bool TryGetClimbBounds(Transform t, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); if ((Object)(object)t == (Object)null) { return false; } ClimbRenderers.Clear(); ((Component)t).GetComponentsInChildren<Renderer>(false, ClimbRenderers); bool flag = false; for (int i = 0; i < ClimbRenderers.Count; i++) { Renderer val = ClimbRenderers[i]; if ((Object)(object)val == (Object)null || !val.enabled) { continue; } string name = ((Object)val).name; if (!NameContains(name, "lava") && !NameContains(name, "Water") && !NameContains(name, "WaterHazard")) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } ClimbRenderers.Clear(); if (flag) { if (!(((Bounds)(ref bounds)).size.x > 0.4f)) { return ((Bounds)(ref bounds)).size.z > 0.4f; } return true; } return false; } private static bool TrySnapOnTop(ClimbSurface spot, bool ring, out Vector3 pos) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) pos = spot.topCenter; float num = Mathf.Max(0.55f, spot.xzExtents.x * 0.62f); float num2 = Mathf.Max(0.55f, spot.xzExtents.z * 0.62f); int num3 = GroundMask(); RaycastHit hit = default(RaycastHit); for (int i = 0; i < 5; i++) { float num4; float num5; if (ring) { switch (i) { case 0: num4 = num; num5 = 0f; break; case 1: num4 = 0f - num; num5 = 0f; break; case 2: num4 = 0f; num5 = num2; break; case 3: num4 = 0f; num5 = 0f - num2; break; default: num4 = num * 0.7f; num5 = num2 * 0.7f; break; } } else { float num6 = Mathf.Max(0.45f, spot.xzExtents.x * 0.28f); float num7 = Mathf.Max(0.45f, spot.xzExtents.z * 0.28f); switch (i) { case 0: num4 = 0f; num5 = 0f; break; case 1: num4 = num6; num5 = 0f; break; case 2: num4 = 0f - num6; num5 = 0f; break; case 3: num4 = 0f; num5 = num7; break; default: num4 = 0f; num5 = 0f - num7; break; } } if (Physics.Raycast(new Vector3(spot.topCenter.x + num4, spot.topY + 10f, spot.topCenter.z + num5), Vector3.down, ref hit, 24f, num3, (QueryTriggerInteraction)1) && IsStandableHit(hit, spot.topY + 1f, 3.5f) && !IsBelowGloomWater(((RaycastHit)(ref hit)).point) && !(((RaycastHit)(ref hit)).point.y < spot.topY - 2.2f) && !(Vector3.Angle(Vector3.up, ((RaycastHit)(ref hit)).normal) > 48f)) { pos = ((RaycastHit)(ref hit)).point + Vector3.up * 0.18f; return true; } } return false; } private static string NormalizePrefabName(string name) { string text = StripInstanceSuffix(name); if (text.Length != 0) { return string.Intern(text); } return "Plant"; } private static string StripInstanceSuffix(string name) { if (string.IsNullOrEmpty(name)) { return "Plant"; } int num = name.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase); if (num >= 0) { name = name.Substring(0, num); } name = name.Trim(); int length = name.Length; if (length >= 4 && name[length - 1] == ')') { int num2 = name.LastIndexOf('('); if (num2 > 0 && num2 < length - 2) { bool flag = true; for (int i = num2 + 1; i < length - 1; i++) { if (name[i] < '0' || name[i] > '9') { flag = false; break; } } if (flag) { name = name.Substring(0, num2).TrimEnd(Array.Empty<char>()); } } } return name; } private static bool IsMeshOrLodName(string name) { if (!NameContains(name, "AutoLOD") && !NameContains(name, "TreeBark") && !NameContains(name, "PalmMesh") && !NameContains(name, "PalmLeaf") && !NameContains(name, "BushLeaves") && !NameContains(name, "TreeCrown") && !NameContains(name, "_Leaves")) { return name.StartsWith("Spine", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsMesaCactusName(string name) { if (string.IsNullOrEmpty(name) || IsMeshOrLodName(name)) { return false; } if (NameContains(name, "Tall Cactus") || NameContains(name, "Cactus Ball Base") || NameContains(name, "Cactus Ball Big")) { return true; } if (!NameContains(name, "cactus")) { return false; } if (!NameContains(name, "Props") && !NameContains(name, "Bushes") && !NameContains(name, "Spawns")) { return !NameContains(name, "Oasis"); } return false; } private static bool IsWalkableSurfaceName(string name) { if (!NameContains(name, "LavaPillar") && !NameContains(name, "rock_Ring")) { return NameContains(name, "Plartform"); } return true; } private static bool IsNestName(string name) { if (!NameContains(name, "EggNest") && !NameContains(name, "BirdNest")) { return NameContains(name, "EggNestRaven"); } return true; } private static bool HasNamedAncestor(Transform t, string token) { Transform val = (((Object)(object)t != (Object)null) ? t.parent : null); int num = 0; while ((Object)(object)val != (Object)null && num < 8) { if (!string.IsNullOrEmpty(((Object)val).name) && NameContains(((Object)val).name, token)) { return true; } val = val.parent; num++; } return false; } private static bool ShouldSkipKilnCitadel(int segment) { if (Plugin.syncedSpawnsInKilnCitadel) { return false; } return IsKilnOrCitadelSegment(segment); } private static bool IsKilnOrCitadelSegment(int segment) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Invalid comparison between Unknown and I4 //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Invalid comparison between Unknown and I4 //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Invalid comparison between Unknown and I4 //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Invalid comparison between Unknown and I4 //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Invalid comparison between Unknown and I4 //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Invalid comparison between Unknown and I4 if (segment < 0) { return false; } try { Segment val = (Segment)(byte)segment; if ((int)val == 5) { return true; } MapHandler instance = Singleton<MapHandler>.Instance; Transform val2 = null; BiomeType val3 = (BiomeType)0; if ((Object)(object)instance != (Object)null && instance.segments != null && segment < instance.segments.Length) { MapSegment val4 = instance.segments[segment]; if (val4 != null) { val3 = val4._biome; if ((Object)(object)val4.segmentParent != (Object)null) { val2 = val4.segmentParent.transform; } } } string name = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : ""); if ((IsCalderaOrGloomName(name) || (int)val3 == 3 || (int)val3 == 8) && (int)val != 4 && (int)val != 5) { return false; } if ((int)val == 4) { return true; } if (IsKilnCitadelSubtree(name)) { return true; } return (int)val3 == 5 || (int)val3 == 9; } catch { return false; } } private static bool IsKilnCitadelSubtree(string name) { if (string.IsNullOrEmpty(name) || IsCalderaOrGloomName(name)) { return false; } if (!NameContains(name, "Peak_Kiln") && !NameContains(name, "Peak_Segment") && !NameContains(name, "Temple_Segment") && !NameContains(name, "Gloom Temple") && !name.Equals("Peak", StringComparison.OrdinalIgnoreCase) && !name.Equals("Citadel", StringComparison.OrdinalIgnoreCase)) { return name.Equals("Kiln", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsCalderaOrGloomName(string name) { if (!NameContains(name, "Caldera") && !NameContains(name, "Volcano_Segment") && !NameContains(name, "Swamp_Segment")) { if (NameContains(name, "Gloom")) { return !NameContains(name, "Gloom Temple"); } return false; } return true; } private static string DescribeSegment(int segment) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) try { MapHandler instance = Singleton<MapHandler>.Instance; if ((Object)(object)instance == (Object)null || instance.segments == null || segment < 0 || segment >= instance.segments.Length) { return ((object)(Segment)(byte)segment/*cast due to .constrained prefix*/).ToString(); } MapSegment val = instance.segments[segment]; string text = ((object)(Segment)(byte)segment/*cast due to .constrained prefix*/).ToString(); if (val == null) { return text; } string text2 = ((object)ResolveBiome(segment)/*cast due to .constrained prefix*/).ToString(); string text3 = (((Object)(object)val.segmentParent != (Object)null) ? ((Object)val.segmentParent).name : "none"); return text + " " + text2 + " / " + text3; } catch { return "segment " + segment; } } private static GameObject TryInstantiateItemRoom(string prefabName, Vector3 pos, Quaternion rot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { return PhotonNetwork.InstantiateItemRoom(prefabName, pos, rot, true); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Campfire Building] InstantiateItemRoom('" + prefabName + "') failed: " + ex.Message)); } return null; } } private static GameObject TryInstantiateRoomObject(string prefabName, Vector3 pos, Quaternion rot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { return PhotonNetwork.InstantiateRoomObject(prefabName, pos, rot, (byte)0, (object[])null); } catch { return null; } } private static bool TrySnapToGround(Vector3 origin, float minY, out Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return TrySnapToGround(origin, minY, 14f, out pos); } private static bool TrySnapToGround(Vector3 origin, float minY, float maxDrop, out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) pos = origin; Vector3[] array = (Vector3[])(object)new Vector3[3] { origin + Vector3.up * 6f, origin + Vector3.up * 25f, new Vector3(origin.x, origin.y + 80f, origin.z) }; int num = TerrainMask(); for (int i = 0; i < array.Length; i++) { if (TryPickGroundHit(array[i], 160f, minY, maxDrop, num, out pos)) { return true; } } int num2 = GroundMask(); if (num2 != num) { for (int j = 0; j < array.Length; j++) { if (TryPickGroundHit(array[j], 160f, minY, maxDrop, num2, out pos)) { return true; } } } return false; } private static bool TryPickGroundHit(Vector3 from, float rayLength, float minY, float maxDrop, int mask, out Vector3 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) pos = from; int num = Physics.RaycastNonAlloc(from, Vector3.down, RayHits, rayLength, mask, (QueryTriggerInteraction)1); bool flag = mask == GroundMask(); int num2 = -1; float num3 = float.MinValue; for (int i = 0; i < num; i++) { RaycastHit hit = RayHits[i]; if ((!flag || !IsCanopyHit(hit)) && IsStandableHit(hit, minY, maxDrop) && !IsBelowGloomWater(((RaycastHit)(ref hit)).point) && !IsGloomWaterCollider(((RaycastHit)(ref hit)).collider) && !(Vector3.Angle(Vector3.up, ((RaycastHit)(ref hit)).normal) > 55f) && ((RaycastHit)(ref hit)).point.y > num3) { num3 = ((RaycastHit)(ref hit)).point.y; num2 = i; } } if (num2 < 0) { return false; } pos = ((RaycastHit)(ref RayHits[num2])).point + Vector3.up * 0.12f; return true; } private static bool IsCanopyHit(RaycastHit hit) { Transform val = (((Object)(object)((RaycastHit)(ref hit)).collider != (Object)null) ? ((Component)((RaycastHit)(ref hit)).collider).transform : null); int num = 0; while ((Object)(object)val != (Object)null && num < 4) { if (!string.IsNullOrEmpty(((Object)val).name) && (IsMeshOrLodName(((Object)val).name) || NameContains(((Object)val).name, "Leaf") || NameContains(((Object)val).name, "Leaves") || NameContains(((Object)val).name, "Crown") || NameContains(((Object)val).name, "Frond") || NameContains(((Object)val).name, "Foliage") || NameContains(((Object)val).name, "Vine"))) { return true; } val = val.parent; num++; } return false; } private static bool IsStandableHit(RaycastHit hit, float minY, float maxDrop) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL