Decompiled source of CustomIslandsLoader v1.5.0
HTFMapLoader.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExtraIslands; using FishNet.Object; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("HTFMapLoader")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("HTFMapLoader")] [assembly: AssemblyTitle("HTFMapLoader")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal static class HoverGuard { private static readonly HashSet<string> _told = new HashSet<string>(); internal static bool HasIt(object instance, string field) { try { Object val = (Object)((instance is Object) ? instance : null); if (val == (Object)null) { return true; } FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), field); if (fieldInfo == null) { return true; } object? value = fieldInfo.GetValue(instance); if ((Object)((value is Object) ? value : null) != (Object)null) { return true; } if (_told.Add(val.name + "." + field)) { MapLoaderPlugin.Log.LogWarning((object)("'" + val.name + "' has no " + field.TrimStart(new char[1] { '_' }) + " assigned, and the game reads it without checking - which throws and stops EVERY interaction near it, NPCs included. Skipped so the rest of the island keeps working. Fix the map by assigning it, or delete the stand.")); } return false; } catch { return true; } } } [HarmonyPatch] internal static class BaitStandsWithNoBait { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("BaitPurchasable"); if (!(type == null)) { return AccessTools.Method(type, "OnStartHover", (Type[])null, (Type[])null); } return null; } private static bool Prepare() { return TargetMethod() != null; } private static bool Prefix(object __instance) { return HoverGuard.HasIt(__instance, "_bait"); } } [HarmonyPatch] internal static class AttachmentStandsWithNoAttachment { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("AttachmentPurchasable"); if (!(type == null)) { return AccessTools.Method(type, "OnStartHover", (Type[])null, (Type[])null); } return null; } private static bool Prepare() { return TargetMethod() != null; } private static bool Prefix(object __instance) { return HoverGuard.HasIt(__instance, "_info"); } } [BepInPlugin("yoxi.htf.maploader", "HTF Map Loader", "1.4.0")] public class MapLoaderPlugin : BaseUnityPlugin { [Serializable] private class MapInfo { public string name; public string author; public int replacesIsland = -1; public int casinoFromIsland = -1; public string sky = ""; } private static class ArrivedUnderOwnSteam { internal static bool InsideTheRing; internal static float At = -999f; internal static bool ConsumeRecent() { bool result = Time.time - At < 30f; At = -999f; return result; } } [HarmonyPatch] private static class WatchTheRing { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("IslandSpawner"); if (!(type == null)) { return AccessTools.Method(type, "OnTriggerEnter", (Type[])null, (Type[])null); } return null; } private static bool Prepare() { return TargetMethod() != null; } private static void Prefix() { ArrivedUnderOwnSteam.InsideTheRing = true; } private static void Finalizer() { ArrivedUnderOwnSteam.InsideTheRing = false; } } [HarmonyPatch] private static class WatchWhoAsksForAnIsland { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("OnlineIslandManager"); if (!(type == null)) { return AccessTools.Method(type, "SpawnIsland", (Type[])null, (Type[])null); } return null; } private static bool Prepare() { return TargetMethod() != null; } private static void Prefix() { if (ArrivedUnderOwnSteam.InsideTheRing) { ArrivedUnderOwnSteam.At = Time.time; } } } private struct Placement { public Vector3 pos; public Quaternion rot; } public const string Id = "yoxi.htf.maploader"; internal static ManualLogSource Log; private static ConfigEntry<int> _slot; private static ConfigEntry<bool> _verbose; private static readonly ConfigEntry<bool>[] _useCustom = new ConfigEntry<bool>[5]; private static ConfigEntry<float> _dayMinutes; private static ConfigEntry<KeyCode> _timeBackKey; private static ConfigEntry<KeyCode> _timeForwardKey; private static ConfigEntry<float> _timeScrubSeconds; private static ConfigEntry<bool> _importGameplay; private static ConfigEntry<int> _casinoFrom; private static ConfigEntry<bool> _terrainShader; private static ConfigEntry<bool> _paintItPink; private static ConfigEntry<bool> _standOnGround; private static readonly Dictionary<string, int> SlotOfScene = new Dictionary<string, int>(); private static readonly Dictionary<string, int> CasinoOfScene = new Dictionary<string, int>(); private static readonly Dictionary<string, string> SkyOfScene = new Dictionary<string, string>(); private static readonly Dictionary<int, string> Replacements = new Dictionary<int, string>(); private static readonly List<AssetBundle> Held = new List<AssetBundle>(); private static readonly string[] Gameplay = new string[8] { "NPCs", "ShopItems", "SlotMachine", "CasinoHolder", "GrillHolder", "CreatureSpawners", "IslandManager", "ExtraColliders" }; private static readonly List<GameObject> Imported = new List<GameObject>(); private static readonly Dictionary<string, Placement> MapPlacement = new Dictionary<string, Placement>(); private static readonly List<KeyValuePair<float, string>> _skipped = new List<KeyValuePair<float, string>>(); private static bool _dumped; private const int IslandScenes = 6; private static readonly string[] NoCollision = new string[19] { "leaf", "leafs", "grass", "fern", "plant", "windy", "coconut", "poof", "smoke", "nightsky", "stars", "moonglow", "moonface", "galaxydust", "cloud", "sun", "shade", "aurora", "moonphase" }; public static string MapsFolder => Path.Combine(Paths.PluginPath, "HTFMaps"); private void Awake() { //IL_01ea: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; _slot = ((BaseUnityPlugin)this).Config.Bind<int>("Maps", "ReplaceIsland", 2, "MAPMAKERS ONLY: the island a json-less test bundle stands in for, 0 to 4. Finished maps declare their island in their own .json, and that always wins - a custom island can only replace the island it was built for."); _importGameplay = ((BaseUnityPlugin)this).Config.Bind<bool>("Maps", "ImportGameplay", true, "Take the NPCs, shops and slot machines from the island your map replaces and put the real, working ones into your map. Turn this off for a map that is meant to be empty."); _casinoFrom = ((BaseUnityPlugin)this).Config.Bind<int>("Maps", "CasinoFromIsland", 3, "Put a working roulette table on your map by borrowing it from an island that has one. Only islands 3 and 4 (the fourth and fifth) have a casino. Set to -1 to leave it alone.\nPlace a prop named RouletteTable in your map to say where it should stand."); _terrainShader = ((BaseUnityPlugin)this).Config.Bind<bool>("Maps", "TerrainUsesGameShader", true, "Draw sculpted ground with the game's own land shader, so raised and carved areas match the island around them instead of looking like plain flat colour. Turn off if your terrain comes out grey."); _paintItPink = ((BaseUnityPlugin)this).Config.Bind<bool>("Maps", "HighlightSculptedGround", false, "Paint the map's own sculpted ground bright magenta, so it is obvious at a glance which ground is yours and which is something else. A diagnostic - turn it off again once you have looked."); _standOnGround = ((BaseUnityPlugin)this).Config.Bind<bool>("Maps", "StandGameplayOnTheGround", false, "Let the ground decide the height of imported NPCs and shops, keeping the left-and-right placement the map asked for. A map whose land has been reshaped leaves them at the old island's heights, hanging in the air."); _dayMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Sky", "MinutesPerDay", 20f, "For maps built with the day + night cycle: how many real minutes one full day (sunrise to sunrise) lasts."); _timeBackKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Sky", "TimeBackKey", (KeyCode)276, "Hold to roll time backwards on a day + night cycle map. Set to None to disable."); _timeForwardKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Sky", "TimeForwardKey", (KeyCode)275, "Hold to run time forwards on a day + night cycle map. Set to None to disable."); _timeScrubSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Sky", "TimeScrubSeconds", 8f, "Holding a time key crosses one whole day in this many real seconds."); _verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Maps", "Verbose", false, "Log every island load, for working out why a map did not appear."); for (int i = 0; i < 5; i++) { _useCustom[i] = ((BaseUnityPlugin)this).Config.Bind<bool>("Maps", "UseCustomIsland" + (i + 1), true, "Load the custom map installed for island " + (i + 1) + ". false = the original island, with the map files kept installed for later."); } LoadBundles(); SceneManager.sceneLoaded += OnSceneLoaded; try { new Harmony("yoxi.htf.maploader").PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)"Patched IslandManager."); try { ExtraIslandsHost.Init(((BaseUnityPlugin)this).Config, Log); } catch (Exception ex) { Log.LogError((object)("Could not start the extra-island support: " + ex)); } if (AccessTools.TypeByName("IslandSpawner") != null && AccessTools.TypeByName("OnlineIslandManager") != null) { Log.LogInfo((object)"Watching the island trigger rings, so sailing up to an island will not move your boat."); } else { Log.LogWarning((object)"Could not find IslandSpawner or OnlineIslandManager, so sailing up to an island may move your boat onto its spawn point. Every other way of arriving still works."); } } catch (Exception ex2) { Log.LogError((object)("Could not patch IslandManager - no custom map will load. " + ex2)); } } private static MapInfo SidecarFor(string bundlePath) { string path = Path.ChangeExtension(bundlePath, ".json"); if (!File.Exists(path)) { return null; } try { return JsonUtility.FromJson<MapInfo>(File.ReadAllText(path)); } catch (Exception ex) { Log.LogWarning((object)(Path.GetFileName(path) + " could not be read (" + ex.Message + "); using the config defaults instead.")); return null; } } private void LoadBundles() { Directory.CreateDirectory(MapsFolder); string[] array = Directory.GetDirectories(Paths.PluginPath, "HTFMaps", SearchOption.AllDirectories).SelectMany((string dir) => Directory.GetFiles(dir, "*.bundle")).Concat(from f in Directory.GetFiles(Paths.PluginPath, "*.bundle", SearchOption.AllDirectories) where File.Exists(Path.ChangeExtension(f, ".json")) select f) .Distinct() .ToArray(); if (array.Length == 0) { Log.LogInfo((object)("No maps in " + MapsFolder + ". Drop a .bundle in there.")); return; } string[] array2 = array; foreach (string text in array2) { AssetBundle val; try { val = AssetBundle.LoadFromFile(text); } catch (Exception ex) { Log.LogError((object)("Could not read " + Path.GetFileName(text) + ": " + ex.Message)); continue; } if ((Object)(object)val == (Object)null) { Log.LogError((object)(Path.GetFileName(text) + " is not an asset bundle, or was built for a different Unity version. The game is 6000.4.4f1.")); continue; } string[] allScenePaths = val.GetAllScenePaths(); if (allScenePaths == null || allScenePaths.Length == 0) { Log.LogError((object)(Path.GetFileName(text) + " has no scene in it. A map bundle must be built FROM A SCENE, not from assets.")); val.Unload(false); continue; } Held.Add(val); MapInfo mapInfo = SidecarFor(text); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); int num2 = ((mapInfo != null && mapInfo.replacesIsland >= 0) ? Mathf.Clamp(mapInfo.replacesIsland, 0, 4) : Mathf.Clamp(_slot.Value, 0, 4)); if (Replacements.ContainsKey(num2)) { Log.LogWarning((object)("Island " + num2 + " is already taken by another map. Set \"" + fileNameWithoutExtension + " replaces island\" to a free one, or remove a bundle from " + MapsFolder + ".")); } Replacements[num2] = allScenePaths[0]; SlotOfScene[allScenePaths[0]] = num2; if (mapInfo != null && mapInfo.casinoFromIsland >= 0) { CasinoOfScene[allScenePaths[0]] = mapInfo.casinoFromIsland; } if (mapInfo != null && !string.IsNullOrEmpty(mapInfo.sky)) { SkyOfScene[allScenePaths[0]] = mapInfo.sky; } if (mapInfo != null && (!string.IsNullOrEmpty(mapInfo.name) || !string.IsNullOrEmpty(mapInfo.author))) { Log.LogInfo((object)(" \"" + (string.IsNullOrEmpty(mapInfo.name) ? fileNameWithoutExtension : mapInfo.name) + "\"" + (string.IsNullOrEmpty(mapInfo.author) ? "" : (" by " + mapInfo.author)))); } Log.LogInfo((object)("Loaded " + Path.GetFileName(text) + " -> " + Path.GetFileNameWithoutExtension(allScenePaths[0]) + ", replacing island " + num2 + ".")); if (allScenePaths.Length > 1) { Log.LogWarning((object)(Path.GetFileName(text) + " holds " + allScenePaths.Length + " scenes; using the first.")); } } if (Replacements.Count > 0) { Log.LogInfo((object)("---- " + Replacements.Count + " custom map(s) ready: " + string.Join(", ", SlotOfScene.Select((KeyValuePair<string, int> kv) => "island " + kv.Value + " <- " + Path.GetFileNameWithoutExtension(kv.Key)).ToArray()) + " ----")); Log.LogWarning((object)"CO-OP NOTE: every player in the lobby needs the SAME maps installed on the SAME islands - a player without the map will see the original island and stand in different scenery than the rest of the crew."); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0006: 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_006e: Unknown result type (might be due to invalid IL or missing references) bool flag = ArrivedUnderOwnSteam.ConsumeRecent(); if (IsOurs(scene)) { WakeAdditionalLights(); Log.LogInfo((object)("Arriving at '" + ((Scene)(ref scene)).name + "': " + (flag ? "you sailed here, so nothing gets moved." : "you were brought here, so the map's own spawn points are used for you and the boat."))); ((MonoBehaviour)this).StartCoroutine(SetUp(scene, !flag)); } else if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).buildIndex < 0) { WakeAdditionalLights(); try { Wire(scene); Log.LogInfo((object)("Wired the spawn points on '" + ((Scene)(ref scene)).name + "', an island this mod did not load. A spawn point is honoured whoever put it there.")); } catch (Exception ex) { Log.LogError((object)("Could not wire the spawn points on '" + ((Scene)(ref scene)).name + "': " + ex.Message)); } } } private static void WakeAdditionalLights() { try { RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline; if ((Object)(object)currentRenderPipeline == (Object)null) { return; } Type type = ((object)currentRenderPipeline).GetType(); FieldInfo field = type.GetField("m_AdditionalLightsRenderingMode", BindingFlags.Instance | BindingFlags.NonPublic); if (!(field == null)) { if (Convert.ToInt32(field.GetValue(currentRenderPipeline)) != 1) { field.SetValue(currentRenderPipeline, Enum.ToObject(field.FieldType, 1)); Log.LogInfo((object)"Additional lights set to per-pixel so map lights (torches...) can shine."); } FieldInfo field2 = type.GetField("m_AdditionalLightsPerObjectLimit", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null && Convert.ToInt32(field2.GetValue(currentRenderPipeline)) < 4) { field2.SetValue(currentRenderPipeline, 4); } } } catch (Exception) { } } private IEnumerator SetUp(Scene scene, bool placeEveryone) { //IL_000e: 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) if (_importGameplay != null && _importGameplay.Value && (SlotOfScene.TryGetValue(((Scene)(ref scene)).path, out var value) || SlotOfScene.TryGetValue(FirstKeyFor(scene), out value))) { if (BringsItsOwnGameplay(scene)) { Log.LogInfo((object)("This map carries its own working NPCs and shops, so nothing was borrowed from island " + value + ". They are the mapmaker's own.")); } else { yield return ImportGameplay(scene, value); } } int num = ((_casinoFrom != null) ? _casinoFrom.Value : (-1)); if (CasinoOfScene.TryGetValue(((Scene)(ref scene)).path, out var value2)) { num = value2; } if (num >= 0) { yield return ImportCasino(scene, num); } yield return FetchRequestedGoods(scene); try { Wire(scene); } catch (Exception ex) { Log.LogError((object)("Could not wire up " + ((Scene)(ref scene)).name + ": " + ex)); } ((MonoBehaviour)this).StartCoroutine(PutTheBoatWhereTheMapAsked(placeEveryone)); ((MonoBehaviour)this).StartCoroutine(PutThePlayerWhereTheMapAsked(placeEveryone)); } private IEnumerator ImportCasino(Scene ours, int fromIsland) { //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) if ((Object)(object)FindIn(ours, "CasinoHolder") != (Object)null) { yield break; } Transform mine = FindIn(ours, "RouletteTable"); if ((Object)(object)mine == (Object)null) { if (_verbose != null && _verbose.Value) { Log.LogInfo((object)"No RouletteTable in this map, so no casino to place."); } yield break; } Transform val = FindUnder(mine, "Wheel"); Transform val2 = (((Object)(object)val != (Object)null) ? val : mine); Vector3 targetPos = val2.position; Quaternion targetRot = val2.rotation; int buildIndex = fromIsland + 1; AsyncOperation op = SceneManager.LoadSceneAsync(buildIndex, (LoadSceneMode)1); if (op == null) { Log.LogError((object)("Could not open island " + fromIsland + ".")); yield break; } while (!op.isDone) { yield return null; } Scene sceneByBuildIndex = SceneManager.GetSceneByBuildIndex(buildIndex); if (!((Scene)(ref sceneByBuildIndex)).IsValid()) { Log.LogError((object)("Island " + fromIsland + " did not load.")); yield break; } Transform val3 = FindIn(sceneByBuildIndex, "CasinoHolder"); Transform val4 = FindNpc(sceneByBuildIndex, "Roulette"); if ((Object)(object)val3 == (Object)null) { Log.LogWarning((object)("Island " + fromIsland + " has no CasinoHolder. Only the fourth and fifth islands do - set CasinoFromIsland to 3 or 4.")); } else { val3.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(((Component)val3).gameObject, ours); Transform val5 = FindUnder(val3, "Wheel"); Transform val6 = (((Object)(object)val5 != (Object)null) ? val5 : val3); Quaternion val7 = Quaternion.Inverse(val3.rotation) * val6.rotation; val3.rotation = targetRot * Quaternion.Inverse(val7); val3.position += targetPos - val6.position; Transform val8 = FindIn(ours, "IslandHolder"); if ((Object)(object)val8 != (Object)null) { val3.SetParent(val8, true); } Imported.Add(((Component)val3).gameObject); MeshRenderer[] componentsInChildren = ((Component)val3).GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val9 in componentsInChildren) { MeshFilter component = ((Component)val9).GetComponent<MeshFilter>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null) && ((Object)component.sharedMesh).name.StartsWith("Combined")) { ((Renderer)val9).enabled = false; } } int num = 0; Renderer[] componentsInChildren2 = ((Component)mine).GetComponentsInChildren<Renderer>(true); foreach (Renderer val10 in componentsInChildren2) { if (!((Object)(object)val10 == (Object)null) && val10.enabled && !IsPartOfTable(((Component)val10).transform, mine)) { val10.enabled = false; num++; } } if ((Object)(object)val4 != (Object)null) { Vector3 val11 = val4.position - val6.position; val4.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(((Component)val4).gameObject, ours); val4.position = targetPos + val11; Transform val12 = FindIn(ours, "NPCs"); if ((Object)(object)val12 != (Object)null) { val4.SetParent(val12, true); } } Log.LogInfo((object)("Casino from island " + fromIsland + " lined up on your table at " + ((Vector3)(ref targetPos)).ToString("0.00") + ", " + num + " duplicate piece(s) hidden" + (((Object)(object)val4 != (Object)null) ? ", croupier included." : "."))); } foreach (object item in CloseTheBorrowedIsland(sceneByBuildIndex, ours)) { yield return item; } } private static List<Transform> FindAllIn(Scene scene, string name) { List<Transform> list = new List<Transform>(); GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Transform[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)((Component)val).gameObject).name == name) { list.Add(val); } } } return list; } private static Transform FindTableTop(Scene scene) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown Transform val = FindIn(scene, "IslandHolder"); if ((Object)(object)val == (Object)null) { return null; } Transform val2 = val.Find("Meshes"); if ((Object)(object)val2 == (Object)null) { return null; } foreach (Transform item in val2) { Transform val3 = item; if (((Object)((Component)val3).gameObject).name == "Table") { return val3; } } return null; } private static bool IsPartOfTable(Transform t, Transform root) { Transform val = t; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root.parent) { if (((Object)((Component)val).gameObject).name == "Table") { return true; } val = val.parent; } return false; } private static Transform FindNpc(Scene scene, string contains) { //IL_0000: 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_002c: Expected O, but got Unknown Transform val = FindIn(scene, "NPCs"); if ((Object)(object)val == (Object)null) { return null; } foreach (Transform item in val) { Transform val2 = item; if (((Object)((Component)val2).gameObject).name.IndexOf(contains, StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } } return null; } private static Transform FindUnder(Transform root, string name) { Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)((Component)val).gameObject).name == name) { return val; } } return null; } private static string FirstKeyFor(Scene scene) { foreach (KeyValuePair<string, int> item in SlotOfScene) { if (Path.GetFileNameWithoutExtension(item.Key) == ((Scene)(ref scene)).name) { return item.Key; } } return ""; } private IEnumerator ImportGameplay(Scene ours, int slot) { //IL_000e: 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) int removed = StripDeadGameplay(ours); int buildIndex = slot + 1; AsyncOperation op = SceneManager.LoadSceneAsync(buildIndex, (LoadSceneMode)1); if (op == null) { Log.LogError((object)("Could not load island " + slot + " to borrow its gameplay from.")); yield break; } while (!op.isDone) { yield return null; } Scene sceneByBuildIndex = SceneManager.GetSceneByBuildIndex(buildIndex); if (!((Scene)(ref sceneByBuildIndex)).IsValid()) { Log.LogError((object)("Island " + slot + " did not load.")); yield break; } int moved = 0; int placed = 0; List<Transform> list = new List<Transform>(); GameObject[] rootGameObjects = ((Scene)(ref sceneByBuildIndex)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if (((Object)val).name != "IslandHolder") { if (Wanted(((Object)val).name)) { list.Add(val.transform); } continue; } foreach (Transform item in val.transform) { Transform val2 = item; if (Wanted(((Object)val2).name)) { list.Add(val2); } } } Transform val3 = FindIn(ours, "IslandHolder"); foreach (Transform item2 in list) { if (!((Object)(object)item2 == (Object)null)) { item2.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(((Component)item2).gameObject, ours); if ((Object)(object)val3 != (Object)null) { item2.SetParent(val3, true); } placed += PlaceLikeTheMapAsked(item2); Imported.Add(((Component)item2).gameObject); moved++; } } foreach (object item3 in CloseTheBorrowedIsland(sceneByBuildIndex, ours)) { yield return item3; } RegisterTheNpcsProperly(ours); ((MonoBehaviour)this).StartCoroutine(RegisterAgainOnceTheServerIsUp(ours)); Log.LogInfo((object)("Borrowed " + moved + " gameplay group(s) from island " + slot + ((removed > 0) ? (", after removing " + removed + " dead copies from the map") : "") + ". " + ((placed > 0) ? (placed + " object(s) moved to where the map put them.") : "The map had none of its own, so they stand where the island had them."))); } private static bool Wanted(string name) { string[] gameplay = Gameplay; foreach (string text in gameplay) { if (name == text) { return true; } } return false; } private static bool BringsItsOwnGameplay(Scene scene) { if (!((Scene)(ref scene)).IsValid()) { return false; } GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if ((Object)(object)val == (Object)null) { continue; } MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && ((object)val2).GetType().Name == "NPC") { return true; } } } return false; } private static int StripDeadGameplay(Scene scene) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown MapPlacement.Clear(); Imported.Clear(); List<GameObject> list = new List<GameObject>(); GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if (Wanted(((Object)val).name)) { list.Add(val); continue; } foreach (Transform item in val.transform) { Transform val2 = item; if (Wanted(((Object)val2).name)) { list.Add(((Component)val2).gameObject); } } } int num = 0; foreach (GameObject item2 in list) { if (!((Object)(object)item2 == (Object)null)) { RememberTree(((Object)item2).name, item2.transform); Object.Destroy((Object)(object)item2); num++; } } return num; } private static void RememberTree(string key, Transform t) { RememberTree(key, t, 0); } private static void RememberTree(string key, Transform t, int depth) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0067: Expected O, but got Unknown if ((Object)(object)t == (Object)null) { return; } Placement value = new Placement { pos = t.position, rot = t.rotation }; if (!MapPlacement.ContainsKey(key)) { MapPlacement[key] = value; } if (depth > 0 && IsRigged(t)) { return; } foreach (Transform item in t) { Transform val = item; RememberTree(key + "/" + ((Object)val).name, val, depth + 1); } } private static bool IsRigged(Transform t) { if (!((Object)(object)((Component)t).GetComponent<SkinnedMeshRenderer>() != (Object)null)) { return (Object)(object)((Component)t).GetComponentInChildren<SkinnedMeshRenderer>(true) != (Object)null; } return true; } private static int PlaceLikeTheMapAsked(Transform group) { //IL_003d: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown if ((Object)(object)group == (Object)null) { return 0; } if (!IsAContainer(((Object)group).name)) { return MoveWholeThing(((Object)group).name, group); } int num = 0; if (MapPlacement.TryGetValue(((Object)group).name, out var value)) { group.position = value.pos; group.rotation = value.rot; num++; } List<Transform> list = new List<Transform>(); foreach (Transform item2 in group) { Transform item = item2; list.Add(item); } foreach (Transform item3 in list) { if ((Object)(object)item3 != (Object)null) { num += MoveWholeThing(((Object)group).name + "/" + ((Object)item3).name, item3); } } return num; } private static bool IsAContainer(string name) { if (!(name == "ShopItems") && !(name == "NPCs")) { return name == "CreatureSpawners"; } return true; } private static int MoveWholeThing(string key, Transform t) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null) { return 0; } Vector3 shift = Vector3.zero; float furthest = -1f; bool rootItself = false; BiggestMove(key, t, ref shift, ref furthest, ref rootItself, key, 0); if (furthest < 0f) { return 0; } if (rootItself && MapPlacement.TryGetValue(key, out var value)) { t.rotation = value.rot; } if (((Vector3)(ref shift)).sqrMagnitude > 1E-08f) { t.position += shift; } if (_verbose != null && _verbose.Value) { ManualLogSource log = Log; string[] obj = new string[5] { " placed ", key, " at ", null, null }; Vector3 position = t.position; obj[3] = ((Vector3)(ref position)).ToString("0.00"); obj[4] = (rootItself ? "" : " (following a part inside it)"); log.LogInfo((object)string.Concat(obj)); } return 1; } private static void BiggestMove(string key, Transform t, ref Vector3 shift, ref float furthest, ref bool rootItself, string rootKey, int depth) { //IL_001a: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown if ((Object)(object)t == (Object)null) { return; } if (MapPlacement.TryGetValue(key, out var value)) { Vector3 val = value.pos - t.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude > furthest) { furthest = sqrMagnitude; shift = val; rootItself = key == rootKey; } } if (depth > 0 && IsRigged(t)) { return; } foreach (Transform item in t) { Transform val2 = item; BiggestMove(key + "/" + ((Object)val2).name, val2, ref shift, ref furthest, ref rootItself, rootKey, depth + 1); } } private static void StandThemOnTheGround() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0084: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) if (_standOnGround != null && !_standOnGround.Value) { return; } int num = LayerMask.NameToLayer("Level"); if (num < 0) { num = 8; } int num2 = 1 << num; int num3 = 0; foreach (GameObject item in Imported) { if ((Object)(object)item == (Object)null) { continue; } foreach (Transform item2 in item.transform) { Transform val = item2; if ((Object)(object)val == (Object)null) { continue; } RaycastHit[] array = Physics.RaycastAll(val.position + Vector3.up * 4f, Vector3.down, 40f, num2, (QueryTriggerInteraction)1); float num4 = float.NegativeInfinity; string text = "nothing"; RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val2 = array2[i]; if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !((Component)((RaycastHit)(ref val2)).collider).transform.IsChildOf(val) && !(((Component)((RaycastHit)(ref val2)).collider).gameObject.scene != ((Component)val).gameObject.scene) && !(((RaycastHit)(ref val2)).point.y > val.position.y + 0.5f) && ((RaycastHit)(ref val2)).point.y > num4) { num4 = ((RaycastHit)(ref val2)).point.y; text = ((Object)((Component)((RaycastHit)(ref val2)).collider).gameObject).name; } } if (float.IsNegativeInfinity(num4)) { Log.LogInfo((object)(" " + ((Object)val).name + " has no ground under it at all - left where the map put it.")); continue; } float num5 = val.position.y - num4; if (!(num5 < 0.3f)) { Vector3 position = val.position; position.y = num4; val.position = position; num3++; Log.LogInfo((object)(" dropped " + ((Object)val).name + " " + num5.ToString("0.0") + " m onto " + text)); } } } if (num3 > 0) { Log.LogInfo((object)("Stood " + num3 + " thing(s) back on the ground - the map had them at the old island's heights.")); } } private static void FloatIt(Transform marker) { //IL_000b: 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) if (SeaLevel(out var y) && !(marker.position.y >= y - 0.05f)) { Log.LogWarning((object)("Boat spawn is " + (y - marker.position.y).ToString("0.00") + " m below the sea surface (y " + y.ToString("0.0") + "). The boat will spawn there exactly, submerged, and float up. Move BoatSpawnPoint to y " + y.ToString("0.0") + " in the editor.")); } } private static bool SeaLevel(out float y) { //IL_0011: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011c: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) y = 0f; Renderer val = null; Bounds bounds2; for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (!((Scene)(ref sceneAt)).isLoaded) { continue; } GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects(); for (int j = 0; j < rootGameObjects.Length; j++) { Renderer[] componentsInChildren = rootGameObjects[j].GetComponentsInChildren<Renderer>(false); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || !val2.enabled || !((Object)((Component)val2).gameObject).name.StartsWith("Water")) { continue; } Bounds bounds = val2.bounds; if (((Bounds)(ref bounds)).size.x < 100f || ((Bounds)(ref bounds)).size.y > 1f) { continue; } if (!((Object)(object)val == (Object)null)) { float x = ((Bounds)(ref bounds)).size.x; bounds2 = val.bounds; if (!(x > ((Bounds)(ref bounds2)).size.x)) { continue; } } val = val2; } } } if ((Object)(object)val == (Object)null) { return false; } bounds2 = val.bounds; y = ((Bounds)(ref bounds2)).center.y; return true; } private static void Skipped(MeshFilter mf, string why) { //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_0020: 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_0025: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Renderer component = ((Component)mf).GetComponent<Renderer>(); Vector3 val; if (!((Object)(object)component != (Object)null)) { val = Vector3.zero; } else { Bounds bounds = component.bounds; val = ((Bounds)(ref bounds)).size; } Vector3 val2 = val; float num = Mathf.Max(val2.x, Mathf.Max(val2.y, val2.z)); if (!(num < 1.5f)) { _skipped.Add(new KeyValuePair<float, string>(num, ((Object)((Component)mf).gameObject).name + " (" + num.ToString("0.0") + " m) - " + why)); } } private static void ReportSolidity(Scene scene) { //IL_0048: 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_0051: 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_0058: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) List<KeyValuePair<float, string>> list = new List<KeyValuePair<float, string>>(); GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Renderer[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Renderer>(false); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || !val.enabled) { continue; } Bounds bounds = val.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float num = Mathf.Max(size.x, Mathf.Max(size.y, size.z)); if (num < 2f || num > 100f) { continue; } string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (text.StartsWith("palm") || text.StartsWith("rock") || text.StartsWith("coconut") || text.StartsWith("fire") || text.StartsWith("smoke")) { continue; } GameObject gameObject = ((Component)val).gameObject; Collider component = gameObject.GetComponent<Collider>(); string text2; if ((Object)(object)component == (Object)null) { text2 = "NO COLLIDER"; } else if (!component.enabled) { text2 = "collider DISABLED"; } else { MeshCollider val2 = (MeshCollider)(object)((component is MeshCollider) ? component : null); text2 = (((Object)(object)val2 == (Object)null) ? ((object)component).GetType().Name : (((Object)(object)val2.sharedMesh == (Object)null) ? "MeshCollider with NO MESH" : (val2.sharedMesh.isReadable ? "MeshCollider ok" : "MeshCollider, mesh NOT READABLE"))); } string text3 = ""; if ((Object)(object)component != (Object)null && component.enabled) { bounds = val.bounds; Vector3 center = ((Bounds)(ref bounds)).center; bounds = component.bounds; float num2 = Vector3.Distance(center, ((Bounds)(ref bounds)).center); if (num2 > 0.5f) { text3 = " *** COLLIDER IS " + num2.ToString("0.0") + " m FROM THE MESH ***"; } } list.Add(new KeyValuePair<float, string>(num, ((Object)gameObject).name + " (" + num.ToString("0.0") + " m) layer " + gameObject.layer + " " + LayerMask.LayerToName(gameObject.layer) + " - " + text2 + text3)); } } list.Sort((KeyValuePair<float, string> a, KeyValuePair<float, string> b) => b.Key.CompareTo(a.Key)); Log.LogInfo((object)"SOLIDITY, biggest first:"); for (int num3 = 0; num3 < list.Count && num3 < 30; num3++) { Log.LogInfo((object)(" " + list[num3].Value)); } } private static void RegisterTheNpcsProperly(Scene ours) { //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) Type type = AccessTools.TypeByName("NPC"); Type type2 = AccessTools.TypeByName("NPCManager"); if (type == null || type2 == null) { return; } FieldInfo fieldInfo = AccessTools.Field(type2, "_idToNpc"); MethodInfo methodInfo = AccessTools.Method(type2, "AddNpc", (Type[])null, (Type[])null); if (fieldInfo == null || methodInfo == null || !(fieldInfo.GetValue(null) is IDictionary dictionary)) { return; } List<object> list = new List<object>(); foreach (DictionaryEntry item in dictionary) { object? value = item.Value; if ((Object)((value is Object) ? value : null) == (Object)null) { list.Add(item.Key); } } foreach (object item2 in list) { dictionary.Remove(item2); } int num = 0; GameObject[] rootGameObjects = ((Scene)(ref ours)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Component[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren(type, true); foreach (Component val in componentsInChildren) { int count = dictionary.Count; methodInfo.Invoke(null, new object[1] { val }); if (dictionary.Count > count) { num++; } } } Log.LogInfo((object)("TALK PATH: Server.Instance=" + ((AccessTools.TypeByName("Server") == null) ? "?" : ((AccessTools.Property(AccessTools.TypeByName("Server"), "Instance") == null) ? "?" : (((Object)/*isinst with value type is only supported in some contexts*/ == (Object)null) ? "MISSING" : "ok"))) + " NPCManager.Instance=" + (((Object)/*isinst with value type is only supported in some contexts*/ == (Object)null) ? "MISSING" : "ok") + " register holds " + dictionary.Count + " NPC(s)")); FieldInfo fieldInfo2 = AccessTools.Field(type, "_id"); FieldInfo fieldInfo3 = AccessTools.Field(type, "_quests"); rootGameObjects = ((Scene)(ref ours)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Component[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren(type, true); foreach (Component val2 in componentsInChildren) { object obj = ((fieldInfo2 != null) ? fieldInfo2.GetValue(val2) : null); object obj2 = ((obj != null && dictionary.Contains(obj)) ? dictionary[obj] : null); ICollection collection = ((fieldInfo3 != null) ? (fieldInfo3.GetValue(val2) as ICollection) : null); Log.LogInfo((object)(" " + ((Object)val2).name + " id=" + obj?.ToString() + " registered=" + ((obj2 == null) ? "NO" : ((obj2 == val2) ? "yes, this one" : ("SOMEONE ELSE (" + ((Object)(Component)obj2).name + ")"))) + " quests=" + ((collection == null) ? "null" : collection.Count.ToString()) + " enabled=" + ((Behaviour)val2).enabled + " active=" + val2.gameObject.activeInHierarchy)); } } if (list.Count > 0 || num > 0) { Log.LogInfo((object)("NPC register: cleared " + list.Count + " dead entr(ies) and put " + num + " of the map's NPCs in. Without this they show their name but will not talk.")); } } private IEnumerator RegisterAgainOnceTheServerIsUp(Scene ours) { //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) Type type = AccessTools.TypeByName("NPCManager"); if (type == null) { yield break; } FieldInfo instanceField = AccessTools.Field(type, "Instance"); MethodInfo isServer = AccessTools.PropertyGetter(type, "IsServerInitialized"); if (instanceField == null || isServer == null) { yield break; } for (float waited = 0f; waited < 20f; waited += 0.5f) { object? value = instanceField.GetValue(null); Object val = (Object)((value is Object) ? value : null); if (val != (Object)null) { bool flag = false; try { flag = (bool)isServer.Invoke(val, null); } catch { } if (flag) { RegisterTheNpcsProperly(ours); ReArmTheTalkEvent(ours); Log.LogInfo((object)"Registered the map's NPCs again now the server is up - that is what gives them their quest index, and without it they will not talk."); yield break; } } yield return (object)new WaitForSeconds(0.5f); } Log.LogWarning((object)"The server never came up, so the NPCs may not talk."); } private static void ReArmTheTalkEvent(Scene ours) { Type type = AccessTools.TypeByName("NPC"); Type type2 = AccessTools.TypeByName("Interactable"); if (type == null || type2 == null) { return; } FieldInfo fieldInfo = AccessTools.Field(type2, "OnInteract"); MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); FieldInfo fieldInfo2 = AccessTools.Field(type, "_characterInteractable"); if (fieldInfo == null || methodInfo == null) { return; } int num = 0; int num2 = 0; GameObject[] rootGameObjects = ((Scene)(ref ours)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Component[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren(type, true); foreach (Component val in componentsInChildren) { Component val2 = (Component)((fieldInfo2 != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null) { val2 = val.GetComponentInChildren(type2, true); } if ((Object)(object)val2 == (Object)null) { continue; } if (((fieldInfo.GetValue(val2) is Delegate obj && obj.GetInvocationList().Length != 0) ? 1 : 0) > (false ? 1 : 0)) { num2++; continue; } try { methodInfo.Invoke(val, null); num++; } catch (Exception ex) { Log.LogWarning((object)("Could not re-arm " + ((Object)val).name + ": " + ex.Message)); } } } Log.LogInfo((object)("Talk event: " + num2 + " NPC(s) already wired, " + num + " re-armed. Nothing subscribed to the event is the difference between an NPC that shows a prompt and one that answers it.")); } private IEnumerator PutTheBoatWhereTheMapAsked(bool placeEveryone) { if (!placeEveryone) { Log.LogInfo((object)"You sailed to this island, so the boat has been left where you moored it. The game only puts the boat on a spawn point when it is teleporting you to an island."); yield break; } Type type = AccessTools.TypeByName("SpawnManager"); Type type2 = AccessTools.TypeByName("BoatManager"); if (type == null || type2 == null) { yield break; } FieldInfo posField = AccessTools.Field(type, "BoatSpawnPos"); FieldInfo rotField = AccessTools.Field(type, "BoatSpawnRot"); FieldInfo instField = AccessTools.Field(type2, "Instance"); MethodInfo boatProp = AccessTools.PropertyGetter(type2, "Boat"); MethodInfo move = AccessTools.Method(type2, "TryMoveBoat", (Type[])null, (Type[])null); if (posField == null || rotField == null || instField == null || boatProp == null || move == null) { yield break; } for (float waited = 0f; waited < 20f; waited += 0.25f) { object? value = instField.GetValue(null); Object mgr = (Object)((value is Object) ? value : null); Object val = (Object)((mgr != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if (mgr != (Object)null && val != (Object)null) { Vector3 val2 = (Vector3)posField.GetValue(null); Quaternion val3 = (Quaternion)rotField.GetValue(null); move.Invoke(mgr, new object[2] { val2, val3 }); yield return (object)new WaitForSeconds(1.5f); val2 = (Vector3)posField.GetValue(null); val3 = (Quaternion)rotField.GetValue(null); move.Invoke(mgr, new object[2] { val2, val3 }); Log.LogInfo((object)("Put the boat on the map's own spawn point at " + ((Vector3)(ref val2)).ToString("0.0") + ". The game had already moved it using the spawn point that was current before this map was wired.")); yield break; } yield return (object)new WaitForSeconds(0.25f); } Log.LogWarning((object)"No boat appeared, so it could not be put on the map's spawn point."); } private IEnumerator PutThePlayerWhereTheMapAsked(bool placeEveryone) { if (!placeEveryone) { Log.LogInfo((object)"You sailed to this island, so you have been left standing where you arrived rather than moved to the map's spawn point."); yield break; } Type type = AccessTools.TypeByName("SpawnManager"); Type type2 = AccessTools.TypeByName("Server"); Type type3 = AccessTools.TypeByName("PlayerManager"); if (type == null || type2 == null || type3 == null) { yield break; } FieldInfo posField = AccessTools.Field(type, "PlayerSpawnPos"); FieldInfo rotField = AccessTools.Field(type, "PlayerSpawnRot"); MethodInfo instProp = AccessTools.PropertyGetter(type2, "Instance"); MethodInfo teleport = AccessTools.Method(type2, "TeleportPlayer", (Type[])null, (Type[])null); FieldInfo alive = AccessTools.Field(type3, "AlivePlayers"); if (posField == null || rotField == null || instProp == null || teleport == null || alive == null) { yield break; } yield return (object)new WaitForSeconds(1.5f); object? obj = instProp.Invoke(null, null); Object val = (Object)((obj is Object) ? obj : null); IEnumerable enumerable = alive.GetValue(null) as IEnumerable; if (val == (Object)null || enumerable == null) { yield break; } Vector3 val2 = (Vector3)posField.GetValue(null); float num = (float)rotField.GetValue(null); int num2 = 0; foreach (object item in enumerable) { if (item != null) { try { teleport.Invoke(val, new object[3] { item, val2, num }); num2++; } catch (Exception ex) { Log.LogWarning((object)("Could not put a player on the map's spawn point: " + ex.Message)); } } } if (num2 > 0) { Log.LogInfo((object)("Put " + num2 + " player(s) on the map's own spawn point at " + ((Vector3)(ref val2)).ToString("0.0") + ".")); } } private static void PublishTheIslandStatics(Scene scene) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_010a: 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_0089: 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_0080: Unknown result type (might be due to invalid IL or missing references) Type type = AccessTools.TypeByName("Island"); if (type == null) { return; } Bounds val = default(Bounds); bool flag = false; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Renderer[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Renderer>(false); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && (IsGeneratedTerrain(((Object)((Component)val2).gameObject).name) || IsIslandLand(((Object)((Component)val2).gameObject).name))) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } } if (flag) { Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(((Bounds)(ref val)).center.x, 0f, ((Bounds)(ref val)).center.z); float num = Mathf.Max(((Bounds)(ref val)).extents.x, ((Bounds)(ref val)).extents.z); GameObject val3 = new GameObject("Island (this map)"); SceneManager.MoveGameObjectToScene(val3, scene); val3.transform.position = position; Component obj = val3.AddComponent(type); FieldInfo fieldInfo = AccessTools.Field(type, "_islandSize"); if (fieldInfo != null) { fieldInfo.SetValue(obj, num); } MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(obj, null); } Log.LogInfo((object)("Island centre published at " + ((Vector3)(ref position)).ToString("0.0") + ", roam size " + num.ToString("0") + "m - creatures now know where home is.")); } } private static void LightTheCampfires(Scene scene) { //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_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = new List<Transform>(); GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Transform[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "CampfireFlame" && (Object)(object)((Component)val).GetComponentInChildren<ParticleSystem>(true) == (Object)null) { list.Add(val); } } } if (list.Count == 0) { return; } ParticleSystem val2 = null; ParticleSystem val3 = null; ParticleSystem[] array = Resources.FindObjectsOfTypeAll<ParticleSystem>(); foreach (ParticleSystem val4 in array) { if ((Object)(object)val4 == (Object)null) { continue; } Scene scene2 = ((Component)val4).gameObject.scene; if (((Scene)(ref scene2)).IsValid()) { if ((Object)(object)val2 == (Object)null && ((Object)val4).name == "Fire") { val2 = val4; } if ((Object)(object)val3 == (Object)null && ((Object)val4).name == "Smoke") { val3 = val4; } } } if ((Object)(object)val2 == (Object)null) { Log.LogWarning((object)(list.Count + " campfire(s) could not be lit - the game has no Fire particle loaded to copy.")); return; } foreach (Transform item in list) { GameObject obj = Object.Instantiate<GameObject>(((Component)val2).gameObject, item); obj.transform.localPosition = Vector3.zero; obj.transform.localScale = Vector3.one * 0.55f; obj.SetActive(true); if ((Object)(object)val3 != (Object)null) { GameObject obj2 = Object.Instantiate<GameObject>(((Component)val3).gameObject, item); obj2.transform.localPosition = Vector3.zero; obj2.transform.localScale = Vector3.one * 0.55f; obj2.SetActive(true); } } Log.LogInfo((object)("Lit " + list.Count + " campfire(s).")); } private IEnumerator FetchRequestedGoods(Scene ours) { //IL_000e: 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) Type purchasableType = AccessTools.TypeByName("Purchasable"); Type itemPurchasableType = AccessTools.TypeByName("ItemPurchasable"); if (purchasableType == null) { yield break; } Dictionary<string, Transform> wantShop = new Dictionary<string, Transform>(); Dictionary<string, Transform> wantLoose = new Dictionary<string, Transform>(); GameObject[] rootGameObjects = ((Scene)(ref ours)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Transform[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (!WasImported(val) && !((Object)(object)((Component)val).GetComponent(purchasableType) != (Object)null)) { if (((Object)val).name.EndsWith(" (Purchasable)")) { wantShop[Normalise(((Object)val).name)] = val; } else if (((Object)val).name.EndsWith(" (Pickup)")) { wantLoose[Normalise(((Object)val).name)] = val; } } } } if (wantShop.Count == 0 && wantLoose.Count == 0) { yield break; } Log.LogInfo((object)("The map orders " + wantShop.Count + " shop stand(s) and " + wantLoose.Count + " loose item(s) by name.")); List<KeyValuePair<GameObject, Transform>> looseJobs = new List<KeyValuePair<GameObject, Transform>>(); for (int island = 0; island < 5; island++) { if (wantShop.Count == 0 && wantLoose.Count == 0) { break; } AsyncOperation op = SceneManager.LoadSceneAsync(island + 1, (LoadSceneMode)1); if (op == null) { continue; } while (!op.isDone) { yield return null; } Scene sceneByBuildIndex = SceneManager.GetSceneByBuildIndex(island + 1); if (!((Scene)(ref sceneByBuildIndex)).IsValid()) { continue; } rootGameObjects = ((Scene)(ref sceneByBuildIndex)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Component[] componentsInChildren2 = rootGameObjects[i].GetComponentsInChildren(purchasableType, true); foreach (Component val2 in componentsInChildren2) { string key = Normalise(((Object)val2.gameObject).name); if (wantShop.TryGetValue(key, out var value)) { wantShop.Remove(key); Transform transform = val2.transform; Vector3 position = value.position; Quaternion rotation = value.rotation; Object.Destroy((Object)(object)((Component)value).gameObject); transform.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(((Component)transform).gameObject, ours); transform.position = position; transform.rotation = rotation; Transform val3 = FindIn(ours, "IslandHolder"); if ((Object)(object)val3 != (Object)null) { transform.SetParent(val3, true); } Imported.Add(((Component)transform).gameObject); Log.LogInfo((object)("Shop stand \"" + ((Object)val2.gameObject).name + "\" fetched from island " + island + ".")); } if (itemPurchasableType != null && itemPurchasableType.IsInstanceOfType(val2) && wantLoose.TryGetValue(key, out value)) { FieldInfo fieldInfo = AccessTools.Field(itemPurchasableType, "_itemToPurchase"); Component val4 = (Component)((fieldInfo != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val4 != (Object)null) { wantLoose.Remove(key); looseJobs.Add(new KeyValuePair<GameObject, Transform>(val4.gameObject, value)); } } } } foreach (object item in CloseTheBorrowedIsland(sceneByBuildIndex, ours)) { yield return item; } } foreach (string key2 in wantShop.Keys) { Log.LogWarning((object)("No island sells \"" + key2 + "\" - that stand stays scenery.")); } foreach (string key3 in wantLoose.Keys) { Log.LogWarning((object)("No island sells \"" + key3 + "\" - nothing to spawn loose.")); } if (looseJobs.Count > 0) { ((MonoBehaviour)this).StartCoroutine(SpawnLooseWhenServerIsUp(looseJobs, ours)); } } private IEnumerator SpawnLooseWhenServerIsUp(List<KeyValuePair<GameObject, Transform>> jobs, Scene ours) { Type type = AccessTools.TypeByName("Server"); PropertyInfo instance = ((type != null) ? AccessTools.Property(type, "Instance") : null); MethodInfo isUp = ((type != null) ? AccessTools.PropertyGetter(type, "IsServerInitialized") : null); if (instance == null || isUp == null) { yield break; } object server = null; for (float waited = 0f; waited < 25f; waited += 0.5f) { server = instance.GetValue(null); bool flag = false; if ((Object)((server is Object) ? server : null) != (Object)null) { try { flag = (bool)isUp.Invoke(server, null); } catch { } } if (flag) { break; } server = null; yield return (object)new WaitForSeconds(0.5f); } if (server == null) { Log.LogInfo((object)"Not the server, or the server never came up - loose items are spawned by the host only."); yield break; } MethodInfo methodInfo = FindSpawnMethod(server.GetType()); int num = 0; foreach (KeyValuePair<GameObject, Transform> job in jobs) { if ((Object)(object)job.Value == (Object)null) { continue; } Vector3 val = job.Value.position + Vector3.up * 0.4f; GameObject val2 = Object.Instantiate<GameObject>(job.Key, val, job.Value.rotation); ((Object)val2).name = ((Object)job.Key).name; Object.Destroy((Object)(object)((Component)job.Value).gameObject); if (methodInfo != null) { try { methodInfo.Invoke(server, (methodInfo.GetParameters().Length != 3) ? new object[2] { val2, null } : new object[3] { val2, null, (object)default(Scene) }); num++; } catch (Exception ex) { Log.LogWarning((object)("Could not network-spawn " + ((Object)val2).name + ": " + ex.Message)); Object.Destroy((Object)(object)val2); } } } if (num > 0) { Log.LogInfo((object)(num + " loose item(s) spawned where the map asked.")); } } private static MethodInfo FindSpawnMethod(Type networkBehaviour) { Type type = networkBehaviour; while (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "Spawn")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length >= 1 && parameters[0].ParameterType == typeof(GameObject)) { return methodInfo; } } } type = type.BaseType; } return null; } private static string Normalise(string name) { return name.Replace("(Purchasable)", "").Replace("(Pickup)", "").Replace(" ", "") .Trim() .ToLowerInvariant(); } private static void MakeItNight(Scene scene, bool cycle) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_004a: 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_0059: 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_0095: Expected O, but got Unknown //IL_0123: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) GameObject val = null; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject val2 in rootGameObjects) { if (((Object)val2).name == "NightSky") { val = val2; break; } } if ((Object)(object)val == (Object)null) { val = new GameObject("NightSky"); SceneManager.MoveGameObjectToScene(val, scene); val.transform.position = SceneCentre(scene, out var _); Log.LogWarning((object)"Map asked for night but carries no NightSky object - rebuild it in the editor to get the galaxy."); } List<string> list = new List<string>(); foreach (Transform item in val.transform) { Transform val3 = item; list.Add(((Object)val3).name); } Log.LogInfo((object)("Sky carries: " + ((list.Count > 0) ? string.Join(", ", list.ToArray()) : "nothing"))); NightKeeper nightKeeper = val.AddComponent<NightKeeper>(); nightKeeper.Cycle = cycle; nightKeeper.DayMinutes = Mathf.Max(1f, _dayMinutes.Value); nightKeeper.BackKey = _timeBackKey.Value; nightKeeper.ForwardKey = _timeForwardKey.Value; nightKeeper.ScrubSeconds = Mathf.Max(1f, _timeScrubSeconds.Value); ManualLogSource log = Log; string obj = (cycle ? ("Day and night will cycle over " + ((Scene)(ref scene)).name + " (" + _dayMinutes.Value + " minutes per day)") : ("Night has fallen over " + ((Scene)(ref scene)).name)); Vector3 position = val.transform.position; log.LogInfo((object)(obj + " - sky from the bundle at " + ((Vector3)(ref position)).ToString("0"))); } private static Vector3 SceneCentre(Scene scene, out Bounds ground) { //IL_0001: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0056: 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) ground = default(Bounds); bool flag = false; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Renderer[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Renderer>(false); foreach (Renderer val in componentsInChildren) { if (IsGeneratedTerrain(((Object)((Component)val).gameObject).name) || IsIslandLand(((Object)((Component)val).gameObject).name)) { if (!flag) { ground = val.bounds; flag = true; } else { ((Bounds)(ref ground)).Encapsulate(val.bounds); } } } } if (!flag) { return Vector3.zero; } return new Vector3(((Bounds)(ref ground)).center.x, 0f, ((Bounds)(ref ground)).center.z); } private static bool IsOurs(Scene scene) { foreach (string value in Replacements.Values) { if (value == ((Scene)(ref scene)).path || Path.GetFileNameWithoutExtension(value) == ((Scene)(ref scene)).name) { return true; } } return false; } private static void Wire(Scene scene) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) Type type = AccessTools.TypeByName("SpawnManager"); if (type == null) { Log.LogError((object)"SpawnManager type not found."); return; } Transform val = FindIn(scene, "PlayerSpawnPoint"); Transform val2 = FindIn(scene, "BoatSpawnPoint"); if ((Object)(object)val == (Object)null) { Log.LogWarning((object)"This map has no PlayerSpawnPoint. Finding somewhere on the island instead - add an object with that exact name to choose."); Transform val3 = HighestGround(scene); if ((Object)(object)val3 == (Object)null) { Log.LogError((object)"Could not find any ground in this map either. Giving up."); return; } val = val3; } Transform val4 = FindIn(scene, "SpawnManager"); GameObject val5; if ((Object)(object)val4 != (Object)null) { val5 = ((Component)val4).gameObject; } else { val5 = new GameObject("SpawnManager"); SceneManager.MoveGameObjectToScene(val5, scene); } if ((Object)(object)val5.GetComponent(type) != (Object)null) { return; } Component val6 = val5.AddComponent(type); if ((Object)(object)val2 != (Object)null) { FloatIt(val2); } Set(val6, "_playerSpawnPoint", val); Set(val6, "_boatSpawnPoint", ((Object)(object)val2 != (Object)null) ? val2 : val); Object val7 = FindBoatPrefab(); if (val7 != (Object)null) { Set(val6, "_boatPrefab", val7); } else { Log.LogWarning((object)"No Boat prefab found, so no boat will be spawned. Everything else works."); } MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(val6, null); } ManualLogSource log = Log; string[] obj = new string[5] { "Wired ", ((Scene)(ref scene)).name, ": player spawn at ", null, null }; Vector3 position = val.position; obj[3] = ((Vector3)(ref position)).ToString("0.0"); object obj2; if (!((Object)(object)val2 != (Object)null)) { obj2 = ""; } else { position = val2.position; obj2 = ", boat at " + ((Vector3)(ref position)).ToString("0.0"); } obj[4] = (string)obj2; log.LogInfo((object)string.Concat(obj)); EvictLeftoverIslands(scene); PublishTheIslandStatics(scene); LightTheCampfires(scene); bool num = Chainloader.PluginInfos.ContainsKey("yoxi.htf.daynight"); string value; bool flag = SkyOfScene.TryGetValue(((Scene)(ref scene)).path, out value) && (value == "night" || value == "cycle"); if (num) { GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject val8 in rootGameObjects) { if (((Object)val8).name == "NightSky") { Object.Destroy((Object)(object)val8); } } if (flag) { Log.LogInfo((object)"HTF Day and Night is running - the map's own sky stands down and the standalone cycle rules."); } } else if (flag) { MakeItNight(scene, value == "cycle"); } int num2 = SwapInGameMaterials(scene); int num3 = MakeSolid(scene); StandThemOnTheGround(); ReportSolidity(scene); Log.LogInfo((object)("Swapped " + num2 + " materials for the game's own (wind, water, lava), and added " + num3 + " colliders.")); } private static int SwapInGameMaterials(Scene scene) { //IL_0250: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, Material> dictionary = new Dictionary<string, Material>(); Material[] array = Resources.FindObjectsOfTypeAll<Material>(); foreach (Material val in array) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name)) { string key = ((Object)val).name.Replace(" (Instance)", ""); if (!dictionary.TryGetValue(key, out var value)) { dictionary[key] = val; } else if (!TheGamesOwn(value) && TheGamesOwn(val)) { dictionary[key] = val; } } } int num = 0; int num2 = 0; Renderer val2 = null; List<Renderer> list = new List<Renderer>(); GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Renderer[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren) { if ((Object)(object)val3 == (Object)null) { continue; } if ((Object)(object)val2 == (Object)null && IsIslandLand(((Object)((Component)val3).gameObject).name)) { val2 = val3; } if (WasImported(((Component)val3).transform)) { continue; } bool flag = IsGeneratedTerrain(((Object)((Component)val3).gameObject).name); if (flag) { list.Add(val3); } if (flag && _terrainShader != null && !_terrainShader.Value) { continue; } if (_verbose != null && _verbose.Value && (flag || IsIslandLand(((Object)((Component)val3).gameObject).name))) { Describe(val3, dictionary); } Material[] sharedMaterials = val3.sharedMaterials; bool flag2 = false; for (int k = 0; k < sharedMaterials.Length; k++) { if ((Object)(object)sharedMaterials[k] == (Object)null) { continue; } Material val4 = Match(dictionary, ((Object)sharedMaterials[k]).name); if ((Object)(object)val4 == (Object)null || !TheGamesOwn(val4)) { if (GiveItItsShaderBack(sharedMaterials[k], dictionary)) { num2++; } } else if (!((Object)(object)val4 == (Object)(object)sharedMaterials[k])) { sharedMaterials[k] = val4; flag2 = true; num++; } } if (flag2) { val3.sharedMaterials = sharedMaterials; } } } if (num2 > 0) { Log.LogInfo((object)("Put the game's own shader back on " + num2 + " material(s) the game had not loaded - wind and grass move again.")); } MatchTheIslandsLighting(val2, list); PaintItPink(list); ReportWhatSharesTheGround(scene, list); return num; } private static void MatchTheIslandsLighting(Renderer islandLand, List<Renderer> sculpted) { //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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_007d: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)islandLand == (Object)null || sculpted.Count == 0) { return; } foreach (Renderer item in sculpted) { if (!((Object)(object)item == (Object)null)) { if (_verbose != null && _verbose.Value) { Log.LogInfo((object)("LIGHTING " + ((Object)((Component)item).gameObject).name + " was reflProbe=" + ((object)item.reflectionProbeUsage/*cast due to .constrained prefix*/).ToString() + " lightProbe=" + ((object)item.lightProbeUsage/*cast due to .constrained prefix*/).ToString() + " shadows=" + ((object)item.shadowCastingMode/*cast due to .constrained prefix*/).ToString() + " receive=" + item.receiveShadows + " -> island has reflProbe=" + ((object)islandLand.reflectionProbeUsage/*cast due to .constrained prefix*/).ToString() + " lightProbe=" + ((object)islandLand.lightProbeUsage/*cast due to .constrained prefix*/).ToString() + " shadows=" + ((object)islandLand.shadowCastingMode/*cast due to .constrained prefix*/).ToString() + " receive=" + islandLand.receiveShadows + " lightmapIndex=" + islandLand.lightmapIndex)); } item.reflectionProbeUsage = islandLand.reflectionProbeUsage; item.lightProbeUsage = islandLand.lightProbeUsage; item.shadowCastingMode = islandLand.shadowCastingMode; item.receiveShadows = islandLand.receiveShadows; item.allowOcclusionWhenDynamic = islandLand.allowOcclusionWhenDynamic; if ((Object)(object)islandLand.probeAnchor != (Object)null) { item.probeAnchor = islandLand.probeAnchor; } } } Log.LogInfo((object)("Sculpted ground now lit like the island (" + sculpted.Count + " renderer(s)).")); } private static Material Match(Dictionary<string, Material> byName, string raw) { string text = raw.Replace(" (Instance)", "").Trim(); if (byName.TryGetValue(text, out var value)) { return value; } int num = text.LastIndexOf('_'); if (num > 0) { string text2 = text.Substring(num + 1); bool flag = text2.Length > 0; string text3 = text2; foreach (char c in text3) { if (c < '0' || c > '9') { flag = false; break; } } if (flag && byName.TryGetValue(text.Substring(0, num), out value)) { return value; } } return null; } private static void DumpLandMaterial(Material real) { //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) if (_dumped || (Object)(object)real == (Object)null) { return; } _dumped = true; Log.LogInfo((object)("LAND MATERIAL " + ((Object)real).name + " shader=" + (((Object)(object)real.shader == (Object)null) ? "?" : ((Object)real.shader).name))); string[] array = new string[4] { "_Colors", "_Normal_Map", "_BaseMap", "_MainTex" }; foreach (string text in array) { if (!real.HasProperty(text)) { Log.LogInfo((object)(" " + text + ": not on shader")); continue; } Texture texture = real.GetTexture(text); Log.LogInfo((object)(" " + text + " = " + (((Object)(object)texture == (Object)null) ? "none" : (((Object)texture).name + " " + texture.width + "x" + texture.height + " " + ((object)texture).GetType().Name)))); } array = new string[10] { "_Normal_Strength", "_Normal_Scale", "_Emission", "_SSAO_Step", "_Smoothness", "_Glossiness", "_Metallic", "_SpecularHighlights", "_EnvironmentReflections", "_GlossyReflections" }; foreach (string text2 in array) { if (real.HasProperty(text2)) { Log.LogInfo((object)(" " + text2 + " = " + real.GetFloat(text2))); } } Log.LogInfo((object)(" keywords: " + string.Join(" ", real.shaderKeywords))); Log.LogInfo((object)(" renderQueue = " + real.renderQueue)); Texture val = (real.HasProperty("_Colors") ? real.GetTexture("_Colors") : null); if ((Object)(object)val == (Object)null) { Log.LogInfo((object)" palette: no _Colors texture"); return; } Texture2D val2 = null; try { val2 = ReadableCopy(val); } catch (Exception ex) { Log.LogInfo((object)(" palette: copy failed " + ex.Message)); return; } if ((Object)(object)val2 == (Object)null) { return; } Log.LogInfo((object)(" PALETTE " + ((Texture)val2).width + "x" + ((Texture)val2).height + " (row 0 = v 0, the bottom)")); for (int num = ((Texture)val2).height - 1; num >= 0; num--) { string text3 = ""; for (int j = 0; j < ((Texture)val2).width; j++) { Color pixel = val2.GetPixel(j, num); text3 += $"{Mathf.RoundToInt(pixel.r * 255f):x2}{Mathf.RoundToInt(pixel.g * 255f):x2}{Mathf.RoundToInt(pixel.b * 255f):x2} "; } Log.LogInfo((object)$" v{num,2} {text3}"); } KeyValuePair<string, Vector2>[] array2 = new KeyValuePair<string, Vector2>[4] { new KeyValuePair<string, Vector2>("island rock (from its mesh)", new Vector2(0.9844f, 0.6699f)), new KeyValuePair<string, Vector2>("our rock ", new Vector2(0.9844f, 0.6719f)), new KeyValuePair<string, Vector2>("our sand ", new Vector2(0.9844f, 0.4531f)), new KeyValuePair<string, Vector2>("our seabed", new Vector2(0.3281f, 0.2031f)) }; for (int i = 0; i < array2.Length; i++) { KeyValuePair<string, Vector2> keyValuePair = array2[i]; string text4; try { Color pixelBilinear = val2.GetPixelBilinear(keyValuePair.Value.x, keyValuePair.Value.y); text4 = "rgb(" + Mathf.RoundToInt(pixelBilinear.r * 255f) + "," + Mathf.RoundToInt(pixelBilinear.g * 255f) + "," + Mathf.RoundToInt(pixelBilinear.b * 255f) + ")"; } catch (Exception ex2) { text4 = "unreadable: " + ex2.GetType().Name; } ManualLogSource log = Log; string[] obj = new string[6] { " palette at ", keyValuePair.Key, " ", null, null, null }; Vector2 value = keyValuePair.Value; obj[3] = ((Vector2)(ref value)).ToString("0.0000"); obj[4] = " -> "; obj[5] = text4; log.LogInfo((object)string.Concat(obj)); } } private static void ReportWhatSharesTheGround(Scene scene, List<Renderer> sculpted) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) if (sculpted.Count == 0) { Log.LogInfo((object)"OVERLAP: no sculpted terrain found."); return; } Renderer val = sculpted[0]; if ((Object)(object)val == (Object)null) { return; } Bounds bounds = val.bounds; ManualLogSource log = Log; string[] obj = new string[6] { "OVERLAP terrain ", ((Object)((Component)val).gameObject).name, " centre=", null, null, null }; Vector3 val2 = ((Bounds)(ref bounds)).center; obj[3] = ((Vector3)(ref val2)).ToString("0.0"); obj[4] = " size="; val2 = ((Bounds)(ref bounds)).size; obj[5] = ((Vector3)(ref val2)).ToString("0.0"); log.LogInfo((object)string.Concat(obj)); int num = 0; List<GameObject> list = new List<GameObject>(); for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (((Scene)(ref sceneAt)).isLoaded) { Log.LogInfo((object)(" [scene " + ((Scene)(ref sceneAt)).name + "]")); list.AddRange(((Scene)(ref sceneAt)).GetRootGameObjects()); } } foreach (GameObject item in list) { Renderer[] componentsInChildren = item.GetComponentsInChildren<Renderer>(false); foreach (Renderer val3 in componentsInChildren) { if ((Object)(object)val3 == (Object)null || (Object)(object)val3 == (Object)(object)val || !val3.enabled || !((Component)val3).gameObject.activeInHierarchy) { continue; } Bounds bounds2 = val3.bounds; if (!((Bounds)(ref bounds2)).Intersects(bounds)) { continue; } Bounds bounds3 = val3.bounds; if (!(((Bounds)(ref bounds3)).size.x < 3f) || !(((Bounds)(ref bounds3)).size.z < 3f)) { Material sharedMaterial = val3.sharedMaterial; ManualLogSource log2 = Log; string[] obj2 = new string[16] { " [", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; Scene scene2 = ((Component)val3).gameObject.scene; obj2[1] = ((Scene)(ref scene2)).name; obj2[2] = "] "; obj2[3] = ((Object)((Component)val3).gameObject).name; obj2[4] = " mat="; obj2[5] = (((Object)(object)sharedMaterial == (Object)null) ? "none" : ((Object)sharedMaterial).name); obj2[6] = " shader="; obj2[7] = (((Object)(object)sharedMaterial == (Object)null || (Object)(object)sharedMaterial.shader == (Object)null) ? "?" : ((Object)sharedMaterial.shader).name); obj2[8] = " queue="; obj2[9] = (((Object)(object)sharedMaterial == (Object)null) ? (-1) : sharedMaterial.renderQueue).ToString(); obj2[10] = " y "; val2 = ((Bounds)(ref bounds3)).min; obj2[11] = val2.y.ToString("0.0"); obj2[12] = " to "; val2 = ((Bounds)(ref bounds3)).max; obj2[13] = val2.y.ToString("0.0"); obj2[14] = " size="; val2 = ((Bounds)(ref bounds3)).size; obj2[15] = ((Vector3)(ref val2)).ToString("0.0"); log2.LogInfo((object)string.Concat(obj2)); if (++num >= 40) { Log.LogInfo((object)" ...more not listed"); return; } } } } if (num == 0) { Log.LogInfo((object)" nothing else overlaps the terrain."); } } private static Texture2D ReadableCopy(Texture src) { //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_0054: 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_0073: Expected O, but got Unknown RenderTexture temporary = RenderTexture.GetTemporary(src.width, src.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); Graphics.Blit(src, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(src.width, src.height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)src.width, (float)src.height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); return val; } private static void PaintItPink(List<Renderer> sculpted) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0066: 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) if (_paintItPink == null || !_paintItPink.Value) { return; } Shader val = Shader.Find("Universal Render Pipeline/Unlit"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Unlit/Color"); } if ((Object)(object)val == (Object)null) { Log.LogWarning((object)"No unlit shader to highlight with."); return; } Material val2 = new Material(val); if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", Color.magenta); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", Color.magenta); } int num = 0; foreach (Renderer item in sculpted) { if (!((Object)(object)item == (Object)null)) { Material[] array = (Material[])(object)new Material[item.sharedMaterials.Length]; for (int i = 0; i < array.Length; i++) { array[i] = val2; } item.sharedMaterials = array; num++; } } Log.LogInfo((object)("HIGHLIGHT: " + num + " sculpted renderer(s) painted magenta. Anything on screen that is NOT magenta is not the map's terrain.")); } private static IEnumerable<object> CloseTheBorrowedIsland(Scene src, Scene ours) { //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_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) if (!((Scene)(ref src)).IsValid() || !((Scene)(ref src)).isLoaded) { yield break; } if (src == ours || ((Scene)(ref src)).path == ((Scene)(ref ours)).path) { Log.LogWarning((object)("Refusing to close " + ((Scene)(ref src)).name + " - that is the map's own scene.")); yield break; } int destroyed = 0; GameObject[] rootGameObjects = ((Scene)(ref src)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if (!((Object)(object)val == (Object)null)) { Object.Destroy((Object)(object)val); destroyed++; } } yield return null; AsyncOperation unload = SceneManager.UnloadSceneAsync(src); if (unload == null) { Log.LogWarning((object)("Unity would not unload " + ((Scene)(ref src)).name + ", but its " + destroyed + " root object(s) have been destroyed, so nothing from it is left in the world.")); } else { while (!unload.isDone) { yield return null; } } } private static void EvictLeftoverIslands(Scene ours) { //IL_000e: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) for (int num = SceneManager.sceneCount - 1; num >= 0; num--) { Scene sceneAt = SceneManager.GetSceneAt(num); if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded && !(sceneAt == ours) && !(((Scene)(ref sceneAt)).path == ((Scene)(ref ours)).path) && ((Scene)(ref sceneAt)).buildIndex > 0 && ((Scene)(ref sceneAt)).buildIndex <= 6) { int num2 = 0; GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if (!((Object)(object)val == (Object)null)) { Object.Destroy((Object)(object)val); num2++; } } Log.LogInfo((object)("Evicted the leftover island scene " + ((Scene)(ref sceneAt)).name + " (build index " + ((Scene)(ref sceneAt)).buildIndex + ") - " + num2 + " root object(s) destroyed. It was standing in the same place as your map.")); if (SceneManager.UnloadSceneAsync(sceneAt) == null) { Log.LogWarning((object)("Unity would not unload " + ((Scene)(ref sceneAt)).name + ", but it is empty now, so nothing from it is left in the world.")); } } } } private static bool GiveItItsShaderBack(Material m, Dictionary<string, Material> byName) { if ((Object)(object)m == (Object)null || (Object)(object)m.shader == (Object)null) { return false; } if (!((Object)m.shader).name.StartsWith("Universal Render Pipeline/")) { return false; } string text = null; string name = ((Object)m).name; if (name.StartsWith("WindyGrass")) { text = "Shader Graphs/Grass"; } else if (name.StartsWith("WindyDecoration")) { text = "Shader Graphs/WindyDecorations"; } else if (name.StartsWith("Windy")) { text = "Shader Graphs/WindyDefault"; } else if (name.Contains("Particle") || name.Contains("Explosion")) { text = "Universal Render Pipeline/Particles/Lit"; } if (text == null) { return false; } Shader val = FindLoadedShader(text); if ((Object)(object)val == (Object)null) { Log.LogWarning((object)("Wanted " + text + " for " + name + " but the game has not got it loaded, so those will not move.")); return false; } m.shader = val; Texture val2 = PaletteFrom(byName); if ((Object)(object)val2 != (Object)null) { string[] array = new string[4] { "_Colors", "_Texture", "_BaseMap", "_MainTex" }; foreach (string text2 in array) { if (m.HasProperty(text2) && (Object)(object)m.GetTexture(text2) == (Object)null) { m.SetTexture(text2, val2); } } } return true; } private static Texture PaletteFrom(Dictionary<string, Material> byName) { string[] array = new string[3] { "Level", "Default", "LevelTesting" }; foreach (string key in array) { if (byName.TryGetValue(key, out var value) && !((Object)(object)value == (Object)null) && LooksLikeTheGames(value) && value.HasProperty("_Colors")) { Texture texture = value.GetTexture("_Colors"); if ((Object)(object)texture != (Object)null) { return texture; } } } Material[] array2 = Resources.FindObjectsOfTypeAll<Material>(); foreach (Material val in array2) { if (!((Object)(object)val == (Object)null) && LooksLikeTheGames(val) && val.HasProperty("_Colors")) { Texture texture2 = val.GetTexture("_Colors"); if ((Object)(object)texture2 != (Object)null && texture2.width == 32 && texture2.height == 32) { return texture2; } } } return null; } private static Shader FindLoadedShader(string name) { Shader val = Shader.Find(name); if ((Object)(object)val != (Object)null) { return val; } Shader[] array = Resources.FindObjectsOfTypeAll<Shader>(); foreach (Shader val2 in array) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == name) { return val2; } } return null; } p