using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("DungeonSplitter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6392a0f7e30095b66aa95d27c39fcad01843c745")]
[assembly: AssemblyProduct("DungeonSplitter")]
[assembly: AssemblyTitle("DungeonSplitter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 DungeonSplitter
{
[BepInPlugin("dungeon_splitter", "Dungeon Splitter", "1.6")]
public class DungeonSplitter : BaseUnityPlugin
{
public const string GUID = "dungeon_splitter";
public const string NAME = "Dungeon Splitter";
public const string VERSION = "1.6";
public static ConfigEntry<string> configAlwaysSend;
public static ConfigEntry<float> configDungeonHeight;
public static float DungeonHeight => configDungeonHeight.Value;
public void Awake()
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
configAlwaysSend = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Always send", "", "List of object ids that are always sent to clients. Separate with commas.");
configAlwaysSend.SettingChanged += delegate
{
DungeonPrefabs.Postfix();
};
configDungeonHeight = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Dungeon height", 1500f, "Height at which the dungeon starts.");
SetupWatcher();
new Harmony("dungeon_splitter").PatchAll();
}
private void OnDestroy()
{
((BaseUnityPlugin)this).Config.Save();
}
private void SetupWatcher()
{
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath));
fileSystemWatcher.Changed += ReadConfigValues;
fileSystemWatcher.Created += ReadConfigValues;
fileSystemWatcher.Renamed += ReadConfigValues;
fileSystemWatcher.IncludeSubdirectories = true;
fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher.EnableRaisingEvents = true;
}
private void ReadConfigValues(object sender, FileSystemEventArgs e)
{
if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
{
return;
}
try
{
((BaseUnityPlugin)this).Config.Reload();
}
catch
{
Debug.LogWarning((object)"Failed to reload config file");
}
}
}
[HarmonyPatch(typeof(ZDOMan), "CreateSyncList")]
public class CreateSyncList
{
private static void Prefix(ZDOPeer peer)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
StateManager.Check(peer.m_peer.m_refPos);
FindObjects.IsSending = true;
}
}
[HarmonyPatch(typeof(ZDOMan), "ReleaseNearbyZDOS")]
public class ReleaseNearbyZDOS
{
private static bool Prefix(ZDOMan __instance, Vector3 refPosition, long uid)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: 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_008d: 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_007d: Unknown result type (might be due to invalid IL or missing references)
StateManager.Check(refPosition);
FindObjects.IsSending = false;
Vector2i zone = ZoneSystem.GetZone(refPosition);
int activeArea = ZoneSystem.instance.m_activeArea;
int num = zone.x - activeArea;
int num2 = zone.y - activeArea;
int num3 = zone.x + activeArea;
int num4 = zone.y + activeArea;
Vector2i val = default(Vector2i);
for (int i = num; i <= num3; i++)
{
for (int j = num2; j <= num4; j++)
{
((Vector2i)(ref val))..ctor(i, j);
int num5 = __instance.SectorToIndex(val);
List<ZDO> value;
if (num5 >= 0)
{
if (__instance.m_objectsBySector[num5] != null)
{
Process(__instance, __instance.m_objectsBySector[num5], val, uid);
}
}
else if (__instance.m_objectsByOutsideSector.TryGetValue(val, out value))
{
Process(__instance, value, val, uid);
}
}
}
return false;
}
private static void Process(ZDOMan zm, List<ZDO> objects, Vector2i zone, long uid)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
foreach (ZDO @object in objects)
{
if (!@object.Persistent)
{
continue;
}
bool flag = @object.m_position.y >= DungeonSplitter.DungeonHeight;
bool flag2 = (flag ? StateManager.InDungeon : StateManager.OnGround);
if (@object.GetOwner() == uid)
{
if (!flag2 || !ZNetScene.InActiveArea(@object.GetSector(), zone))
{
@object.SetOwner(0L);
}
}
else if (flag2 && (!@object.HasOwner() || !IsInPeerSameLevel(zm, flag, @object.GetOwner()) || !zm.IsInPeerActiveArea(@object.GetSector(), @object.GetOwner())) && ZNetScene.InActiveArea(@object.GetSector(), zone))
{
@object.SetOwner(uid);
}
}
}
private static bool IsInPeerSameLevel(ZDOMan zm, bool inDungeon, long uid)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
if (uid == zm.m_sessionID)
{
return ZNet.instance.GetReferencePosition().y >= DungeonSplitter.DungeonHeight == inDungeon;
}
ZNetPeer peer = ZNet.instance.GetPeer(uid);
if (peer != null)
{
return peer.m_refPos.y >= DungeonSplitter.DungeonHeight == inDungeon;
}
return false;
}
}
[HarmonyPatch(typeof(ZNetScene), "CreateDestroyObjects")]
public class CreateDestroyObjects
{
private static double LastCheck;
private static bool AnyNearby;
private static void Prefix()
{
//IL_0024: 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_007b: 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)
if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
return;
}
double netTime = ZNet.instance.m_netTime;
Vector3 pos = ZNet.instance.GetReferencePosition();
if (netTime - LastCheck > 5.0)
{
LastCheck = netTime;
AnyNearby = ZNet.instance.GetPeers().Any((ZNetPeer peer) => peer.IsReady() && Utils.DistanceXZ(peer.m_refPos, pos) < 300f);
}
if (AnyNearby)
{
StateManager.CheckForRemove(pos);
}
else
{
StateManager.Check(pos);
}
FindObjects.IsSending = false;
}
}
[HarmonyPatch(typeof(ZNetScene), "IsAreaReady")]
public class IsAreaReady
{
private static void Prefix(Vector3 point)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
StateManager.Check(point);
FindObjects.IsSending = false;
}
}
[HarmonyPatch(typeof(ZDOMan), "FindObjects")]
public class FindObjects
{
public static HashSet<int> AlwaysSend = new HashSet<int>();
public static HashSet<int> AlwaysLoad = new HashSet<int>();
public static bool IsSending;
private static bool Prefix(ZDOMan __instance, Vector2i sector, List<ZDO> objects)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
int num = __instance.SectorToIndex(sector);
List<ZDO> value;
if (num >= 0)
{
if (__instance.m_objectsBySector[num] != null)
{
objects.AddRange(__instance.m_objectsBySector[num].Where(IsOk).ToList());
return false;
}
}
else if (__instance.m_objectsByOutsideSector.TryGetValue(sector, out value))
{
objects.AddRange(value.Where(IsOk).ToList());
}
return false;
}
public static bool IsOk(ZDO zdo)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
if (!AlwaysLoad.Contains(zdo.m_prefab) && !StateManager.IsSameLevel(zdo.m_position))
{
if (IsSending)
{
return AlwaysSend.Contains(zdo.m_prefab);
}
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ZDOMan), "FindDistantObjects")]
public class FindDistantObjects
{
private static bool Prefix(ZDOMan __instance, Vector2i sector, List<ZDO> objects)
{
//IL_0001: 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)
int num = __instance.SectorToIndex(sector);
if (num >= 0)
{
List<ZDO> list = __instance.m_objectsBySector[num];
if (list == null)
{
return false;
}
objects.AddRange(list.Where((ZDO zdo) => zdo.Distant && StateManager.IsSameLevel(zdo.m_position)).ToList());
return false;
}
if (__instance.m_objectsByOutsideSector.TryGetValue(sector, out var value))
{
objects.AddRange(value.Where((ZDO zdo) => zdo.Distant && StateManager.IsSameLevel(zdo.m_position)).ToList());
}
return false;
}
}
[HarmonyPatch(typeof(ZoneSystem), "Start")]
public class DungeonPrefabs
{
public static int ProxyHash = StringExtensionMethods.GetStableHashCode("LocationProxy");
public static int PlayerHash = StringExtensionMethods.GetStableHashCode("Player");
public static void Postfix()
{
FindObjects.AlwaysLoad = (from prefab in ZNetScene.instance.m_namedPrefabs.Values
where Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<Teleport>())
select StringExtensionMethods.GetStableHashCode(((Object)prefab).name)).ToHashSet();
FindObjects.AlwaysLoad.Add(ProxyHash);
FindObjects.AlwaysSend = (from prefab in ZNetScene.instance.m_namedPrefabs.Values
where Object.op_Implicit((Object)(object)prefab.GetComponent<DungeonGenerator>())
select StringExtensionMethods.GetStableHashCode(((Object)prefab).name)).ToHashSet();
foreach (string item in from str in DungeonSplitter.configAlwaysSend.Value.Split(new char[1] { ',' })
select str.Trim() into str
where !string.IsNullOrEmpty(str)
select str)
{
FindObjects.AlwaysSend.Add(StringExtensionMethods.GetStableHashCode(item));
}
FindObjects.AlwaysSend.Add(PlayerHash);
}
}
public class StateManager
{
public static bool InDungeon;
public static bool OnGround;
public static double LastDungeon;
public static double LastGround;
private const double Delay = 2.5;
public static bool IsSameLevel(Vector3 pos)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
if (!(pos.y >= DungeonSplitter.DungeonHeight))
{
return OnGround;
}
return InDungeon;
}
public static void Check(Vector3 pos)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
OnGround = !(InDungeon = pos.y >= DungeonSplitter.DungeonHeight);
}
public static void CheckForRemove(Vector3 pos)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
bool num = pos.y >= DungeonSplitter.DungeonHeight;
double netTime = ZNet.instance.m_netTime;
if (num)
{
InDungeon = true;
LastDungeon = netTime;
OnGround = netTime - LastGround <= 2.5;
}
else
{
OnGround = true;
LastGround = netTime;
InDungeon = netTime - LastDungeon <= 2.5;
}
}
}
}