using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("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; } } } namespace HTFMapLoader { [BepInPlugin("com.howtofish.maploader", "HTF Map Loader", "0.2.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [Serializable] public sealed class MapManifest { public string id; public string name; public string author; public string bundle; public string scene; public string positionMode; public SerializableVector3 position = new SerializableVector3(); public bool moveScene = true; public string radarColor = ""; public float islandSize = 55f; public RuntimeManifest runtime = new RuntimeManifest(); public WildlifeManifest wildlife = new WildlifeManifest(); } [Serializable] public sealed class SerializableVector3 { public float x; public float y; public float z; public Vector3 ToVector3() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(x, y, z); } } [Serializable] public sealed class RuntimeManifest { public string playerSpawn = "PlayerSpawnPoint"; public string boatSpawn = "BoatSpawnPoint"; public SerializableVector3 defaultPlayerSpawn = new SerializableVector3 { x = 0f, y = 6f, z = 0f }; public SerializableVector3 defaultBoatSpawn = new SerializableVector3 { x = 0f, y = 0.5f, z = -25f }; } [Serializable] public sealed class WildlifeManifest { public bool seagulls; public bool clams; public int seagullMax = 3; public float seagullDelay = 60f; public int clamMax = 3; public float clamDelay = 15f; } private sealed class RegisteredMap { public MapManifest Manifest; public string Folder; public string BundlePath; public string SceneName; public string ScenePath; public Vector3 Position; public Color RadarColor; public byte LogicalIndex; public AssetBundle Bundle; public object MapDot; public override string ToString() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) return (Manifest?.name ?? Manifest?.id ?? "Map") + " " + $"index={LogicalIndex} scene='{SceneName}' pos={Position}"; } } public const string Guid = "com.howtofish.maploader"; public const string Name = "HTF Map Loader"; public const string Version = "0.2.8"; internal static Plugin Instance; internal static ManualLogSource Log; private Harmony _harmony; private ConfigEntry _enabled; private ConfigEntry _verbose; private ConfigEntry _repairRuntime; private ConfigEntry _enableMapWildlife; private readonly List _maps = new List(); private readonly Dictionary _mapsByIndex = new Dictionary(); private bool _scanned; private bool _registered; private bool _loggedDisabled; private bool _verifiedRegisteredTriggers; private float _managerFirstSeenTime = -1f; private bool _bypassQueuePatch; private bool _transitioning; private RegisteredMap _loadingMap; private RegisteredMap _currentMap; private object _radarUi; private MethodInfo _radarUpdateDotMethod; private float _nextRadarAcquire; private int _nativeGroundLayer = -1; private PhysicsMaterial _nativeGroundMaterial; private string LegacyMapsRoot => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Maps"); private string PluginsRoot => Paths.PluginPath; private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; _enabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enable HTF Map Loader."); _repairRuntime = ((BaseUnityPlugin)this).Config.Bind("General", "RepairMissingRuntimeObjects", true, "Automatically repair common Island/SpawnManager/Level setup when a map is missing it."); _enableMapWildlife = ((BaseUnityPlugin)this).Config.Bind("General", "AllowMapWildlifeOptions", true, "Allow map.json to request optional built-in Seagull and Clam spawners."); _verbose = ((BaseUnityPlugin)this).Config.Bind("Debug", "VerboseLogging", false, "Enable verbose Map Loader logging."); Directory.CreateDirectory(LegacyMapsRoot); SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; PatchQueueRequest(); PatchNativeIslandSpawnerTrigger(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"HTF Map Loader v0.2.8 loaded."); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Enabled={_enabled.Value}, RepairRuntime={_repairRuntime.Value}, WildlifeOptions={_enableMapWildlife.Value}"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Legacy maps directory: " + LegacyMapsRoot)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Thunderstore plugin root: " + PluginsRoot)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Map packs are discovered recursively from BepInEx/plugins/**/Maps/**/map.json."); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.sceneUnloaded -= OnSceneUnloaded; Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } foreach (RegisteredMap map in _maps) { try { if ((Object)(object)map.Bundle != (Object)null) { map.Bundle.Unload(false); } } catch { } } } private void Update() { if (!_enabled.Value) { if (!_loggedDisabled) { _loggedDisabled = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GENERAL] HTF Map Loader is disabled by config: [General] Enabled=false."); } return; } _loggedDisabled = false; if (!_scanned) { ScanMapFolders(); _scanned = true; } if (!_registered && _maps.Count > 0) { TryRegisterMaps(); } if (_registered && !_verifiedRegisteredTriggers && IsGameplayWorldReady()) { VerifyRegisteredNavigationTriggers(); _verifiedRegisteredTriggers = true; } if (_registered && IsGameplayWorldReady()) { UpdateRadar(); } } private void ScanMapFolders() { //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) _maps.Clear(); string[] array = DiscoverMapManifests(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[MAPS] Found {array.Length} map.json file(s) across installed plugin packages."); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); int num = 0; string[] array2 = array; foreach (string text in array2) { try { string text2 = File.ReadAllText(text); MapManifest mapManifest = JsonUtility.FromJson(text2); ApplyExplicitVectorOverrides(mapManifest, text2, text); if (!ValidateManifest(mapManifest, text)) { continue; } if (!hashSet.Add(mapManifest.id.Trim())) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] Duplicate map id '" + mapManifest.id + "'. Skipping " + text + ".")); continue; } string directoryName = Path.GetDirectoryName(text); string text3 = mapManifest.bundle.Trim(); string text4 = Path.Combine(directoryName, text3); if (!File.Exists(text4)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] '" + mapManifest.id + "' bundle does not exist: " + text4)); continue; } RegisteredMap item = new RegisteredMap { Manifest = mapManifest, Folder = directoryName, BundlePath = text4, SceneName = ((mapManifest.scene != null) ? mapManifest.scene.Trim() : ""), Position = ResolveMapPosition(mapManifest, num), RadarColor = ResolveRadarColor(mapManifest, num) }; _maps.Add(item); num++; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[MAPS] Discovered '" + (mapManifest.name ?? mapManifest.id) + "' bundle='" + text3 + "'.")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[MAPS] Failed reading '" + text + "': " + ex.Message)); } } } private string[] DiscoverMapManifests() { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); AddMapManifestsFromMapsRoot(LegacyMapsRoot, hashSet); try { if (Directory.Exists(PluginsRoot)) { foreach (string item in EnumerateDirectoriesSafe(PluginsRoot, "Maps")) { AddMapManifestsFromMapsRoot(item, hashSet); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] Failed scanning plugin packages: " + ex.Message)); } return hashSet.OrderBy((string p) => p, StringComparer.OrdinalIgnoreCase).ToArray(); } private void AddMapManifestsFromMapsRoot(string mapsRoot, HashSet results) { if (string.IsNullOrWhiteSpace(mapsRoot) || results == null || !Directory.Exists(mapsRoot)) { return; } try { string[] files = Directory.GetFiles(mapsRoot, "map.json", SearchOption.AllDirectories); foreach (string text in files) { try { results.Add(Path.GetFullPath(text)); } catch { results.Add(text); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] Could not scan '" + mapsRoot + "': " + ex.Message)); } } private IEnumerable EnumerateDirectoriesSafe(string root, string wantedName) { Stack pending = new Stack(); pending.Push(root); while (pending.Count > 0) { string path = pending.Pop(); string[] directories; try { directories = Directory.GetDirectories(path); } catch { continue; } string[] array = directories; foreach (string text in array) { string fileName; try { fileName = Path.GetFileName(text.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)); } catch { continue; } if (string.Equals(fileName, wantedName, StringComparison.OrdinalIgnoreCase)) { yield return text; } else { pending.Push(text); } } } } private void ApplyExplicitVectorOverrides(MapManifest manifest, string json, string manifestPath) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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) if (manifest == null || string.IsNullOrWhiteSpace(json)) { return; } if (TryReadVector3Object(json, "position", out var value)) { manifest.position = value; } if (manifest.runtime == null) { manifest.runtime = new RuntimeManifest(); } if (TryReadObjectBody(json, "runtime", out var body)) { if (TryReadVector3Object(body, "defaultPlayerSpawn", out value)) { manifest.runtime.defaultPlayerSpawn = value; } if (TryReadVector3Object(body, "defaultBoatSpawn", out value)) { manifest.runtime.defaultBoatSpawn = value; } } if (_verbose != null && _verbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[JSON] Parsed vectors from '" + manifestPath + "': " + $"position={manifest.position?.ToVector3()}, " + $"defaultPlayerSpawn={manifest.runtime?.defaultPlayerSpawn?.ToVector3()}, " + $"defaultBoatSpawn={manifest.runtime?.defaultBoatSpawn?.ToVector3()}.")); } } private static bool TryReadVector3Object(string json, string propertyName, out SerializableVector3 value) { value = null; if (!TryReadObjectBody(json, propertyName, out var body)) { return false; } if (!TryReadFloatProperty(body, "x", out var value2) || !TryReadFloatProperty(body, "y", out var value3) || !TryReadFloatProperty(body, "z", out var value4)) { return false; } value = new SerializableVector3 { x = value2, y = value3, z = value4 }; return true; } private static bool TryReadObjectBody(string json, string propertyName, out string body) { body = null; if (string.IsNullOrWhiteSpace(json) || string.IsNullOrWhiteSpace(propertyName)) { return false; } Match match = Regex.Match(json, "\"" + Regex.Escape(propertyName) + "\"\\s*:\\s*\\{", RegexOptions.IgnoreCase); if (!match.Success) { return false; } int num = json.IndexOf('{', match.Index); if (num < 0) { return false; } int num2 = 0; bool flag = false; bool flag2 = false; for (int i = num; i < json.Length; i++) { char c = json[i]; if (flag) { if (flag2) { flag2 = false; continue; } switch (c) { case '\\': flag2 = true; break; case '"': flag = false; break; } continue; } switch (c) { case '"': flag = true; break; case '{': num2++; break; case '}': num2--; if (num2 == 0) { body = json.Substring(num + 1, i - num - 1); return true; } break; } } return false; } private static bool TryReadFloatProperty(string objectBody, string propertyName, out float value) { value = 0f; if (string.IsNullOrWhiteSpace(objectBody)) { return false; } Match match = Regex.Match(objectBody, "\"" + Regex.Escape(propertyName) + "\"\\s*:\\s*([-+]?(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][-+]?\\d+)?)", RegexOptions.IgnoreCase); if (!match.Success) { return false; } return float.TryParse(match.Groups[1].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out value); } private bool ValidateManifest(MapManifest manifest, string manifestPath) { if (manifest == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] Invalid JSON manifest: " + manifestPath + ".")); return false; } List list = new List(); if (string.IsNullOrWhiteSpace(manifest.id)) { list.Add("id"); } if (string.IsNullOrWhiteSpace(manifest.name)) { list.Add("name"); } if (string.IsNullOrWhiteSpace(manifest.author)) { list.Add("author"); } if (string.IsNullOrWhiteSpace(manifest.bundle)) { list.Add("bundle"); } if (string.IsNullOrWhiteSpace(manifest.scene)) { list.Add("scene"); } if (string.IsNullOrWhiteSpace(manifest.positionMode)) { list.Add("positionMode"); } if (list.Count > 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] '" + manifestPath + "' is missing required field(s): " + string.Join(", ", list) + ". See MAP_JSON_REFERENCE.md.")); return false; } string a = manifest.positionMode.Trim(); if (!string.Equals(a, "auto", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "manual", StringComparison.OrdinalIgnoreCase)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] '" + manifest.id + "' has invalid positionMode='" + manifest.positionMode + "'. Use 'auto' or 'manual'.")); return false; } if (string.Equals(a, "manual", StringComparison.OrdinalIgnoreCase) && manifest.position == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] '" + manifest.id + "' uses manual positioning but has no position object.")); return false; } Color val = default(Color); if (!string.IsNullOrWhiteSpace(manifest.radarColor) && !ColorUtility.TryParseHtmlString(manifest.radarColor.Trim(), ref val)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] '" + manifest.id + "' has invalid radarColor='" + manifest.radarColor + "'. Use a hex color like #20DFFF.")); return false; } if (manifest.runtime == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] '" + manifest.id + "' is missing runtime. Include the runtime object even if you keep the default marker names.")); return false; } if (manifest.wildlife == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[MAPS] '" + manifest.id + "' is missing wildlife. Include the wildlife object and set seagulls/clams explicitly.")); return false; } return true; } private Vector3 ResolveMapPosition(MapManifest manifest, int order) { //IL_006b: 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_001e: Unknown result type (might be due to invalid IL or missing references) if (manifest != null && string.Equals(manifest.positionMode, "manual", StringComparison.OrdinalIgnoreCase)) { if (manifest.position == null) { return Vector3.zero; } return manifest.position.ToVector3(); } int num = order / 8; int num2 = order % 8; float num3 = 650f + (float)num * 450f; float num4 = MathF.PI / 4f * (float)num2 + MathF.PI / 8f; return new Vector3(Mathf.Cos(num4) * num3, 0f, Mathf.Sin(num4) * num3); } private Color ResolveRadarColor(MapManifest manifest, int order) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00ae: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_0104: 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) Color result = default(Color); if (manifest != null && !string.IsNullOrWhiteSpace(manifest.radarColor) && ColorUtility.TryParseHtmlString(manifest.radarColor.Trim(), ref result)) { result.a = 1f; return result; } Color[] array = (Color[])(object)new Color[6] { new Color(0.15f, 0.85f, 1f, 1f), new Color(0.75f, 0.35f, 1f, 1f), new Color(1f, 0.35f, 0.75f, 1f), new Color(0.3f, 1f, 0.65f, 1f), new Color(0.45f, 0.65f, 1f, 1f), new Color(1f, 0.8f, 0.25f, 1f) }; return array[Math.Abs(order) % array.Length]; } private void TryRegisterMaps() { //IL_0258: Unknown result type (might be due to invalid IL or missing references) object obj = FindLiveObjectByTypeName("IslandManager"); if (obj == null) { return; } FieldInfo fieldInfo = FindField(obj.GetType(), "_islandInfos"); Array array = ((fieldInfo != null) ? (fieldInfo.GetValue(obj) as Array) : null); if (array == null || array.Length < 5) { return; } if (_managerFirstSeenTime < 0f) { _managerFirstSeenTime = Time.unscaledTime; } else { if (Time.unscaledTime - _managerFirstSeenTime < 1.5f) { return; } try { CacheNativeGroundCollision(); int length = array.Length; object value = array.GetValue(Math.Min(4, array.Length - 1)); if (value == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[REGISTER] No IslandInfo template available."); return; } Type type = value.GetType(); FieldInfo fieldInfo2 = FindField(type, "_spawnPosition"); FieldInfo fieldInfo3 = FindField(type, "_warning"); object? obj2 = fieldInfo2?.GetValue(value); GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null); object? obj3 = fieldInfo3?.GetValue(value); GameObject sourceWarning = (GameObject)((obj3 is GameObject) ? obj3 : null); if (fieldInfo2 == null || fieldInfo3 == null || (Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[REGISTER] Native IslandInfo trigger template is incomplete."); return; } ResolveNonConflictingMapPositions(array, fieldInfo2); int length2 = array.Length + _maps.Count; Array array2 = Array.CreateInstance(type, length2); Array.Copy(array, array2, array.Length); for (int i = 0; i < _maps.Count; i++) { RegisteredMap registeredMap = _maps[i]; int num = length + i; if (num > 255) { ((BaseUnityPlugin)this).Logger.LogError((object)"[REGISTER] Too many maps for byte island indexes."); break; } registeredMap.LogicalIndex = (byte)num; object obj4 = CreateIslandInfoForMap(registeredMap, type, val, sourceWarning, fieldInfo2, fieldInfo3); if (obj4 != null) { array2.SetValue(obj4, num); _mapsByIndex[registeredMap.LogicalIndex] = registeredMap; ((BaseUnityPlugin)this).Logger.LogWarning((object)("[REGISTER] " + registeredMap.Manifest.name + " " + $"index={registeredMap.LogicalIndex} " + "scene='" + registeredMap.Manifest.scene + "' " + $"pos={registeredMap.Position} " + "bundle='" + registeredMap.Manifest.bundle + "' radar=" + registeredMap.Manifest.radarColor)); } } fieldInfo.SetValue(obj, array2); _registered = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)($"[REGISTER] Added {_mapsByIndex.Count} custom map(s). " + $"IslandInfo {array.Length} -> {array2.Length}.")); ResetRadarReferences(); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[REGISTER] Failed: {arg}"); } } } private void ResolveNonConflictingMapPositions(Array existingInfos, FieldInfo spawnField) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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: 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_0025: 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) List list = new List(); if (existingInfos != null) { for (int i = 0; i < existingInfos.Length; i++) { object value = existingInfos.GetValue(i); if (value != null && TryGetIslandInfoPosition(value, spawnField, out var position)) { list.Add(position); if (_verbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[PLACEMENT] Existing island index={i} pos={position}."); } } } } for (int j = 0; j < _maps.Count; j++) { RegisteredMap registeredMap = _maps[j]; Vector3 position2 = registeredMap.Position; if (!FindPositionConflict(position2, list, 550f, out var conflictingPosition)) { list.Add(position2); continue; } Vector3 val = FindFreeNavigationPosition(list, j, 550f); ((BaseUnityPlugin)this).Logger.LogWarning((object)($"[PLACEMENT] '{registeredMap.Manifest.id}' requested {position2}, but that " + $"position conflicts with an existing island at {conflictingPosition}. " + $"Automatically moved navigation/radar position to {val}.")); registeredMap.Position = val; list.Add(val); } } private bool TryGetIslandInfoPosition(object info, FieldInfo fallbackSpawnField, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if (info == null) { return false; } try { PropertyInfo property = info.GetType().GetProperty("IslandPosition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(Vector3) && property.CanRead) { position = (Vector3)property.GetValue(info, null); return true; } } catch { } try { object? obj2 = (fallbackSpawnField ?? FindField(info.GetType(), "_spawnPosition"))?.GetValue(info); GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)val != (Object)null) { position = val.transform.position; return true; } } catch { } return false; } private static bool FindPositionConflict(Vector3 candidate, IEnumerable occupied, float minimumSpacing, out Vector3 conflictingPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_004a: Unknown result type (might be due to invalid IL or missing references) conflictingPosition = Vector3.zero; Vector2 val2 = default(Vector2); foreach (Vector3 item in occupied) { Vector2 val = new Vector2(candidate.x, candidate.z); ((Vector2)(ref val2))..ctor(item.x, item.z); if (Vector2.Distance(val, val2) < minimumSpacing) { conflictingPosition = item; return true; } } return false; } private Vector3 FindFreeNavigationPosition(IEnumerable occupied, int mapOrder, float minimumSpacing) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) List occupied2 = occupied.ToList(); Vector3 val = default(Vector3); for (int i = 0; i < 64; i++) { float num = 1250f + (float)i * 450f; for (int j = 0; j < 12; j++) { int num2 = (j + mapOrder * 3) % 12; float num3 = MathF.PI / 6f * (float)num2 + MathF.PI / 12f; ((Vector3)(ref val))..ctor(Mathf.Cos(num3) * num, 0f, Mathf.Sin(num3) * num); if (!FindPositionConflict(val, occupied2, minimumSpacing, out var _)) { return val; } } } return new Vector3(2500f + (float)mapOrder * 650f, 0f, 2500f); } private object CreateIslandInfoForMap(RegisteredMap map, Type infoType, GameObject sourceSpawn, GameObject sourceWarning, FieldInfo spawnField, FieldInfo warningField) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00bf: Unknown result type (might be due to invalid IL or missing references) Transform parent = sourceSpawn.transform.parent; GameObject val = (GameObject)(((Object)(object)parent != (Object)null) ? ((object)Object.Instantiate(((Component)parent).gameObject)) : ((object)new GameObject("HTFML_Trigger_" + map.Manifest.id))); ((Object)val).name = "HTFML_IslandPositionHolder_" + map.Manifest.id; Transform val2 = FindChildRecursive(val.transform, ((Object)sourceSpawn).name); if ((Object)(object)val2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[REGISTER] '" + map.Manifest.id + "': cloned spawn not found.")); Object.Destroy((Object)(object)val); return null; } Vector3 val3 = map.Position - val2.position; Transform transform = val.transform; transform.position += val3; GameObject gameObject = ((Component)val2).gameObject; ((Object)gameObject).name = "HTFML_IslandPosition_" + map.Manifest.id; GameObject val4 = null; if ((Object)(object)sourceWarning != (Object)null) { Transform val5 = FindChildRecursive(val.transform, ((Object)sourceWarning).name); if ((Object)(object)val5 != (Object)null) { val4 = ((Component)val5).gameObject; ((Object)val4).name = "HTFML_IslandWarning_" + map.Manifest.id; } } Type type = AccessTools.TypeByName("IslandSpawner"); Component val6 = ((type != null) ? gameObject.GetComponent(type) : null); FieldInfo fieldInfo = (((Object)(object)val6 != (Object)null) ? FindField(((object)val6).GetType(), "_islandIndex") : null); if ((Object)(object)val6 == (Object)null || fieldInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[REGISTER] '" + map.Manifest.id + "': IslandSpawner/index missing.")); Object.Destroy((Object)(object)val); return null; } fieldInfo.SetValue(val6, Convert.ChangeType(map.LogicalIndex, fieldInfo.FieldType)); object obj = Activator.CreateInstance(infoType, nonPublic: true); spawnField.SetValue(obj, gameObject); warningField.SetValue(obj, val4); val.SetActive(true); gameObject.SetActive(true); RepairClonedTriggerGeometry(((Object)(object)parent != (Object)null) ? ((Component)parent).gameObject : null, val); DumpRegisteredNavigationTrigger(map, val, gameObject, val6); return obj; } private void RepairClonedTriggerGeometry(GameObject sourceHolder, GameObject clonedHolder) { //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00ea: 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) if ((Object)(object)sourceHolder == (Object)null || (Object)(object)clonedHolder == (Object)null) { return; } Collider[] componentsInChildren = sourceHolder.GetComponentsInChildren(true); Collider[] componentsInChildren2 = clonedHolder.GetComponentsInChildren(true); int num = Math.Min(componentsInChildren.Length, componentsInChildren2.Length); for (int i = 0; i < num; i++) { Collider val = componentsInChildren[i]; Collider val2 = componentsInChildren2[i]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || ((object)val).GetType() != ((object)val2).GetType()) { continue; } bool enabled = val2.enabled; val2.enabled = false; SphereCollider val3 = (SphereCollider)(object)((val is SphereCollider) ? val : null); if (val3 != null) { SphereCollider val4 = (SphereCollider)(object)((val2 is SphereCollider) ? val2 : null); if (val4 != null) { val4.center = val3.center; val4.radius = val3.radius; goto IL_0148; } } BoxCollider val5 = (BoxCollider)(object)((val is BoxCollider) ? val : null); if (val5 != null) { BoxCollider val6 = (BoxCollider)(object)((val2 is BoxCollider) ? val2 : null); if (val6 != null) { val6.center = val5.center; val6.size = val5.size; goto IL_0148; } } CapsuleCollider val7 = (CapsuleCollider)(object)((val is CapsuleCollider) ? val : null); if (val7 != null) { CapsuleCollider val8 = (CapsuleCollider)(object)((val2 is CapsuleCollider) ? val2 : null); if (val8 != null) { val8.center = val7.center; val8.radius = val7.radius; val8.height = val7.height; val8.direction = val7.direction; } } goto IL_0148; IL_0148: Physics.SyncTransforms(); val2.enabled = enabled; } Physics.SyncTransforms(); ((BaseUnityPlugin)this).Logger.LogWarning((object)($"[TRIGGER FIX] Refreshed {num} cloned collider(s) after moving " + $"'{((Object)clonedHolder).name}' to {clonedHolder.transform.position}.")); } private void DumpRegisteredNavigationTrigger(RegisteredMap map, GameObject holder, GameObject spawn, Component spawner) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) if (map == null || (Object)(object)holder == (Object)null || (Object)(object)spawn == (Object)null) { return; } try { Collider[] componentsInChildren = holder.GetComponentsInChildren(true); ManualLogSource logger = ((BaseUnityPlugin)this).Logger; string[] obj = new string[12] { "[TRIGGER DUMP] '", map.Manifest.id, "' holder='", ((Object)holder).name, "' ", $"holderActive={holder.activeInHierarchy} ", $"spawn='{((Object)spawn).name}' spawnActive={spawn.activeInHierarchy} ", $"spawnPos={spawn.transform.position} ", "spawnerEnabled=", null, null, null }; Behaviour val = (Behaviour)(object)((spawner is Behaviour) ? spawner : null); obj[9] = ((val != null) ? val.enabled.ToString() : "n/a"); obj[10] = " "; obj[11] = $"colliders={componentsInChildren.Length}."; logger.LogWarning((object)string.Concat(obj)); Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (!((Object)(object)val2 == (Object)null)) { Rigidbody component = ((Component)val2).GetComponent(); ManualLogSource logger2 = ((BaseUnityPlugin)this).Logger; string[] obj2 = new string[10] { "[TRIGGER DUMP] collider='", ((Object)val2).name, "' ", $"type={((object)val2).GetType().Name} enabled={val2.enabled} ", $"isTrigger={val2.isTrigger} active={((Component)val2).gameObject.activeInHierarchy} ", $"layer={((Component)val2).gameObject.layer} tag='{SafeTag(((Component)val2).gameObject)}' ", null, null, null, null }; Bounds bounds = val2.bounds; object arg = ((Bounds)(ref bounds)).center; bounds = val2.bounds; obj2[6] = $"center={arg} size={((Bounds)(ref bounds)).size} "; obj2[7] = "rb="; obj2[8] = (((Object)(object)component != (Object)null) ? $"kinematic={component.isKinematic}" : "none"); obj2[9] = "."; logger2.LogWarning((object)string.Concat(obj2)); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[TRIGGER DUMP] Failed for '" + map.Manifest.id + "': " + ex.Message)); } } private static string SafeTag(GameObject go) { if ((Object)(object)go == (Object)null) { return ""; } try { return go.tag; } catch { return ""; } } private void PatchNativeIslandSpawnerTrigger() { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("IslandSpawner"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[PATCH] IslandSpawner type not found."); return; } int num = 0; string[] array = new string[2] { "OnTriggerEnter", "OnTriggerStay" }; foreach (string text in array) { MethodInfo method = type.GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Collider) }, null); if (!(method == null)) { _harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "NativeIslandSpawnerTriggerPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[PATCH] IslandSpawner." + text + "(Collider) patched.")); } } if (num == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[PATCH] No IslandSpawner trigger callbacks were found."); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[PATCH] IslandSpawner trigger patch failed: {arg}"); } } private static void NativeIslandSpawnerTriggerPostfix(object __instance, Collider other) { Plugin instance = Instance; if ((Object)(object)instance == (Object)null || !instance._enabled.Value || __instance == null || (Object)(object)other == (Object)null) { return; } FieldInfo fieldInfo = FindField(__instance.GetType(), "_islandIndex"); if (fieldInfo == null) { return; } byte b; try { b = Convert.ToByte(fieldInfo.GetValue(__instance)); } catch { return; } if (!instance._mapsByIndex.TryGetValue(b, out var value)) { return; } ManualLogSource logger = ((BaseUnityPlugin)instance).Logger; string[] obj2 = new string[5] { $"[ISLAND SPAWNER HIT] map='{value.Manifest.id}' index={b} ", "spawner='", null, null, null }; object obj3 = ((__instance is Component) ? __instance : null); object obj4; if (obj3 == null) { obj4 = null; } else { GameObject gameObject = ((Component)obj3).gameObject; obj4 = ((gameObject != null) ? ((Object)gameObject).name : null); } obj2[2] = (string)obj4; obj2[3] = "' "; obj2[4] = $"other='{((Object)other).name}' otherLayer={((Component)other).gameObject.layer}."; logger.LogWarning((object)string.Concat(obj2)); if (instance.IsCustomMapAlreadyActive(value) || instance._transitioning) { return; } if (!IsGameplayBoatOrPlayerCollider(other)) { if (instance._verbose.Value) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("[ISLAND SPAWNER] '" + value.Manifest.id + "' ignored collider '" + ((Object)other).name + "'.")); } return; } object obj5 = FindLiveObjectByTypeName("IslandManager"); if (obj5 == null) { return; } FieldInfo fieldInfo2 = FindField(obj5.GetType(), "_hasQueuedIsland"); try { if (fieldInfo2 != null && fieldInfo2.FieldType == typeof(bool) && (bool)fieldInfo2.GetValue(obj5)) { return; } } catch { } MethodInfo methodInfo = AccessTools.Method(obj5.GetType(), "QueueRequest", new Type[1] { typeof(byte) }, (Type[])null); if (methodInfo == null) { return; } ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[ISLAND SPAWNER] Native trigger reached custom map " + $"'{value.Manifest.id}' index={b} with collider " + $"'{((Object)other).name}'. Forwarding QueueRequest({b}).")); try { methodInfo.Invoke(obj5, new object[1] { b }); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[ISLAND SPAWNER] QueueRequest repair failed: " + ex.Message)); } } private static bool IsGameplayBoatOrPlayerCollider(Collider other) { Transform val = (((Object)(object)other != (Object)null) ? ((Component)other).transform : null); Type type = AccessTools.TypeByName("Boat"); Type type2 = AccessTools.TypeByName("Player"); while ((Object)(object)val != (Object)null) { GameObject gameObject = ((Component)val).gameObject; string text = ((Object)gameObject).name ?? ""; if (string.Equals(text, "MenuBoat", StringComparison.OrdinalIgnoreCase)) { return false; } if (type != null && (Object)(object)gameObject.GetComponent(type) != (Object)null) { return true; } if (type2 != null && (Object)(object)gameObject.GetComponent(type2) != (Object)null) { return true; } if (text.IndexOf("HostBoatCol", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("LocalPlayer", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } val = val.parent; } return false; } private void PatchQueueRequest() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("IslandManager"); MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "QueueRequest", new Type[1] { typeof(byte) }, (Type[])null) : null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[PATCH] IslandManager.QueueRequest(byte) not found."); return; } _harmony = new Harmony("com.howtofish.maploader"); _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "QueueRequestPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[PATCH] IslandManager.QueueRequest(byte) patched."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[PATCH] QueueRequest failed: {arg}"); } } private static bool QueueRequestPrefix(object __instance, byte islandId) { if ((Object)(object)Instance == (Object)null || !Instance._enabled.Value || Instance._bypassQueuePatch) { return true; } if (Instance._mapsByIndex.TryGetValue(islandId, out var value)) { if (Instance.IsCustomMapAlreadyActive(value)) { if (Instance._verbose.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)($"[QUEUE] Ignoring duplicate QueueRequest({islandId}) " + "for already active map '" + value.Manifest.id + "'.")); } return false; } if (!Instance._transitioning) { ((MonoBehaviour)Instance).StartCoroutine(Instance.TransitionToCustomMap(value)); } return false; } if (Instance._currentMap != null) { if (!Instance._transitioning) { ((MonoBehaviour)Instance).StartCoroutine(Instance.LeaveCustomAndQueueNative(__instance, islandId)); } return false; } return true; } private bool IsCustomMapAlreadyActive(RegisteredMap target) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (target == null) { return false; } if (_currentMap != null && _currentMap == target) { Scene sceneByName = SceneManager.GetSceneByName(target.SceneName); if (((Scene)(ref sceneByName)).IsValid() && ((Scene)(ref sceneByName)).isLoaded) { return true; } } if (!string.IsNullOrWhiteSpace(target.SceneName)) { Scene sceneByName2 = SceneManager.GetSceneByName(target.SceneName); if (((Scene)(ref sceneByName2)).IsValid() && ((Scene)(ref sceneByName2)).isLoaded) { _currentMap = target; return true; } } return false; } private IEnumerator TransitionToCustomMap(RegisteredMap target) { if (IsCustomMapAlreadyActive(target)) { yield break; } _transitioning = true; try { if (_currentMap != null) { yield return UnloadMapScene(_currentMap); } if (!EnsureBundleLoaded(target)) { yield break; } CacheNativeGroundCollision(); yield return UnloadAllGameplayIslandsExceptGame(); _loadingMap = target; AsyncOperation load = SceneManager.LoadSceneAsync(target.SceneName, (LoadSceneMode)1); if (load == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[LOAD] LoadSceneAsync('" + target.SceneName + "') returned null.")); _loadingMap = null; yield break; } while (!load.isDone) { yield return null; } _currentMap = target; _loadingMap = null; ((BaseUnityPlugin)this).Logger.LogWarning((object)$"[LOAD] Custom map active: {target}"); } finally { _transitioning = false; } } private IEnumerator LeaveCustomAndQueueNative(object islandManager, byte islandId) { _transitioning = true; if (_currentMap != null) { yield return UnloadMapScene(_currentMap); } _currentMap = null; try { MethodInfo methodInfo = AccessTools.Method(islandManager.GetType(), "QueueRequest", new Type[1] { typeof(byte) }, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[LOAD] Could not forward native QueueRequest."); yield break; } _bypassQueuePatch = true; methodInfo.Invoke(islandManager, new object[1] { islandId }); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[LOAD] Forwarded native QueueRequest({islandId})."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[LOAD] Leaving custom map failed: {arg}"); } finally { _bypassQueuePatch = false; _transitioning = false; } } private IEnumerator UnloadAllGameplayIslandsExceptGame() { List list = new List(); for (int num = SceneManager.sceneCount - 1; num >= 0; num--) { Scene sceneAt = SceneManager.GetSceneAt(num); if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded && !string.Equals(((Scene)(ref sceneAt)).name, "Game", StringComparison.OrdinalIgnoreCase)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[LOAD] Unloading '" + ((Scene)(ref sceneAt)).name + "'.")); AsyncOperation val = SceneManager.UnloadSceneAsync(sceneAt); if (val != null) { list.Add(val); } } } foreach (AsyncOperation op in list) { while (!op.isDone) { yield return null; } } } private IEnumerator UnloadMapScene(RegisteredMap map) { if (map == null || string.IsNullOrWhiteSpace(map.SceneName)) { yield break; } Scene sceneByName = SceneManager.GetSceneByName(map.SceneName); if (!((Scene)(ref sceneByName)).IsValid() || !((Scene)(ref sceneByName)).isLoaded) { yield break; } AsyncOperation op = SceneManager.UnloadSceneAsync(sceneByName); if (op != null) { while (!op.isDone) { yield return null; } } } private bool EnsureBundleLoaded(RegisteredMap map) { if ((Object)(object)map.Bundle != (Object)null && !string.IsNullOrWhiteSpace(map.SceneName)) { return true; } try { map.Bundle = AssetBundle.LoadFromFile(map.BundlePath); if ((Object)(object)map.Bundle == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[BUNDLE] LoadFromFile failed: " + map.BundlePath)); return false; } string[] allScenePaths = map.Bundle.GetAllScenePaths(); if (allScenePaths == null || allScenePaths.Length == 0) { ((BaseUnityPlugin)this).Logger.LogError((object)("[BUNDLE] '" + map.Manifest.id + "' contains no scenes.")); return false; } string requested = map.Manifest.scene ?? ""; string text = null; if (!string.IsNullOrWhiteSpace(requested)) { text = allScenePaths.FirstOrDefault((string p) => string.Equals(Path.GetFileNameWithoutExtension(p), requested, StringComparison.OrdinalIgnoreCase) || string.Equals(p, requested, StringComparison.OrdinalIgnoreCase)); } if (text == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("[BUNDLE] '" + map.Manifest.id + "' requested scene '" + requested + "', but that scene was not found in the bundle.")); ((BaseUnityPlugin)this).Logger.LogError((object)("[BUNDLE] Available scenes: " + string.Join(", ", allScenePaths))); return false; } map.ScenePath = text; map.SceneName = Path.GetFileNameWithoutExtension(text); ((BaseUnityPlugin)this).Logger.LogWarning((object)("[BUNDLE] '" + map.Manifest.id + "' -> scene '" + map.SceneName + "'.")); return true; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[BUNDLE] '{map.Manifest.id}' failed: {arg}"); return false; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded && (string.Equals(((Scene)(ref scene)).name, "Game", StringComparison.OrdinalIgnoreCase) || string.Equals(((Scene)(ref scene)).name, "DevIsland", StringComparison.OrdinalIgnoreCase) || ((Scene)(ref scene)).name.StartsWith("Island", StringComparison.OrdinalIgnoreCase))) { ResetRadarReferences(); } RegisteredMap registeredMap = _maps.FirstOrDefault((RegisteredMap m) => !string.IsNullOrWhiteSpace(m.SceneName) && string.Equals(m.SceneName, ((Scene)(ref scene)).name, StringComparison.OrdinalIgnoreCase)); if (registeredMap != null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[RUNTIME] Preparing custom scene '" + ((Scene)(ref scene)).name + "'.")); PositionMapScene(registeredMap, scene); if (_repairRuntime.Value) { PrepareMapRuntime(registeredMap, scene); } if (_enableMapWildlife.Value) { ApplyOptionalWildlife(registeredMap, scene); } ResetRadarReferences(); } } private void OnSceneUnloaded(Scene scene) { if (_currentMap != null && string.Equals(_currentMap.SceneName, ((Scene)(ref scene)).name, StringComparison.OrdinalIgnoreCase)) { _currentMap = null; } } private void PositionMapScene(RegisteredMap map, Scene scene) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (map == null || !map.Manifest.moveScene) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[RUNTIME] '" + map?.Manifest?.id + "' moveScene=false; scene coordinates preserved.")); return; } GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); GameObject val = ((IEnumerable)rootGameObjects).FirstOrDefault((Func)((GameObject r) => (Object)(object)r != (Object)null && string.Equals(((Object)r).name, "IslandHolder", StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val != (Object)null) { Vector3 position = val.transform.position; val.transform.position = map.Position; ((BaseUnityPlugin)this).Logger.LogWarning((object)($"[RUNTIME] '{map.Manifest.id}' IslandHolder moved {position} -> " + $"{val.transform.position} (requested {map.Position}).")); return; } GameObject[] array = rootGameObjects; foreach (GameObject val2 in array) { if ((Object)(object)val2 != (Object)null) { Transform transform = val2.transform; transform.position += map.Position; } } ((BaseUnityPlugin)this).Logger.LogWarning((object)("[RUNTIME] '" + map.Manifest.id + "' has no IslandHolder; moved " + $"{rootGameObjects.Length} root(s) by {map.Position}.")); } private void PrepareMapRuntime(RegisteredMap map, Scene scene) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) GameObject val = ((IEnumerable)((Scene)(ref scene)).GetRootGameObjects()).FirstOrDefault((Func)((GameObject r) => (Object)(object)r != (Object)null && string.Equals(((Object)r).name, "IslandHolder", StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val == (Object)null) { val = new GameObject("IslandHolder"); SceneManager.MoveGameObjectToScene(val, scene); val.transform.position = (map.Manifest.moveScene ? map.Position : Vector3.zero); } AdaptLevelPhysics(val.transform); EnsureIslandComponent(map, val.transform); EnsureSpawnManager(map, val.transform); } private void EnsureIslandComponent(RegisteredMap map, Transform holder) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown Type type = AccessTools.TypeByName("Island"); if (!(type == null)) { Transform val = FindChildRecursive(holder, "IslandManager"); GameObject val2; if ((Object)(object)val != (Object)null) { val2 = ((Component)val).gameObject; } else { val2 = new GameObject("IslandManager"); val2.transform.SetParent(holder, false); } Component val3 = val2.GetComponent(type); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(type); } SetFieldIfExists(val3, "_islandSize", map.Manifest.islandSize); } } private void EnsureSpawnManager(RegisteredMap map, Transform holder) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) Type type = AccessTools.TypeByName("SpawnManager"); if (!(type == null)) { Transform val = FindChildRecursive(holder, "SpawnManager"); GameObject val2; if ((Object)(object)val != (Object)null) { val2 = ((Component)val).gameObject; } else { val2 = new GameObject("SpawnManager"); val2.transform.SetParent(holder, false); } val2.SetActive(false); string text = map.Manifest.runtime?.playerSpawn ?? "PlayerSpawnPoint"; string text2 = map.Manifest.runtime?.boatSpawn ?? "BoatSpawnPoint"; Transform val3 = FindChildRecursive(holder, text); if ((Object)(object)val3 == (Object)null) { GameObject val4 = new GameObject(text); val4.transform.SetParent(val2.transform, false); val4.transform.localPosition = (Vector3)(((??)map.Manifest.runtime?.defaultPlayerSpawn?.ToVector3()) ?? new Vector3(0f, 6f, 0f)); val3 = val4.transform; } Transform val5 = FindChildRecursive(holder, text2); if ((Object)(object)val5 == (Object)null) { GameObject val6 = new GameObject(text2); val6.transform.SetParent(val2.transform, false); val6.transform.localPosition = (Vector3)(((??)map.Manifest.runtime?.defaultBoatSpawn?.ToVector3()) ?? new Vector3(0f, 0.5f, -25f)); val5 = val6.transform; } Component val7 = val2.GetComponent(type); if ((Object)(object)val7 == (Object)null) { val7 = val2.AddComponent(type); } SetFieldIfExists(val7, "_testPrint", "HTF Map Loader: " + map.Manifest.id); SetFieldIfExists(val7, "_playerSpawnPoint", val3); SetFieldIfExists(val7, "_boatSpawnPoint", val5); object obj = FindBoatPrefabInMemory(); if (obj != null) { SetFieldIfExists(val7, "_boatPrefab", obj); } val2.SetActive(true); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[RUNTIME] '{map.Manifest.id}' PlayerSpawn={val3.position}, BoatSpawn={val5.position}."); } } private void ApplyOptionalWildlife(RegisteredMap map, Scene scene) { //IL_0019: 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) WildlifeManifest wildlife = map.Manifest.wildlife; if (wildlife != null) { if (wildlife.seagulls) { EnsureSeagullSpawner(scene, Mathf.Clamp(wildlife.seagullMax, 1, 20), Mathf.Max(1f, wildlife.seagullDelay)); } if (wildlife.clams) { EnsureClamSpawner(scene, Mathf.Clamp(wildlife.clamMax, 1, 20), Mathf.Max(1f, wildlife.clamDelay)); } } } private void EnsureSeagullSpawner(Scene scene, int maxCount, float delay) { //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_0097: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindIslandHolder(scene); if ((Object)(object)val == (Object)null || (Object)(object)FindChildRecursive(val.transform, "SeagullSpawner") != (Object)null) { return; } Type type = AccessTools.TypeByName("ItemSpawner"); Type type2 = AccessTools.TypeByName("Bird"); if (!(type == null) && !(type2 == null)) { Object val2 = FindNamedComponentPrefab(type2, "Seagull"); if (val2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[WILDLIFE] Seagull prefab not available in memory."); return; } Transform orCreateChild = GetOrCreateChild(val.transform, "CreatureSpawners"); GameObject val3 = new GameObject("SeagullSpawner"); val3.transform.SetParent(orCreateChild, false); val3.transform.localPosition = new Vector3(0f, 20f, 0f); val3.SetActive(false); BoxCollider val4 = val3.AddComponent(); ((Collider)val4).isTrigger = true; val4.size = new Vector3(70f, 12f, 70f); Component spawner = val3.AddComponent(type); ConfigureItemSpawner(spawner, val4, val2, deadCreature: false, spawnInAir: true, maxCount, delay, 1); val3.SetActive(true); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[WILDLIFE] SeagullSpawner added max={maxCount}, delay={delay:0.#}."); } } private void EnsureClamSpawner(Scene scene, int maxCount, float delay) { //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_0097: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindIslandHolder(scene); if ((Object)(object)val == (Object)null || (Object)(object)FindChildRecursive(val.transform, "ClamSpawner") != (Object)null) { return; } Type type = AccessTools.TypeByName("ItemSpawner"); Type type2 = AccessTools.TypeByName("Creature"); if (!(type == null) && !(type2 == null)) { Object val2 = FindNamedComponentPrefab(type2, "Clam"); if (val2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[WILDLIFE] Clam prefab not available in memory."); return; } Transform orCreateChild = GetOrCreateChild(val.transform, "CreatureSpawners"); GameObject val3 = new GameObject("ClamSpawner"); val3.transform.SetParent(orCreateChild, false); val3.transform.localPosition = new Vector3(0f, 1.5f, 0f); val3.SetActive(false); BoxCollider val4 = val3.AddComponent(); ((Collider)val4).isTrigger = true; val4.center = new Vector3(0f, -1.25f, 0f); val4.size = new Vector3(28f, 3f, 28f); Component spawner = val3.AddComponent(type); ConfigureItemSpawner(spawner, val4, val2, deadCreature: true, spawnInAir: false, maxCount, delay, 2); val3.SetActive(true); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[WILDLIFE] ClamSpawner added max={maxCount}, delay={delay:0.#}."); } } private void ConfigureItemSpawner(Component spawner, BoxCollider box, Object prefab, bool deadCreature, bool spawnInAir, int max, float delay, int count) { SetFieldIfExists(spawner, "_isActive", true); SetFieldIfExists(spawner, "_itemToSpawn", prefab); SetFieldIfExists(spawner, "_spawnsDeadCreature", deadCreature); SetFieldIfExists(spawner, "_startFrequencyForRadio", 98); SetFieldIfExists(spawner, "_useRandomRotation", true); SetFieldIfExists(spawner, "_maxItemsSpawned", max); SetFieldIfExists(spawner, "_spawnInstant", true); SetFieldIfExists(spawner, "_onlySpawnOnce", false); SetFieldIfExists(spawner, "_spawnInAir", spawnInAir); SetFieldIfExists(spawner, "_spawnDelay", delay); SetFieldIfExists(spawner, "_spawnCount", count); SetFieldIfExists(spawner, "_spawnBox", box); SetFieldIfExists(spawner, "_hasSpawned", false); FieldInfo fieldInfo = FindField(((object)spawner).GetType(), "_itemsSpawned"); if (fieldInfo != null) { try { fieldInfo.SetValue(spawner, Activator.CreateInstance(fieldInfo.FieldType)); } catch { } } } private void VerifyRegisteredNavigationTriggers() { //IL_0138: Unknown result type (might be due to invalid IL or missing references) Type type = AccessTools.TypeByName("IslandSpawner"); if (type == null) { return; } Object[] source = Resources.FindObjectsOfTypeAll(type); foreach (RegisteredMap map in _mapsByIndex.Values) { Component val = source.OfType().FirstOrDefault((Func)delegate(Component c) { if ((Object)(object)c == (Object)null || (Object)(object)c.gameObject == (Object)null) { return false; } FieldInfo fieldInfo = FindField(((object)c).GetType(), "_islandIndex"); if (fieldInfo == null) { return false; } try { return Convert.ToByte(fieldInfo.GetValue(c)) == map.LogicalIndex; } catch { return false; } }); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)($"[TRIGGER VERIFY] '{map.Manifest.id}' index={map.LogicalIndex}: " + "NO live IslandSpawner found.")); continue; } Transform parent = val.gameObject.transform.parent; Collider[] array = ((parent != null) ? ((Component)parent).GetComponentsInChildren(true) : null) ?? Array.Empty(); ((BaseUnityPlugin)this).Logger.LogWarning((object)($"[TRIGGER VERIFY] '{map.Manifest.id}' index={map.LogicalIndex}: " + $"spawner='{((Object)val.gameObject).name}' active={val.gameObject.activeInHierarchy} " + $"pos={val.transform.position} colliders={array.Length}.")); } } private bool IsGameplayWorldReady() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) bool flag = false; bool flag2 = false; for (int i = 0; i < SceneManager.sceneCount; i++) { Scene scene = SceneManager.GetSceneAt(i); if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded) { if (string.Equals(((Scene)(ref scene)).name, "Game", StringComparison.OrdinalIgnoreCase)) { flag = true; } else if (((Scene)(ref scene)).name.StartsWith("Island", StringComparison.OrdinalIgnoreCase) || string.Equals(((Scene)(ref scene)).name, "DevIsland", StringComparison.OrdinalIgnoreCase) || _maps.Any((RegisteredMap m) => !string.IsNullOrWhiteSpace(m.SceneName) && string.Equals(m.SceneName, ((Scene)(ref scene)).name, StringComparison.OrdinalIgnoreCase))) { flag2 = true; } } } if (!flag || !flag2) { return false; } object obj = FindLiveObjectByTypeName("IslandManager"); if (obj == null) { return false; } Array infos = FindField(obj.GetType(), "_islandInfos")?.GetValue(obj) as Array; if (infos != null) { return _mapsByIndex.Keys.All((byte index) => index < infos.Length); } return false; } private void UpdateRadar() { //IL_011c: Unknown result type (might be due to invalid IL or missing references) if (_mapsByIndex.Count == 0) { return; } if (_radarUi == null || _maps.Any((RegisteredMap m) => _mapsByIndex.ContainsKey(m.LogicalIndex) && m.MapDot == null)) { EnsureRadarDots(); } if (_radarUi == null) { return; } if (!IsNativeRadarCurrentlyVisible()) { foreach (RegisteredMap map in _maps) { SetMapDotVisualActive(map.MapDot, active: false); } return; } foreach (RegisteredMap map2 in _maps) { if (map2.MapDot == null) { continue; } try { if (_radarUpdateDotMethod == null) { Type type = map2.MapDot.GetType(); _radarUpdateDotMethod = _radarUi.GetType().GetMethod("UpdateDot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { type, typeof(Vector3) }, null); } _radarUpdateDotMethod?.Invoke(_radarUi, new object[2] { map2.MapDot, map2.Position }); SetMapDotVisualActive(map2.MapDot, active: true); ApplyMapDotColor(map2); } catch { ResetRadarReferences(); break; } } } private void EnsureRadarDots() { if (Time.unscaledTime < _nextRadarAcquire) { return; } _nextRadarAcquire = Time.unscaledTime + 1f; object obj = FindLiveObjectByTypeName("RadarUI"); if (obj == null) { return; } FieldInfo fieldInfo = FindField(obj.GetType(), "_islandDots"); if (!(fieldInfo?.GetValue(obj) is Array array)) { return; } Type elementType = array.GetType().GetElementType(); if (elementType == null) { return; } int val = (from m in _maps where _mapsByIndex.ContainsKey(m.LogicalIndex) select m.LogicalIndex + 1).DefaultIfEmpty(array.Length).Max(); Array array2 = Array.CreateInstance(elementType, Math.Max(array.Length, val)); Array.Copy(array, array2, array.Length); object obj2 = null; for (int num = 0; num < array.Length; num++) { object value = array.GetValue(num); if (value != null) { obj2 = value; break; } } if (obj2 == null) { return; } foreach (RegisteredMap map in _maps) { int logicalIndex = map.LogicalIndex; object obj3 = ((logicalIndex < array.Length) ? array.GetValue(logicalIndex) : null); if (obj3 != null && map.MapDot == null && IsOurMapDot(obj3, map.Manifest.id)) { map.MapDot = obj3; } if (map.MapDot == null) { map.MapDot = CloneMapDot(obj2, "HTFML_Radar_" + map.Manifest.id); } if (map.MapDot != null) { array2.SetValue(map.MapDot, logicalIndex); ApplyMapDotColor(map); } } fieldInfo.SetValue(obj, array2); _radarUi = obj; _radarUpdateDotMethod = null; ((BaseUnityPlugin)this).Logger.LogWarning((object)($"[RADAR] MapDot array {array.Length} -> {array2.Length}. " + "Custom=" + string.Join(", ", _mapsByIndex.Values.Select((RegisteredMap m) => $"{m.Manifest.id}@{m.LogicalIndex}:{m.Position}")))); } private bool IsOurMapDot(object mapDot, string mapId) { if (mapDot == null) { return false; } try { object? obj = FindField(mapDot.GetType(), "_dot")?.GetValue(mapDot); Component val = (Component)((obj is Component) ? obj : null); return (Object)(object)val != (Object)null && (Object)(object)val.gameObject != (Object)null && string.Equals(((Object)val.gameObject).name, "HTFML_Radar_" + mapId, StringComparison.OrdinalIgnoreCase); } catch { return false; } } private object CloneMapDot(object template, string name) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) object obj = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(template, null); if (obj == null) { return null; } FieldInfo fieldInfo = FindField(obj.GetType(), "_dot"); object? obj2 = fieldInfo?.GetValue(template); Component val = (Component)((obj2 is Component) ? obj2 : null); if ((Object)(object)val == (Object)null || (Object)(object)val.transform.parent == (Object)null) { return null; } GameObject val2 = Object.Instantiate(val.gameObject); ((Object)val2).name = name; val2.transform.SetParent(val.transform.parent, false); val2.transform.localPosition = val.transform.localPosition; val2.transform.localRotation = val.transform.localRotation; val2.transform.localScale = val.transform.localScale; Component component = val2.GetComponent(fieldInfo.FieldType); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return null; } fieldInfo.SetValue(obj, component); val2.SetActive(val.gameObject.activeInHierarchy); return obj; } private bool IsNativeRadarCurrentlyVisible() { if (_radarUi == null) { return false; } if (!(FindField(_radarUi.GetType(), "_islandDots")?.GetValue(_radarUi) is Array array)) { return false; } int num = Math.Min(5, array.Length); for (int i = 0; i < num; i++) { object value = array.GetValue(i); object? obj = ((value != null) ? FindField(value.GetType(), "_dot") : null)?.GetValue(value); Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null && val.gameObject.activeInHierarchy) { return true; } } return false; } private void ApplyMapDotColor(RegisteredMap map) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (map == null || map.MapDot == null) { return; } object? obj = FindField(map.MapDot.GetType(), "_dot")?.GetValue(map.MapDot); Component val = (Component)((obj is Component) ? obj : null); PropertyInfo propertyInfo = ((object)val)?.GetType().GetProperty("color", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(propertyInfo != null) || !propertyInfo.CanWrite || !(propertyInfo.PropertyType == typeof(Color))) { return; } try { propertyInfo.SetValue(val, map.RadarColor, null); } catch { } } private void SetMapDotVisualActive(object mapDot, bool active) { if (mapDot != null) { object? obj = FindField(mapDot.GetType(), "_dot")?.GetValue(mapDot); Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null && val.gameObject.activeSelf != active) { val.gameObject.SetActive(active); } } } private void ResetRadarReferences() { _radarUi = null; _radarUpdateDotMethod = null; _nextRadarAcquire = Time.unscaledTime + 0.75f; foreach (RegisteredMap map in _maps) { map.MapDot = null; } } private void CacheNativeGroundCollision() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) Collider val = null; float num = -1f; for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (!((Scene)(ref sceneAt)).IsValid() || !((Scene)(ref sceneAt)).isLoaded || (!((Scene)(ref sceneAt)).name.StartsWith("Island", StringComparison.OrdinalIgnoreCase) && !string.Equals(((Scene)(ref sceneAt)).name, "DevIsland", StringComparison.OrdinalIgnoreCase))) { continue; } GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects(); for (int j = 0; j < rootGameObjects.Length; j++) { Collider[] componentsInChildren = rootGameObjects[j].GetComponentsInChildren(true); foreach (Collider val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2.enabled && !val2.isTrigger) { Bounds bounds = val2.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float num2 = size.x * size.z; if (num2 > num) { num = num2; val = val2; } } } } } if (!((Object)(object)val == (Object)null)) { _nativeGroundLayer = ((Component)val).gameObject.layer; _nativeGroundMaterial = val.sharedMaterial; } } private void AdaptLevelPhysics(Transform holder) { if ((Object)(object)holder == (Object)null) { return; } int num = LayerMask.NameToLayer("Level"); if (num < 0) { num = ((_nativeGroundLayer >= 0) ? _nativeGroundLayer : 8); } Collider[] componentsInChildren = ((Component)holder).GetComponentsInChildren(true); int num2 = 0; Collider[] array = componentsInChildren; foreach (Collider val in array) { if ((Object)(object)val == (Object)null || val.isTrigger) { continue; } Rigidbody component = ((Component)val).gameObject.GetComponent(); if (!((Object)(object)component != (Object)null) || component.isKinematic) { ((Component)val).gameObject.layer = num; TrySetLevelTag(((Component)val).gameObject); val.enabled = true; if ((Object)(object)_nativeGroundMaterial != (Object)null && (Object)(object)val.sharedMaterial == (Object)null) { val.sharedMaterial = _nativeGroundMaterial; } num2++; } } if (_verbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[PHYSICS] Adapted {num2} static collider(s) to Level."); } } private bool TrySetLevelTag(GameObject go) { try { if (!go.CompareTag("Level")) { go.tag = "Level"; } return true; } catch { return false; } } private object FindBoatPrefabInMemory() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Type type = AccessTools.TypeByName("Boat"); if (type == null) { return null; } Object[] array = Resources.FindObjectsOfTypeAll(type); Object[] array2 = array; foreach (Object val in array2) { Component val2 = (Component)(object)((val is Component) ? val : null); if (!((Object)(object)val2 == (Object)null)) { Scene scene = val2.gameObject.scene; if (!((Scene)(ref scene)).IsValid() || ((Scene)(ref scene)).buildIndex < 0) { return val; } } } return ((IEnumerable)array).FirstOrDefault((Func)((Object o) => o != (Object)null)); } private Object FindNamedComponentPrefab(Type componentType, string wantedName) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Object[] array = Resources.FindObjectsOfTypeAll(componentType); Object val = null; Object[] array2 = array; foreach (Object obj in array2) { Component val2 = (Component)(object)((obj is Component) ? obj : null); if (!((Object)(object)val2 == (Object)null) && (((Object)val2.gameObject).name ?? "").IndexOf(wantedName, StringComparison.OrdinalIgnoreCase) >= 0) { Scene scene = val2.gameObject.scene; if (!((Scene)(ref scene)).IsValid() || ((Scene)(ref scene)).buildIndex < 0) { return (Object)(object)val2; } if (val == (Object)null) { val = (Object)(object)val2; } } } return val; } private GameObject FindIslandHolder(Scene scene) { if (!((Scene)(ref scene)).IsValid() || !((Scene)(ref scene)).isLoaded) { return null; } return ((IEnumerable)((Scene)(ref scene)).GetRootGameObjects()).FirstOrDefault((Func)((GameObject r) => (Object)(object)r != (Object)null && string.Equals(((Object)r).name, "IslandHolder", StringComparison.OrdinalIgnoreCase))); } private Transform GetOrCreateChild(Transform parent, string name) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Transform val = FindChildRecursive(parent, name); if ((Object)(object)val != (Object)null) { return val; } GameObject val2 = new GameObject(name); val2.transform.SetParent(parent, false); return val2.transform; } private static object FindLiveObjectByTypeName(string typeName) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Type type = AccessTools.TypeByName(typeName); if (type == null) { return null; } Object[] array = Resources.FindObjectsOfTypeAll(type); Object[] array2 = array; foreach (Object obj in array2) { Component val = (Component)(object)((obj is Component) ? obj : null); if (!((Object)(object)val == (Object)null)) { Scene scene = val.gameObject.scene; if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded) { return val; } } } return ((IEnumerable)array).FirstOrDefault((Func)((Object o) => o != (Object)null)); } private static FieldInfo FindField(Type type, string name) { Type type2 = type; while (type2 != null) { FieldInfo field = type2.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type2 = type2.BaseType; } return null; } private static Transform FindChildRecursive(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } if (string.Equals(((Object)root).name, name, StringComparison.Ordinal)) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindChildRecursive(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static bool SetFieldIfExists(object target, string fieldName, object value) { if (target == null) { return false; } FieldInfo fieldInfo = FindField(target.GetType(), fieldName); if (fieldInfo == null) { return false; } try { object value2 = value; if (value != null && !fieldInfo.FieldType.IsInstanceOfType(value)) { value2 = ((!fieldInfo.FieldType.IsEnum) ? Convert.ChangeType(value, fieldInfo.FieldType) : Enum.ToObject(fieldInfo.FieldType, value)); } fieldInfo.SetValue(target, value2); return true; } catch { return false; } } } }