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<bool> _enabled;
private ConfigEntry<bool> _verbose;
private ConfigEntry<bool> _repairRuntime;
private ConfigEntry<bool> _enableMapWildlife;
private readonly List<RegisteredMap> _maps = new List<RegisteredMap>();
private readonly Dictionary<byte, RegisteredMap> _mapsByIndex = new Dictionary<byte, RegisteredMap>();
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<bool>("General", "Enabled", true, "Enable HTF Map Loader.");
_repairRuntime = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RepairMissingRuntimeObjects", true, "Automatically repair common Island/SpawnManager/Level setup when a map is missing it.");
_enableMapWildlife = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AllowMapWildlifeOptions", true, "Allow map.json to request optional built-in Seagull and Clam spawners.");
_verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("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<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
int num = 0;
string[] array2 = array;
foreach (string text in array2)
{
try
{
string text2 = File.ReadAllText(text);
MapManifest mapManifest = JsonUtility.FromJson<MapManifest>(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<string> hashSet = new HashSet<string>(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, string>((string p) => p, StringComparer.OrdinalIgnoreCase).ToArray();
}
private void AddMapManifestsFromMapsRoot(string mapsRoot, HashSet<string> 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<string> EnumerateDirectoriesSafe(string root, string wantedName)
{
Stack<string> pending = new Stack<string>();
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<string> list = new List<string>();
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<Vector3> list = new List<Vector3>();
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<Vector3> 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<Vector3> 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<Vector3> 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<GameObject>(((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<Collider>(true);
Collider[] componentsInChildren2 = clonedHolder.GetComponentsInChildren<Collider>(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<Collider>(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<Rigidbody>();
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 "<null>";
}
try
{
return go.tag;
}
catch
{
return "<unavailable>";
}
}
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<AsyncOperation> list = new List<AsyncOperation>();
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<GameObject>)rootGameObjects).FirstOrDefault((Func<GameObject, bool>)((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<GameObject>)((Scene)(ref scene)).GetRootGameObjects()).FirstOrDefault((Func<GameObject, bool>)((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<BoxCollider>();
((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<BoxCollider>();
((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<Component>().FirstOrDefault((Func<Component, bool>)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<Collider>(true) : null) ?? Array.Empty<Collider>();
((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<GameObject>(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<Collider>(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<Collider>(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<Rigidbody>();
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<Object>)array).FirstOrDefault((Func<Object, bool>)((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<GameObject>)((Scene)(ref scene)).GetRootGameObjects()).FirstOrDefault((Func<GameObject, bool>)((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<Object>)array).FirstOrDefault((Func<Object, bool>)((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;
}
}
}
}