using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using AtlyssCommandLib.API;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Mirror;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Guid("8f2a7c14-6b03-4d9e-a157-3c8b0e6d42f9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyTitle("TundrasInstancer")]
[assembly: AssemblyProduct("TundrasInstancer")]
[assembly: AssemblyDescription("Private map instances on command.")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace tundras_instancer;
internal struct MapEntry
{
internal string ScenePath;
internal string Caption;
internal string SpawnTag;
}
internal static class MapCatalog
{
internal static List<MapEntry> Gather()
{
List<MapEntry> list = new List<MapEntry>();
Portal[] array = Resources.FindObjectsOfTypeAll<Portal>();
for (int i = 0; i < array.Length; i++)
{
ScenePortalData scenePortal = array[i]._scenePortal;
if (scenePortal != null)
{
Add(list, scenePortal._subScene, scenePortal._portalCaptionTitle, scenePortal._spawnPointTag);
}
}
ScriptableMapData[] array2 = Resources.FindObjectsOfTypeAll<ScriptableMapData>();
for (int j = 0; j < array2.Length; j++)
{
Add(list, array2[j]._subScene, array2[j]._mapCaptionTitle, array2[j]._spawnPointTag);
}
return list;
}
private static void Add(List<MapEntry> found, string scenePath, string caption, string spawnTag)
{
if (string.IsNullOrEmpty(scenePath))
{
return;
}
for (int i = 0; i < found.Count; i++)
{
if (found[i].ScenePath == scenePath)
{
return;
}
}
found.Add(new MapEntry
{
ScenePath = scenePath,
Caption = (string.IsNullOrEmpty(caption) ? Key(scenePath) : caption),
SpawnTag = (string.IsNullOrEmpty(spawnTag) ? "spawnPoint" : spawnTag)
});
}
internal static string Key(string scenePath)
{
if (string.IsNullOrEmpty(scenePath))
{
return "";
}
int num = scenePath.LastIndexOf('/');
string text = ((num < 0) ? scenePath : scenePath.Substring(num + 1));
if (text.EndsWith(".unity", StringComparison.OrdinalIgnoreCase))
{
text = text.Substring(0, text.Length - 6);
}
return text;
}
internal static bool IsVanilla(string scenePath)
{
return SceneUtility.GetBuildIndexByScenePath(scenePath) >= 0;
}
internal static bool Resolve(string wanted, out MapEntry match)
{
match = default(MapEntry);
if (string.IsNullOrEmpty(wanted))
{
return false;
}
string text = Flatten(wanted);
List<MapEntry> list = Gather();
for (int i = 0; i < list.Count; i++)
{
if (Flatten(Key(list[i].ScenePath)) == text || Flatten(list[i].Caption) == text)
{
match = list[i];
return true;
}
}
for (int j = 0; j < list.Count; j++)
{
if (Flatten(Key(list[j].ScenePath)).Contains(text) || Flatten(list[j].Caption).Contains(text))
{
match = list[j];
return true;
}
}
return false;
}
private static string Flatten(string value)
{
if (string.IsNullOrEmpty(value))
{
return "";
}
return value.Replace(" ", "").Replace("_", "").ToLowerInvariant();
}
}
internal static class InstanceCommands
{
private static readonly Color Notice = new Color(0.6f, 0.85f, 1f);
private static readonly Color Problem = new Color(1f, 0.55f, 0.5f);
internal static void Register()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
//IL_004f: 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_0064: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
//IL_009f: 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_00b4: Expected O, but got Unknown
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Expected O, but got Unknown
try
{
CommandProvider val = new CommandProvider("instance", "Private map instances");
val.RegisterCommand("go", "Open a private instance of a map and travel to it", "instance go <map name>", new CommandCallback(Go), (CommandOptions?)new CommandOptions((ChatCommandType)3));
val.RegisterCommand("maps", "List maps that can be instanced", new CommandCallback(Maps), (CommandOptions?)new CommandOptions((ChatCommandType)3));
val.RegisterCommand("list", "List the private instances that are open right now", new CommandCallback(ListOpen), (CommandOptions?)new CommandOptions((ChatCommandType)2));
val.RegisterCommand("leave", "Return to the hub from a private instance", new CommandCallback(Leave), (CommandOptions?)new CommandOptions((ChatCommandType)3));
val.RegisterCommand("close", "Give up the private instance you opened", new CommandCallback(Close), (CommandOptions?)new CommandOptions((ChatCommandType)3));
Utils.RegisterProvider(val);
Log.Info("registered /instance with go, maps, list, leave and close");
}
catch (Exception ex)
{
Log.Warn("could not register commands, " + ex.Message);
}
}
private static bool Go(Caller caller, string[] args)
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: 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_0098: 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_00f0: 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_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
Player player = caller.player;
if (!NetworkServer.active || (Object)(object)player == (Object)null)
{
return true;
}
if (args == null || args.Length == 0)
{
return false;
}
if (TundrasInstancerConfig.HostOnly.Value && !((Caller)(ref caller)).isHost)
{
Utils.NotifyCaller(caller, "Only the host can open private instances here.", Problem);
return true;
}
string text = string.Join(" ", args);
if (!MapCatalog.Resolve(text, out var match))
{
Utils.NotifyCaller(caller, "No map called " + text + ". Try /instance maps.", Problem);
return true;
}
if (!TundrasInstancerConfig.AllowVanillaMaps.Value && MapCatalog.IsVanilla(match.ScenePath))
{
Utils.NotifyCaller(caller, match.Caption + " is a vanilla map and instancing it is disabled.", Problem);
return true;
}
MapInstancingManager current = MapInstancingManager._current;
if ((Object)(object)current == (Object)null)
{
Utils.NotifyCaller(caller, "The world is not ready yet, try again in a moment.", Problem);
return true;
}
MapInstance val = InstanceRegistry.FindAdmitting(match.ScenePath, player);
if ((Object)(object)val != (Object)null)
{
Utils.NotifyCaller(caller, "Rejoining your instance of " + match.Caption + ".", Notice);
}
else
{
InstanceClaim instanceClaim = InstanceRegistry.FindOwnedBy(player);
if (instanceClaim != null)
{
Utils.NotifyCaller(caller, "You already have " + MapCatalog.Key(instanceClaim.ScenePath) + " open. Use /instance close first, or /instance go " + MapCatalog.Key(instanceClaim.ScenePath) + " to return to it.", Problem);
return true;
}
InstanceRequests.Add(player);
Utils.NotifyCaller(caller, "Opening a private instance of " + match.Caption + ".", Notice);
}
Scene scene = ((Component)player).gameObject.scene;
current.Init_SendPeer_ToScene(player, ((Scene)(ref scene)).path, match.ScenePath, match.SpawnTag, (ZoneDifficulty)1);
return true;
}
private static int PeersInside(InstanceClaim claim)
{
if ((Object)(object)claim.Instance == (Object)null || claim.Instance._peersInInstance == null)
{
return 0;
}
return claim.Instance._peersInInstance.Count;
}
private static int OthersInside(InstanceClaim claim, Player except)
{
if ((Object)(object)claim.Instance == (Object)null || claim.Instance._peersInInstance == null)
{
return 0;
}
int num = 0;
List<Player> peersInInstance = claim.Instance._peersInInstance;
for (int i = 0; i < peersInInstance.Count; i++)
{
if ((Object)(object)peersInInstance[i] != (Object)null && (Object)(object)peersInInstance[i] != (Object)(object)except)
{
num++;
}
}
return num;
}
private static bool Maps(Caller caller, string[] args)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
List<MapEntry> list = MapCatalog.Gather();
if (list.Count == 0)
{
Utils.NotifyCaller(caller, "No maps found yet, load into the world first.", Problem);
return true;
}
for (int i = 0; i < list.Count; i++)
{
string text = (MapCatalog.IsVanilla(list[i].ScenePath) ? "" : " (modded)");
Utils.NotifyCaller(caller, MapCatalog.Key(list[i].ScenePath) + " - " + list[i].Caption + text, Notice);
}
return true;
}
private static bool ListOpen(Caller caller, string[] args)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
if (!((Caller)(ref caller)).isHost)
{
Utils.NotifyCaller(caller, "Only the host can see who has an instance open.", Problem);
return true;
}
IList<InstanceClaim> all = InstanceRegistry.All;
if (all.Count == 0)
{
Utils.NotifyCaller(caller, "No private instances are open.", Notice);
return true;
}
for (int i = 0; i < all.Count; i++)
{
Utils.NotifyCaller(caller, MapCatalog.Key(all[i].ScenePath) + " owner " + all[i].OwnerName() + " peers " + PeersInside(all[i]), Notice);
}
return true;
}
private static bool Close(Caller caller, string[] args)
{
//IL_0024: 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_009b: 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_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
Player player = caller.player;
if (!NetworkServer.active || (Object)(object)player == (Object)null)
{
return true;
}
InstanceClaim instanceClaim = InstanceRegistry.FindOwnedBy(player);
if (instanceClaim == null)
{
Utils.NotifyCaller(caller, "You do not have an instance open.", Problem);
return true;
}
int num = OthersInside(instanceClaim, player);
string text = MapCatalog.Key(instanceClaim.ScenePath);
InstanceRegistry.Release(player);
if (num > 0)
{
Utils.NotifyCaller(caller, "Gave up " + text + ". " + num + " still inside, it closes when they leave.", Notice);
}
else
{
Utils.NotifyCaller(caller, "Gave up " + text + ". You can open another now.", Notice);
}
return true;
}
private static bool Leave(Caller caller, string[] args)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
Player player = caller.player;
if (!NetworkServer.active || (Object)(object)player == (Object)null)
{
return true;
}
MapInstancingManager current = MapInstancingManager._current;
if ((Object)(object)current == (Object)null)
{
return true;
}
Scene scene = ((Component)player).gameObject.scene;
current.Init_SendPeer_ToScene(player, ((Scene)(ref scene)).path, current._hubMap, current._hubMainSpawnPointTag, (ZoneDifficulty)1);
Utils.NotifyCaller(caller, "Returning to the hub.", Notice);
return true;
}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.tundra.atlyss.tundrasinstancer", "Tundra's Instancer", "1.0.0")]
public class TundrasInstancerPlugin : BaseUnityPlugin
{
internal const string PluginGuid = "com.tundra.atlyss.tundrasinstancer";
private void Awake()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
Log.Init(((BaseUnityPlugin)this).Logger);
TundrasInstancerConfig.Init(((BaseUnityPlugin)this).Config);
InstanceCommands.Register();
InstancePatches.Apply(new Harmony("com.tundra.atlyss.tundrasinstancer"));
Log.Info("ready");
}
private void Update()
{
InstanceSleeper.Tick();
}
private void OnDestroy()
{
InstanceSleeper.WakeAll();
}
}
internal static class Log
{
private static ManualLogSource _source;
internal static void Init(ManualLogSource source)
{
_source = source;
}
internal static void Info(string message)
{
if (_source != null)
{
_source.LogInfo((object)message);
}
}
internal static void Warn(string message)
{
if (_source != null)
{
_source.LogWarning((object)message);
}
}
}
internal static class TundrasInstancerConfig
{
internal static ConfigEntry<bool> HostOnly;
internal static ConfigEntry<bool> AllowVanillaMaps;
internal static ConfigEntry<bool> SleepIdleInstances;
internal static ConfigEntry<bool> SleepCreepVisuals;
internal static void Init(ConfigFile config)
{
HostOnly = config.Bind<bool>("Access", "HostOnly", false, "When true only the host may open a private instance.");
AllowVanillaMaps = config.Bind<bool>("Access", "AllowVanillaMaps", true, "When false only maps added by MapLoader may be instanced, leaving the vanilla world alone.");
SleepIdleInstances = config.Bind<bool>("Performance", "SleepIdleInstances", true, "On the host, stops drawing props, lights, cameras and particles in instances you are not standing in.");
SleepCreepVisuals = config.Bind<bool>("Performance", "SleepCreepVisuals", true, "Also stops drawing and animating monsters in those instances. Only affects your own screen, other players still see them.");
}
}
internal sealed class InstanceClaim
{
internal MapInstance Instance;
internal string ScenePath;
internal PartyObjectBehavior Party;
internal Player Owner;
internal string OwnerId;
internal string OwnerLabel;
internal bool Admits(Player player)
{
if ((Object)(object)player == (Object)null)
{
return false;
}
if (InstanceRegistry.SameOwner(this, player))
{
return true;
}
if ((Object)(object)Owner != (Object)null)
{
Party = Owner.Network_partyObject;
}
if ((Object)(object)Party != (Object)null)
{
return (Object)(object)player.Network_partyObject == (Object)(object)Party;
}
return false;
}
internal string OwnerName()
{
if ((Object)(object)Owner != (Object)null && !string.IsNullOrEmpty(Owner._nickname))
{
return Owner._nickname;
}
if (!string.IsNullOrEmpty(OwnerLabel))
{
return OwnerLabel;
}
return "someone who left";
}
}
internal static class InstanceRegistry
{
private static readonly List<InstanceClaim> Claims = new List<InstanceClaim>();
internal static IList<InstanceClaim> All
{
get
{
Prune();
return Claims;
}
}
internal static void Prune()
{
for (int num = Claims.Count - 1; num >= 0; num--)
{
if ((Object)(object)Claims[num].Instance == (Object)null)
{
Log.Info("private instance of " + Claims[num].ScenePath + " was unloaded");
Claims.RemoveAt(num);
}
}
}
internal static string IdentityOf(Player player)
{
if ((Object)(object)player == (Object)null)
{
return null;
}
string steamID = player._steamID;
if (!string.IsNullOrEmpty(steamID))
{
return steamID;
}
return null;
}
internal static bool SameOwner(InstanceClaim claim, Player player)
{
if (claim == null || (Object)(object)player == (Object)null)
{
return false;
}
string text = IdentityOf(player);
if (text != null && text == claim.OwnerId)
{
return true;
}
return (Object)(object)claim.Owner == (Object)(object)player;
}
internal static InstanceClaim FindOwnedBy(Player owner)
{
if ((Object)(object)owner == (Object)null)
{
return null;
}
Prune();
foreach (InstanceClaim claim in Claims)
{
if (SameOwner(claim, owner))
{
return claim;
}
}
return null;
}
internal static bool Release(Player owner)
{
InstanceClaim instanceClaim = FindOwnedBy(owner);
if (instanceClaim == null)
{
return false;
}
Claims.Remove(instanceClaim);
Log.Info("released the private instance of " + instanceClaim.ScenePath + " owned by " + instanceClaim.OwnerName());
return true;
}
internal static void Add(MapInstance instance, string scenePath, Player owner)
{
InstanceClaim instanceClaim = FindOwnedBy(owner);
if (instanceClaim != null)
{
Log.Warn(instanceClaim.OwnerName() + " already owns an instance of " + instanceClaim.ScenePath + ", not claiming another");
return;
}
InstanceClaim instanceClaim2 = new InstanceClaim();
instanceClaim2.Instance = instance;
instanceClaim2.ScenePath = scenePath;
instanceClaim2.Owner = owner;
instanceClaim2.OwnerId = IdentityOf(owner);
instanceClaim2.OwnerLabel = (((Object)(object)owner == (Object)null) ? null : owner._nickname);
instanceClaim2.Party = (((Object)(object)owner == (Object)null) ? null : owner.Network_partyObject);
Claims.Add(instanceClaim2);
Log.Info("claimed a private instance of " + scenePath + " for " + instanceClaim2.OwnerName());
}
internal static bool HasAnyFor(string scenePath)
{
Prune();
foreach (InstanceClaim claim in Claims)
{
if (claim.ScenePath == scenePath)
{
return true;
}
}
return false;
}
internal static bool IsPrivate(MapInstance instance)
{
Prune();
foreach (InstanceClaim claim in Claims)
{
if ((Object)(object)claim.Instance == (Object)(object)instance)
{
return true;
}
}
return false;
}
internal static MapInstance FindAdmitting(string scenePath, Player player)
{
Prune();
foreach (InstanceClaim claim in Claims)
{
if (claim.ScenePath == scenePath && claim.Admits(player))
{
return claim.Instance;
}
}
return null;
}
}
internal static class InstanceRequests
{
private static readonly List<Player> Pending = new List<Player>();
internal static void Add(Player player)
{
for (int num = Pending.Count - 1; num >= 0; num--)
{
if ((Object)(object)Pending[num] == (Object)null)
{
Pending.RemoveAt(num);
}
}
if ((Object)(object)player != (Object)null && !Pending.Contains(player))
{
Pending.Add(player);
}
}
internal static bool Consume(Player player)
{
if ((Object)(object)player != (Object)null)
{
return Pending.Remove(player);
}
return false;
}
}
internal sealed class SleptInstance
{
internal MapInstance Instance;
internal List<Renderer> Renderers = new List<Renderer>();
internal List<Behaviour> Behaviours = new List<Behaviour>();
internal List<ParticleSystem> Particles = new List<ParticleSystem>();
internal List<AudioSource> Audio = new List<AudioSource>();
internal List<Animator> Animators = new List<Animator>();
}
internal static class InstanceSleeper
{
private static readonly List<SleptInstance> Slept = new List<SleptInstance>();
private static bool _describedAoi;
internal static void Tick()
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
if (!TundrasInstancerConfig.SleepIdleInstances.Value || !NetworkServer.active)
{
return;
}
Player mainPlayer = Player._mainPlayer;
MapInstancingManager current = MapInstancingManager._current;
if ((Object)(object)mainPlayer == (Object)null || (Object)(object)current == (Object)null)
{
return;
}
DescribeAoiOnce();
Scene scene = ((Component)mainPlayer).gameObject.scene;
for (int num = Slept.Count - 1; num >= 0; num--)
{
SleptInstance sleptInstance = Slept[num];
if ((Object)(object)sleptInstance.Instance == (Object)null)
{
Slept.RemoveAt(num);
}
else if (sleptInstance.Instance._loadedScene == scene)
{
Wake(sleptInstance);
Slept.RemoveAt(num);
}
}
foreach (MapInstance loadedInstance in current._loadedInstances)
{
if (!((Object)(object)loadedInstance == (Object)null) && !(loadedInstance._loadedScene == scene) && ((Scene)(ref loadedInstance._loadedScene)).IsValid() && !IsSlept(loadedInstance))
{
Sleep(loadedInstance);
}
}
}
internal static void WakeAll()
{
foreach (SleptInstance item in Slept)
{
if ((Object)(object)item.Instance != (Object)null)
{
Wake(item);
}
}
Slept.Clear();
}
private static bool IsSlept(MapInstance instance)
{
foreach (SleptInstance item in Slept)
{
if ((Object)(object)item.Instance == (Object)(object)instance)
{
return true;
}
}
return false;
}
private static void Sleep(MapInstance instance)
{
SleptInstance sleptInstance = new SleptInstance();
sleptInstance.Instance = instance;
Transform environment = (((Object)(object)instance._environmentGroup == (Object)null) ? null : instance._environmentGroup.transform);
GameObject[] rootGameObjects = ((Scene)(ref instance._loadedScene)).GetRootGameObjects();
foreach (GameObject val in rootGameObjects)
{
Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
foreach (Renderer val2 in componentsInChildren)
{
if (val2.enabled && !Skip(((Component)val2).transform, environment))
{
val2.enabled = false;
sleptInstance.Renderers.Add(val2);
}
}
Light[] componentsInChildren2 = val.GetComponentsInChildren<Light>(true);
foreach (Light val3 in componentsInChildren2)
{
if (((Behaviour)val3).enabled && !Skip(((Component)val3).transform, environment))
{
((Behaviour)val3).enabled = false;
sleptInstance.Behaviours.Add((Behaviour)(object)val3);
}
}
Camera[] componentsInChildren3 = val.GetComponentsInChildren<Camera>(true);
foreach (Camera val4 in componentsInChildren3)
{
if (((Behaviour)val4).enabled && !Skip(((Component)val4).transform, null))
{
((Behaviour)val4).enabled = false;
sleptInstance.Behaviours.Add((Behaviour)(object)val4);
}
}
ReflectionProbe[] componentsInChildren4 = val.GetComponentsInChildren<ReflectionProbe>(true);
foreach (ReflectionProbe val5 in componentsInChildren4)
{
if (((Behaviour)val5).enabled)
{
((Behaviour)val5).enabled = false;
sleptInstance.Behaviours.Add((Behaviour)(object)val5);
}
}
ParticleSystem[] componentsInChildren5 = val.GetComponentsInChildren<ParticleSystem>(true);
foreach (ParticleSystem val6 in componentsInChildren5)
{
if (val6.isPlaying && !Skip(((Component)val6).transform, null))
{
val6.Pause(false);
sleptInstance.Particles.Add(val6);
}
}
AudioSource[] componentsInChildren6 = val.GetComponentsInChildren<AudioSource>(true);
foreach (AudioSource val7 in componentsInChildren6)
{
if (val7.isPlaying && !Skip(((Component)val7).transform, null))
{
val7.Pause();
sleptInstance.Audio.Add(val7);
}
}
Animator[] componentsInChildren7 = val.GetComponentsInChildren<Animator>(true);
foreach (Animator val8 in componentsInChildren7)
{
if (((Behaviour)val8).enabled && !Skip(((Component)val8).transform, null))
{
((Behaviour)val8).enabled = false;
sleptInstance.Animators.Add(val8);
}
}
}
Slept.Add(sleptInstance);
Log.Info("slept " + instance._mapName + ": " + sleptInstance.Renderers.Count + " renderers, " + sleptInstance.Behaviours.Count + " lights/cameras/probes, " + sleptInstance.Particles.Count + " particle systems, " + sleptInstance.Audio.Count + " audio sources, " + sleptInstance.Animators.Count + " animators");
}
private static void Wake(SleptInstance slept)
{
foreach (Renderer renderer in slept.Renderers)
{
if ((Object)(object)renderer != (Object)null)
{
renderer.enabled = true;
}
}
foreach (Behaviour behaviour in slept.Behaviours)
{
if ((Object)(object)behaviour != (Object)null)
{
behaviour.enabled = true;
}
}
foreach (ParticleSystem particle in slept.Particles)
{
if ((Object)(object)particle != (Object)null)
{
particle.Play(false);
}
}
foreach (AudioSource item in slept.Audio)
{
if ((Object)(object)item != (Object)null)
{
item.UnPause();
}
}
foreach (Animator animator in slept.Animators)
{
if ((Object)(object)animator != (Object)null)
{
((Behaviour)animator).enabled = true;
}
}
Log.Info("woke " + slept.Instance._mapName);
}
private static bool Skip(Transform transform, Transform environment)
{
if ((Object)(object)environment != (Object)null && transform.IsChildOf(environment))
{
return true;
}
if ((Object)(object)((Component)transform).GetComponentInParent<Player>() != (Object)null)
{
return true;
}
if (TundrasInstancerConfig.SleepCreepVisuals.Value)
{
return false;
}
return (Object)(object)((Component)transform).GetComponentInParent<NetworkIdentity>() != (Object)null;
}
private static void DescribeAoiOnce()
{
if (!_describedAoi)
{
_describedAoi = true;
InterestManagementBase aoi = NetworkServer.aoi;
Log.Info("interest management: " + (((Object)(object)aoi == (Object)null) ? "none, every client receives every instance" : ((object)aoi).GetType().Name));
}
}
}
internal static class InstancePatches
{
internal static void Apply(Harmony harmony)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(MapInstancingManager), "Init_SendPeer_ToScene", (Type[])null, (Type[])null);
if (methodInfo == null)
{
Log.Warn("MapInstancingManager.Init_SendPeer_ToScene is gone, private instances cannot work");
return;
}
try
{
harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(InstancePatches), "Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
catch (Exception ex)
{
Log.Warn("could not patch the instancing manager, " + ex.Message);
}
}
private static bool Prefix(Player _player, string _old, string _new, string _spawnTag, ZoneDifficulty _difficulty)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (!NetworkServer.active || (Object)(object)_player == (Object)null || string.IsNullOrEmpty(_new))
{
return true;
}
bool flag = InstanceRequests.Consume(_player);
if (!flag && !InstanceRegistry.HasAnyFor(_new))
{
return true;
}
InstanceTransport.Begin(_player, _old, _new, _spawnTag, _difficulty, flag);
return false;
}
}
internal static class InstanceTransport
{
private const float FindTimeout = 20f;
private const float ReadyTimeout = 30f;
private const float GateTimeout = 60f;
private static readonly Dictionary<string, int> QueueHolds = new Dictionary<string, int>();
private static bool _loadInFlight;
private static float _loadStarted;
private static MapInstancingManager _bound;
private static void Bind(MapInstancingManager manager)
{
if (!((Object)(object)_bound == (Object)(object)manager))
{
_bound = manager;
_loadInFlight = false;
QueueHolds.Clear();
}
}
private static bool LoadStillInFlight()
{
if (!_loadInFlight)
{
return false;
}
if (Time.realtimeSinceStartup - _loadStarted <= 60f)
{
return true;
}
Log.Warn("a previous instance load never finished, clearing the gate");
_loadInFlight = false;
return false;
}
internal static void Begin(Player player, string oldScene, string newScene, string spawnTag, ZoneDifficulty difficulty, bool forcePrivate)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
MapInstancingManager current = MapInstancingManager._current;
if ((Object)(object)current == (Object)null)
{
Log.Warn("no instancing manager, the transport was dropped");
}
else
{
((MonoBehaviour)current).StartCoroutine(Run(current, player, oldScene, newScene, spawnTag, difficulty, forcePrivate));
}
}
private static IEnumerator Run(MapInstancingManager manager, Player player, string oldScene, string newScene, string spawnTag, ZoneDifficulty difficulty, bool forcePrivate)
{
if ((Object)(object)manager == (Object)null || (Object)(object)player == (Object)null)
{
yield break;
}
Bind(manager);
string who = player._nickname;
Log.Info("transport start, " + who + " to " + newScene + (forcePrivate ? " (private)" : ""));
player.Network_currentGameCondition = (GameCondition)0;
yield return (object)new WaitForSeconds(1.25f);
if ((Object)(object)player == (Object)null)
{
yield break;
}
MapInstance target = (forcePrivate ? null : InstanceRegistry.FindAdmitting(newScene, player));
if ((Object)(object)target == (Object)null && !forcePrivate)
{
target = FindPublic(manager, newScene, player);
}
bool weLoaded = false;
if ((Object)(object)target == (Object)null)
{
float gateWaited = 0f;
while (LoadStillInFlight() && gateWaited < 60f)
{
gateWaited += Time.deltaTime;
yield return null;
}
if (LoadStillInFlight())
{
Restore(player, "another instance is still loading, try again in a moment");
yield break;
}
_loadInFlight = true;
_loadStarted = Time.realtimeSinceStartup;
HoldQueue(manager, newScene);
weLoaded = true;
HashSet<int> before = HandlesFor(newScene);
Log.Info("loading a copy of " + newScene + ", " + before.Count + " already open");
IEnumerator load = LoadCopy(newScene);
while (load.MoveNext())
{
yield return load.Current;
}
Scene loaded = NewSceneFor(newScene, before);
_loadInFlight = false;
if (!((Scene)(ref loaded)).IsValid())
{
ReleaseQueue(manager, newScene);
Restore(player, newScene + " did not load");
yield break;
}
float waited = 0f;
while (waited < 20f)
{
target = FindInScene(manager, loaded);
if ((Object)(object)target != (Object)null)
{
break;
}
waited += Time.deltaTime;
yield return null;
}
if ((Object)(object)target == (Object)null)
{
ReleaseQueue(manager, newScene);
Restore(player, newScene + " loaded but never registered a MapInstance");
yield break;
}
Log.Info("instance ready, " + target._mapName + " handle " + ((Scene)(ref loaded)).handle);
if (forcePrivate)
{
InstanceRegistry.Add(target, newScene, player);
}
}
if ((Object)(object)player == (Object)null)
{
if (weLoaded)
{
ReleaseQueue(manager, newScene);
}
yield break;
}
if (player._isHostPlayer)
{
DropHostColliders(manager, ((Component)player).gameObject.scene);
}
SceneManager.MoveGameObjectToScene(((Component)player).gameObject, SceneManager.GetActiveScene());
yield return (object)new WaitForSeconds(0.45f);
if ((Object)(object)player == (Object)null || (Object)(object)target == (Object)null)
{
if (weLoaded)
{
ReleaseQueue(manager, newScene);
}
yield break;
}
SceneManager.MoveGameObjectToScene(((Component)player).gameObject, target._loadedScene);
((Component)player).transform.SetAsLastSibling();
if (!target._peersInInstance.Contains(player))
{
target._peersInInstance.Add(player);
}
target.SendPeer_ToSpawnPoint(((Component)player).gameObject, spawnTag);
if ((int)target._zoneType != 0)
{
player._statusEntity.Replenish_All();
}
NetworkConnectionToClient conn = ((NetworkBehaviour)player).connectionToClient;
if (conn != null)
{
((NetworkConnection)conn).Send<SceneMessage>(new SceneMessage
{
sceneName = newScene,
sceneOperation = (SceneOperation)1
}, 0);
float readyWaited = 0f;
while (!((NetworkConnection)conn).isReady && readyWaited < 30f)
{
readyWaited += Time.deltaTime;
yield return null;
}
if (!((NetworkConnection)conn).isReady)
{
Log.Warn(who + " never reported ready, continuing anyway");
}
if (!string.IsNullOrEmpty(oldScene) && oldScene != newScene)
{
((NetworkConnection)conn).Send<SceneMessage>(new SceneMessage
{
sceneName = oldScene,
sceneOperation = (SceneOperation)2
}, 0);
}
}
yield return (object)new WaitForSeconds(0.85f);
if ((Object)(object)player != (Object)null && (Object)(object)target != (Object)null)
{
if ((Object)(object)Player._mainPlayer == (Object)(object)player && player._isHostPlayer)
{
target.Spawn_HostCameraColliders();
}
player.Network_playerZoneType = target._zoneType;
player.Network_currentGameCondition = (GameCondition)1;
player.Network_currentPlayerCondition = (PlayerCondition)2;
player._lastSpawnPoint = spawnTag;
Log.Info("transport done, " + who + " is in " + target._mapName);
}
if (weLoaded)
{
ReleaseQueue(manager, newScene);
}
}
private static IEnumerator LoadCopy(string scenePath)
{
AsyncOperation op = null;
try
{
op = SceneManager.LoadSceneAsync(scenePath, new LoadSceneParameters((LoadSceneMode)1, (LocalPhysicsMode)2));
}
catch (Exception ex)
{
Log.Warn("could not start loading " + scenePath + ", " + ex.Message);
}
if (op != null)
{
while (!op.isDone)
{
yield return null;
}
}
}
private static HashSet<int> HandlesFor(string scenePath)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
HashSet<int> hashSet = new HashSet<int>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene sceneAt = SceneManager.GetSceneAt(i);
if (((Scene)(ref sceneAt)).path == scenePath)
{
hashSet.Add(((Scene)(ref sceneAt)).handle);
}
}
return hashSet;
}
private static Scene NewSceneFor(string scenePath, HashSet<int> before)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: 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_0029: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene sceneAt = SceneManager.GetSceneAt(i);
if (((Scene)(ref sceneAt)).path == scenePath && !before.Contains(((Scene)(ref sceneAt)).handle))
{
return sceneAt;
}
}
return default(Scene);
}
private static MapInstance FindPublic(MapInstancingManager manager, string scenePath, Player player)
{
for (int i = 0; i < manager._loadedInstances.Count; i++)
{
MapInstance val = manager._loadedInstances[i];
if ((Object)(object)val == (Object)null || ((Scene)(ref val._loadedScene)).path != scenePath || InstanceRegistry.IsPrivate(val))
{
continue;
}
PatternInstanceManager patternInstance = val._patternInstance;
if ((Object)(object)patternInstance != (Object)null)
{
PartyObjectBehavior network_instanceParty = patternInstance.Network_instanceParty;
if ((Object)(object)network_instanceParty != (Object)null && (Object)(object)player.Network_partyObject != (Object)(object)network_instanceParty)
{
continue;
}
}
return val;
}
return null;
}
private static void DropHostColliders(MapInstancingManager manager, Scene leaving)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < manager._loadedInstances.Count; i++)
{
MapInstance val = manager._loadedInstances[i];
if ((Object)(object)val != (Object)null && val._loadedScene == leaving)
{
val.Destroy_HostCameraColliders();
}
}
}
private static MapInstance FindInScene(MapInstancingManager manager, Scene scene)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < manager._loadedInstances.Count; i++)
{
MapInstance val = manager._loadedInstances[i];
if ((Object)(object)val != (Object)null)
{
Scene scene2 = ((Component)val).gameObject.scene;
if (((Scene)(ref scene2)).handle == ((Scene)(ref scene)).handle)
{
return val;
}
}
}
return null;
}
private static void HoldQueue(MapInstancingManager manager, string scenePath)
{
QueueHolds.TryGetValue(scenePath, out var value);
QueueHolds[scenePath] = value + 1;
if (!manager._instanceQueue.Contains(scenePath))
{
manager._instanceQueue.Add(scenePath);
}
}
private static void ReleaseQueue(MapInstancingManager manager, string scenePath)
{
if (QueueHolds.TryGetValue(scenePath, out var value))
{
value--;
if (value > 0)
{
QueueHolds[scenePath] = value;
return;
}
QueueHolds.Remove(scenePath);
manager._instanceQueue.Remove(scenePath);
}
}
private static void Restore(Player player, string reason)
{
Log.Warn("transport aborted, " + reason);
if (!((Object)(object)player == (Object)null))
{
player.Network_currentGameCondition = (GameCondition)1;
player.Network_currentPlayerCondition = (PlayerCondition)2;
}
}
}