Decompiled source of WorldEditorBridge v1.18.0

plugins/WorldEditorBridge.dll

Decompiled 9 hours ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("WorldEditorBridge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.18.0.0")]
[assembly: AssemblyInformationalVersion("1.18.0+23a5e620b66b3d6f976d3b78820d95deeb7fc9a4")]
[assembly: AssemblyProduct("WorldEditorBridge")]
[assembly: AssemblyTitle("WorldEditorBridge")]
[assembly: AssemblyVersion("1.18.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class BuildInfo
{
	public const string Version = "1.18.0";
}
namespace WorldEditorBridge
{
	[BepInPlugin("Tie.WorldEditorBridge", "WorldEditorBridge", "1.18.0")]
	public sealed class WorldEditorBridgePlugin : BaseUnityPlugin
	{
		private sealed class Job
		{
			public Func<byte[]> Work;

			public byte[] Result;

			public Exception Error;

			public readonly ManualResetEventSlim Done = new ManualResetEventSlim(initialState: false);

			public int State;
		}

		public const string Guid = "Tie.WorldEditorBridge";

		private const string OldGuid = "local.worldeditorbridge";

		public const string Version = "1.18.0";

		private const int SnapshotVersion = 1;

		private ConfigEntry<string> _bind;

		private ConfigEntry<int> _port;

		private ConfigEntry<string> _token;

		private HttpListener _listener;

		private Thread _thread;

		private volatile bool _running;

		private readonly ConcurrentQueue<Job> _jobs = new ConcurrentQueue<Job>();

		private static readonly FieldInfo ObjectsById = typeof(ZDOMan).GetField("m_objectsByID", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo GeneratedZones = typeof(ZoneSystem).GetField("m_generatedZones", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo ZdoRotation = typeof(ZDO).GetField("m_rotation", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo GlobalKeys = typeof(ZoneSystem).GetField("m_globalKeys", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly int TerrainCompilerPrefab = StringExtensionMethods.GetStableHashCode("_TerrainCompiler");

		private static readonly int TombstonePrefab = StringExtensionMethods.GetStableHashCode("Player_tombstone");

		private static readonly FieldInfo ObjectsBySector = typeof(ZDOMan).GetField("m_objectsBySector", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo PortalObjects = typeof(ZDOMan).GetField("m_portalObjects", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly Dictionary<int, bool> Movers = new Dictionary<int, bool>();

		private static readonly Dictionary<int, (ConnectionType Type, ZDOID Source, ZDOID Target)> Links = new Dictionary<int, (ConnectionType, ZDOID, ZDOID)>();

		private void Awake()
		{
			string text = Path.Combine(Paths.ConfigPath, "local.worldeditorbridge.cfg");
			if (File.Exists(text) && !File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
			{
				try
				{
					File.Move(text, ((BaseUnityPlugin)this).Config.ConfigFilePath);
					((BaseUnityPlugin)this).Config.Reload();
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Settings moved from local.worldeditorbridge.cfg to Tie.WorldEditorBridge.cfg");
				}
				catch (IOException ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not move " + text + ": " + ex.Message));
				}
			}
			_bind = ((BaseUnityPlugin)this).Config.Bind<string>("Http", "BindAddress", "127.0.0.1", "Address to listen on. Keep 127.0.0.1 and reach it through an SSH tunnel (ssh -L 5182:127.0.0.1:5182 user@server).");
			_port = ((BaseUnityPlugin)this).Config.Bind<int>("Http", "Port", 5182, "TCP port of the bridge.");
			_token = ((BaseUnityPlugin)this).Config.Bind<string>("Http", "Token", "", "Secret the editor must send (X-Bridge-Token header or ?token=). Generated on first start when empty.");
			if (string.IsNullOrWhiteSpace(_token.Value))
			{
				byte[] array = new byte[18];
				using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create())
				{
					randomNumberGenerator.GetBytes(array);
				}
				_token.Value = Convert.ToBase64String(array).Replace('+', 'A').Replace('/', 'B')
					.TrimEnd(new char[1] { '=' });
				((BaseUnityPlugin)this).Config.Save();
			}
			try
			{
				_listener = new HttpListener();
				_listener.Prefixes.Add($"http://{_bind.Value}:{_port.Value}/");
				if (_bind.Value == "127.0.0.1")
				{
					_listener.Prefixes.Add($"http://localhost:{_port.Value}/");
				}
				_listener.Start();
				_running = true;
				_thread = new Thread(Serve)
				{
					IsBackground = true,
					Name = "WorldEditorBridge"
				};
				_thread.Start();
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("WorldEditorBridge {0} listening on http://{1}:{2}/ (token in BepInEx/config/{3}.cfg)", "1.18.0", _bind.Value, _port.Value, "Tie.WorldEditorBridge"));
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"WorldEditorBridge could not listen on {_bind.Value}:{_port.Value}: {ex2.Message}");
			}
		}

		private void OnDestroy()
		{
			_running = false;
			try
			{
				_listener?.Stop();
			}
			catch
			{
			}
		}

		private void Update()
		{
			for (int i = 0; i < 4; i++)
			{
				if (!_jobs.TryDequeue(out var result))
				{
					break;
				}
				if (Interlocked.CompareExchange(ref result.State, 1, 0) == 0)
				{
					try
					{
						result.Result = result.Work();
					}
					catch (Exception error)
					{
						result.Error = error;
					}
					result.Done.Set();
				}
			}
		}

		private byte[] OnMainThread(Func<byte[]> work, int timeoutMs = 30000)
		{
			Job job = new Job
			{
				Work = work
			};
			_jobs.Enqueue(job);
			if (!job.Done.Wait(timeoutMs))
			{
				if (Interlocked.CompareExchange(ref job.State, 2, 0) == 0)
				{
					throw new TimeoutException("the game did not answer in time");
				}
				job.Done.Wait();
			}
			if (job.Error != null)
			{
				throw job.Error;
			}
			return job.Result;
		}

		private void Serve()
		{
			while (_running)
			{
				HttpListenerContext ctx;
				try
				{
					ctx = _listener.GetContext();
				}
				catch
				{
					if (!_running)
					{
						break;
					}
					continue;
				}
				ThreadPool.QueueUserWorkItem(delegate
				{
					Handle(ctx);
				});
			}
		}

		private void Handle(HttpListenerContext ctx)
		{
			HttpListenerResponse response = ctx.Response;
			try
			{
				if ((ctx.Request.Headers["X-Bridge-Token"] ?? ctx.Request.QueryString["token"]) != _token.Value)
				{
					Reply(response, 401, "text/plain", Encoding.UTF8.GetBytes("bad or missing token"));
					return;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null)
				{
					Reply(response, 503, "text/plain", Encoding.UTF8.GetBytes("no world loaded yet"));
					return;
				}
				if (!ZNet.instance.IsServer())
				{
					Reply(response, 409, "text/plain", Encoding.UTF8.GetBytes("this game is connected to a server: install WorldEditorBridge on that server, or host the world yourself"));
					return;
				}
				switch (ctx.Request.Url.AbsolutePath)
				{
				case "/status":
					Reply(response, 200, "application/json", OnMainThread(Status));
					break;
				case "/players":
					Reply(response, 200, "application/json", OnMainThread(Players));
					break;
				case "/terrain":
				{
					if (ctx.Request.HttpMethod != "POST")
					{
						Reply(response, 405, "text/plain", Encoding.UTF8.GetBytes("POST only"));
						break;
					}
					byte[] body2 = ReadAll(ctx.Request.InputStream);
					Reply(response, 200, "application/json", OnMainThread(() => ApplyTerrain(body2)));
					break;
				}
				case "/objects":
				{
					if (ctx.Request.HttpMethod != "POST")
					{
						Reply(response, 405, "text/plain", Encoding.UTF8.GetBytes("POST only"));
						break;
					}
					byte[] body4 = ReadAll(ctx.Request.InputStream);
					Reply(response, 200, "application/json", OnMainThread(() => ApplyObjects(body4)));
					break;
				}
				case "/zones/reset":
				{
					if (ctx.Request.HttpMethod != "POST")
					{
						Reply(response, 405, "text/plain", Encoding.UTF8.GetBytes("POST only"));
						break;
					}
					byte[] body5 = ReadAll(ctx.Request.InputStream);
					Reply(response, 200, "application/json", OnMainThread(() => ResetZones(body5)));
					break;
				}
				case "/watch":
				{
					if (ctx.Request.HttpMethod != "POST")
					{
						Reply(response, 405, "text/plain", Encoding.UTF8.GetBytes("POST only"));
						break;
					}
					byte[] body3 = ReadAll(ctx.Request.InputStream);
					Reply(response, 200, "application/json", OnMainThread(() => Watch(body3)));
					break;
				}
				case "/zone":
				{
					if (ctx.Request.HttpMethod != "POST")
					{
						Reply(response, 405, "text/plain", Encoding.UTF8.GetBytes("POST only"));
						break;
					}
					byte[] body = ReadAll(ctx.Request.InputStream);
					byte[] array2 = OnMainThread(() => ZoneObjects(body));
					using MemoryStream memoryStream2 = new MemoryStream();
					using (GZipStream gZipStream2 = new GZipStream(memoryStream2, CompressionLevel.Fastest, leaveOpen: true))
					{
						gZipStream2.Write(array2, 0, array2.Length);
					}
					Reply(response, 200, "application/octet-stream", memoryStream2.ToArray());
					break;
				}
				case "/snapshot":
				{
					byte[] array = OnMainThread(Snapshot, 120000);
					using MemoryStream memoryStream = new MemoryStream();
					using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionLevel.Fastest, leaveOpen: true))
					{
						gZipStream.Write(array, 0, array.Length);
					}
					Reply(response, 200, "application/octet-stream", memoryStream.ToArray());
					break;
				}
				default:
					Reply(response, 404, "text/plain", Encoding.UTF8.GetBytes("unknown path"));
					break;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"WorldEditorBridge request {ctx.Request.Url.AbsolutePath} failed: {ex}");
				try
				{
					Reply(response, 500, "text/plain", Encoding.UTF8.GetBytes(ex.Message));
				}
				catch
				{
				}
			}
		}

		private static byte[] ReadAll(Stream s)
		{
			using MemoryStream memoryStream = new MemoryStream();
			s.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private byte[] ApplyTerrain(byte[] body)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage(body);
			int num = val.ReadInt();
			Dictionary<ZDOID, ZDO> obj = (Dictionary<ZDOID, ZDO>)ObjectsById.GetValue(ZDOMan.instance);
			Dictionary<Vector2s, ZDO> dictionary = new Dictionary<Vector2s, ZDO>();
			foreach (ZDO value3 in obj.Values)
			{
				if (value3.GetPrefab() == TerrainCompilerPrefab)
				{
					Vector2s zone = ZoneSystem.GetZone(value3.GetPosition());
					if (!dictionary.TryGetValue(zone, out var value) || value.GetByteArray(ZDOVars.s_TCData, (byte[])null) == null)
					{
						dictionary[zone] = value3;
					}
				}
			}
			int num2 = 0;
			int num3 = 0;
			Vector2s val2 = default(Vector2s);
			for (int i = 0; i < num; i++)
			{
				int num4 = val.ReadInt();
				int num5 = val.ReadInt();
				byte[] array = val.ReadByteArray();
				((Vector2s)(ref val2))..ctor((short)num4, (short)num5);
				if (!dictionary.TryGetValue(val2, out var value2))
				{
					value2 = (dictionary[val2] = CreateTerrainCompiler(val2));
					num3++;
				}
				value2.Set(ZDOVars.s_TCData, array);
				num2++;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"WorldEditorBridge: applied terrain to {num2} zone(s) ({num3} new)");
			return Encoding.UTF8.GetBytes($"{{\"applied\":{num2},\"created\":{num3}}}");
		}

		private byte[] ApplyObjects(byte[] body)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_00ed: 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)
			ZPackage val = new ZPackage(body);
			long sessionID = ZDOMan.GetSessionID();
			int num = val.ReadInt();
			ZDOID[] array = (ZDOID[])(object)new ZDOID[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = new ZDOID(val.ReadLong(), val.ReadUInt());
			}
			int num2 = val.ReadInt();
			Func<ZDO>[] array2 = new Func<ZDO>[num2];
			for (int j = 0; j < num2; j++)
			{
				array2[j] = ReadSaveFormat(new ZPackage(val.ReadByteArray()));
			}
			(int Prefab, Vector3 Position)[] where = null;
			if (val.GetPos() < val.Size())
			{
				where = new(int, Vector3)[num];
				for (int k = 0; k < num; k++)
				{
					where[k] = (Prefab: val.ReadInt(), Position: val.ReadVector3());
				}
			}
			int num3 = 0;
			int num4 = 0;
			List<int> list = new List<int>();
			for (int l = 0; l < num; l++)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(array[l]);
				if (zDO == null)
				{
					list.Add(l);
					continue;
				}
				zDO.SetOwner(sessionID);
				ZDOMan.instance.DestroyZDO(zDO);
				num3++;
			}
			if (list.Count > 0 && where != null)
			{
				num4 = DestroyAtPlace(list.Select((int num7) => where[num7]).ToList(), sessionID);
			}
			int num5 = list.Count - num4;
			StringBuilder stringBuilder = new StringBuilder();
			for (int num6 = 0; num6 < num2; num6++)
			{
				ZDO val2 = array2[num6]();
				if (num6 > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append('"').Append(((ZDOID)(ref val2.m_uid)).UserID.ToString(CultureInfo.InvariantCulture)).Append(':')
					.Append(((ZDOID)(ref val2.m_uid)).ID.ToString(CultureInfo.InvariantCulture))
					.Append('"');
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"WorldEditorBridge: destroyed {num3 + num4} object(s) ({num4} found again at their place under a new id, {num5} already gone), created {num2}");
			return Encoding.UTF8.GetBytes($"{{\"destroyed\":{num3 + num4},\"refound\":{num4},\"missing\":{num5},\"created\":[{stringBuilder}]}}");
		}

		private static int DestroyAtPlace(List<(int Prefab, Vector3 Position)> wanted, long session)
		{
			//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)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<int, List<Vector3>> dictionary = new Dictionary<int, List<Vector3>>();
			foreach (var (key, item) in wanted)
			{
				if (!dictionary.TryGetValue(key, out var value))
				{
					value = (dictionary[key] = new List<Vector3>());
				}
				value.Add(item);
			}
			Dictionary<ZDOID, ZDO> obj = (Dictionary<ZDOID, ZDO>)ObjectsById.GetValue(ZDOMan.instance);
			int num = 0;
			foreach (ZDO item2 in new List<ZDO>(obj.Values))
			{
				if (dictionary.TryGetValue(item2.GetPrefab(), out var value2) && value2.Count != 0)
				{
					Vector3 p = item2.GetPosition();
					int num2 = value2.FindIndex(delegate(Vector3 w)
					{
						//IL_0000: Unknown result type (might be due to invalid IL or missing references)
						//IL_0002: Unknown result type (might be due to invalid IL or missing references)
						//IL_0007: Unknown result type (might be due to invalid IL or missing references)
						//IL_000c: Unknown result type (might be due to invalid IL or missing references)
						Vector3 val = w - p;
						return ((Vector3)(ref val)).sqrMagnitude < 0.01f;
					});
					if (num2 >= 0)
					{
						value2.RemoveAt(num2);
						item2.SetOwner(session);
						ZDOMan.instance.DestroyZDO(item2);
						num++;
					}
				}
			}
			return num;
		}

		private byte[] ResetZones(byte[] body)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage(body);
			int num = val.ReadInt();
			Dictionary<Vector2s, (bool, bool)> dictionary = new Dictionary<Vector2s, (bool, bool)>();
			Vector2s key = default(Vector2s);
			for (int i = 0; i < num; i++)
			{
				((Vector2s)(ref key))..ctor((short)val.ReadInt(), (short)val.ReadInt());
				dictionary[key] = (val.ReadBool(), val.ReadBool());
			}
			Dictionary<ZDOID, ZDO> obj = (Dictionary<ZDOID, ZDO>)ObjectsById.GetValue(ZDOMan.instance);
			long sessionID = ZDOMan.GetSessionID();
			int num2 = 0;
			foreach (ZDO item in new List<ZDO>(obj.Values))
			{
				if (item.Persistent && dictionary.TryGetValue(ZoneSystem.GetZone(item.GetPosition()), out var value))
				{
					int prefab = item.GetPrefab();
					bool flag = prefab == TerrainCompilerPrefab;
					if (prefab != TombstonePrefab && (!flag || value.Item2) && (flag || !value.Item1 || item.GetLong(ZDOVars.s_creator, 0L) == 0L))
					{
						item.SetOwner(sessionID);
						ZDOMan.instance.DestroyZDO(item);
						num2++;
					}
				}
			}
			ZoneSystem instance = ZoneSystem.instance;
			HashSet<Vector2s> hashSet = (HashSet<Vector2s>)GeneratedZones.GetValue(instance);
			int num3 = 0;
			foreach (Vector2s key2 in dictionary.Keys)
			{
				hashSet.Remove(key2);
				if (instance.m_locationInstances.TryGetValue(key2, out var value2) && value2.m_placed)
				{
					value2.m_placed = false;
					instance.m_locationInstances[key2] = value2;
					num3++;
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"WorldEditorBridge: reset {dictionary.Count} zone(s): {num2} object(s) removed, {num3} location(s) to place again");
			return Encoding.UTF8.GetBytes($"{{\"zones\":{dictionary.Count},\"destroyed\":{num2},\"locations\":{num3}}}");
		}

		private static Func<ZDO> ReadSaveFormat(ZPackage p)
		{
			//IL_005f: 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)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_009b: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			int flags = p.ReadUShort();
			Vector3 pos;
			if ((flags & 0x2000) != 0)
			{
				Vector2s val = p.ReadVector2s();
				pos = new Vector3((float)val.x, 0f, (float)val.y);
			}
			else
			{
				pos = p.ReadVector3();
			}
			int prefab = p.ReadInt();
			Vector3 euler = (((flags & 0x1000) != 0) ? p.ReadSmallRotation() : Vector3.zero);
			List<Action<ZDO>> values = new List<Action<ZDO>>();
			ConnectionType linkType = (ConnectionType)0;
			int linkHash = 0;
			if ((flags & 0xFF) != 0)
			{
				if ((flags & 1) != 0)
				{
					linkType = (ConnectionType)p.ReadByte();
					linkHash = p.ReadInt();
				}
				Each(2, delegate(int key)
				{
					float v = p.ReadSingle();
					return delegate(ZDO z)
					{
						z.Set(key, v);
					};
				});
				Each(4, delegate(int key)
				{
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					Vector3 v = p.ReadVector3();
					return delegate(ZDO z)
					{
						//IL_0008: Unknown result type (might be due to invalid IL or missing references)
						z.Set(key, v);
					};
				});
				Each(8, delegate(int key)
				{
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					Quaternion v = p.ReadQuaternion();
					return delegate(ZDO z)
					{
						//IL_0008: Unknown result type (might be due to invalid IL or missing references)
						z.Set(key, v);
					};
				});
				Each(16, delegate(int key)
				{
					int v = p.ReadInt();
					return delegate(ZDO z)
					{
						z.Set(key, v, false);
					};
				});
				Each(32, delegate(int key)
				{
					long v = p.ReadLong();
					return delegate(ZDO z)
					{
						z.Set(key, v);
					};
				});
				Each(64, delegate(int key)
				{
					string v = p.ReadString();
					return delegate(ZDO z)
					{
						z.Set(key, v);
					};
				});
				Each(128, delegate(int key)
				{
					byte[] v = p.ReadByteArray();
					return delegate(ZDO z)
					{
						z.Set(key, v);
					};
				});
			}
			return delegate
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
				ZDO val2 = ZDOMan.instance.CreateNewZDO(pos, prefab);
				val2.Persistent = (flags & 0x100) != 0;
				val2.Distant = (flags & 0x200) != 0;
				val2.Type = (ObjectType)(byte)((flags >> 10) & 3);
				val2.SetPrefab(prefab);
				val2.SetRotation(Quaternion.Euler(euler));
				foreach (Action<ZDO> item in values)
				{
					item(val2);
				}
				if ((int)linkType != 0)
				{
					Relink(val2, linkType, linkHash);
				}
				return val2;
			};
			void Each(int flag, Func<int, Action<ZDO>> read)
			{
				if ((flags & flag) != 0)
				{
					int num = p.ReadNumItems();
					for (int i = 0; i < num; i++)
					{
						values.Add(read(p.ReadInt()));
					}
				}
			}
		}

		private static ZDO CreateTerrainCompiler(Vector2s zone)
		{
			//IL_0028: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = ZNetScene.instance.GetPrefab(TerrainCompilerPrefab);
			ZNetView val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ZNetView>() : null);
			ZDO obj = ZDOMan.instance.CreateNewZDO(ZoneSystem.GetZonePos(zone), TerrainCompilerPrefab);
			obj.Persistent = (Object)(object)val == (Object)null || val.m_persistent;
			obj.Type = (ObjectType)((!((Object)(object)val != (Object)null)) ? 3 : ((int)val.m_type));
			obj.Distant = (Object)(object)val != (Object)null && val.m_distant;
			obj.SetPrefab(TerrainCompilerPrefab);
			return obj;
		}

		private static void Reply(HttpListenerResponse res, int code, string type, byte[] body)
		{
			res.StatusCode = code;
			res.ContentType = type;
			res.ContentLength64 = body.Length;
			res.OutputStream.Write(body, 0, body.Length);
			res.OutputStream.Close();
		}

		private static string Json(string s)
		{
			return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
		}

		private static string F(float v)
		{
			return v.ToString("R", CultureInfo.InvariantCulture);
		}

		private byte[] Status()
		{
			World world = ZNet.World;
			Dictionary<ZDOID, ZDO> dictionary = (Dictionary<ZDOID, ZDO>)ObjectsById.GetValue(ZDOMan.instance);
			string s = string.Format("{{\"plugin\":{0},\"world\":{1},\"seedName\":{2},\"objects\":{3},\"players\":{4},\"netTime\":{5}}}", Json("1.18.0"), Json(world?.m_name ?? ""), Json(world?.m_seedName ?? ""), dictionary.Count, ZNet.instance.GetPlayerList().Count, ZNet.instance.GetTimeSeconds().ToString("R", CultureInfo.InvariantCulture));
			return Encoding.UTF8.GetBytes(s);
		}

		private byte[] Players()
		{
			//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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0063: 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_0077: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder("[");
			bool flag = true;
			foreach (PlayerInfo player in ZNet.instance.GetPlayerList())
			{
				ZDOID characterID = player.m_characterID;
				ZDO val = (((ZDOID)(ref characterID)).IsNone() ? null : ZDOMan.instance.GetZDO(player.m_characterID));
				Vector3 val2 = ((val != null) ? val.GetPosition() : player.m_position);
				float num;
				if (val == null)
				{
					num = 0f;
				}
				else
				{
					Quaternion rotation = val.GetRotation();
					num = ((Quaternion)(ref rotation)).eulerAngles.y;
				}
				float v = num;
				if (!flag)
				{
					stringBuilder.Append(',');
				}
				flag = false;
				stringBuilder.Append("{\"name\":" + Json(player.m_name ?? "") + ",\"x\":" + F(val2.x) + ",\"y\":" + F(val2.y) + ",\"z\":" + F(val2.z) + ",\"yaw\":" + F(v) + "}");
			}
			return Encoding.UTF8.GetBytes(stringBuilder.Append(']').ToString());
		}

		private byte[] Snapshot()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			World world = ZNet.World;
			ZPackage val = new ZPackage();
			val.Write((byte)86);
			val.Write((byte)87);
			val.Write((byte)69);
			val.Write((byte)66);
			val.Write(1);
			val.Write(world.m_name);
			val.Write(world.m_seedName);
			val.Write(world.m_seed);
			val.Write(world.m_worldGenVersion);
			val.Write(ZNet.instance.GetTimeSeconds());
			byte[] array = ZoneSystemData();
			val.Write(array.Length);
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				val.Write(b);
			}
			Dictionary<ZDOID, ZDO> obj = (Dictionary<ZDOID, ZDO>)ObjectsById.GetValue(ZDOMan.instance);
			List<ZDO> list = new List<ZDO>(obj.Count);
			foreach (ZDO value in obj.Values)
			{
				if (value.Persistent)
				{
					list.Add(value);
				}
			}
			Dictionary<ZDOID, (ConnectionType, int)> links = SnapshotLinks();
			val.Write((short)41);
			val.Write(list.Count);
			foreach (ZDO item in list)
			{
				WriteZdo(val, item, links);
			}
			foreach (ZDO item2 in list)
			{
				val.Write(((ZDOID)(ref item2.m_uid)).UserID);
				val.Write(((ZDOID)(ref item2.m_uid)).ID);
			}
			return val.GetArray();
		}

		private static byte[] ZoneSystemData()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			ZoneSystem instance = ZoneSystem.instance;
			ZPackage val = new ZPackage();
			HashSet<Vector2s> hashSet = (HashSet<Vector2s>)GeneratedZones.GetValue(instance);
			val.Write(hashSet.Count);
			foreach (Vector2s item in hashSet)
			{
				val.Write(item);
			}
			val.Write(instance.m_locationVersion);
			HashSet<string> hashSet2 = (HashSet<string>)GlobalKeys.GetValue(instance);
			val.Write(hashSet2.Count);
			foreach (string item2 in hashSet2)
			{
				val.Write(item2);
			}
			val.Write(instance.LocationsGenerated);
			val.Write(instance.m_locationInstances.Count);
			foreach (LocationInstance value in instance.m_locationInstances.Values)
			{
				ZoneLocation location = value.m_location;
				val.Write((location != null) ? StringExtensionMethods.GetStableHashCode(location.m_prefabName) : 0);
				val.Write(value.m_position.x);
				val.Write(value.m_position.y);
				val.Write(value.m_position.z);
				val.Write(value.m_placed);
			}
			return val.GetArray();
		}

		private static List<Vector2s> ReadZones(byte[] body)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage(body);
			int num = val.ReadInt();
			List<Vector2s> list = new List<Vector2s>(num);
			for (int i = 0; i < num; i++)
			{
				int num2 = val.ReadInt();
				int num3 = val.ReadInt();
				if (num2 >= -256 && num2 < 256 && num3 >= -256 && num3 < 256)
				{
					list.Add(new Vector2s(num2, num3));
				}
			}
			return list;
		}

		private static IEnumerable<ZDO> ZoneZdos(Vector2s zone)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			List<ZDO>[] array = (List<ZDO>[])ObjectsBySector.GetValue(ZDOMan.instance);
			Dictionary<SectorIndex, List<ZDO>> dictionary = (Dictionary<SectorIndex, List<ZDO>>)PortalObjects.GetValue(ZDOMan.instance);
			SectorIndex val = ZoneSystem.SectorToIndex(zone);
			IEnumerable<ZDO> enumerable2;
			if (val.Sector < array.Length)
			{
				List<ZDO> list = array[val.Sector];
				if (list != null)
				{
					IEnumerable<ZDO> enumerable = list;
					enumerable2 = enumerable;
					goto IL_0080;
				}
			}
			enumerable2 = Enumerable.Empty<ZDO>();
			goto IL_0080;
			IL_0080:
			IEnumerable<ZDO> enumerable3 = enumerable2;
			if (dictionary != null && dictionary.TryGetValue(val, out var value))
			{
				enumerable3 = enumerable3.Concat(value);
			}
			foreach (ZDO item in enumerable3)
			{
				if (item.Persistent)
				{
					yield return item;
				}
			}
		}

		private static bool Moves(int prefab)
		{
			if (!Movers.TryGetValue(prefab, out var value))
			{
				GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
				value = (Movers[prefab] = (Object)(object)val != (Object)null && ((Object)(object)val.GetComponent<ZSyncTransform>() != (Object)null || (Object)(object)val.GetComponent<Fireplace>() != (Object)null || (Object)(object)val.GetComponent<Smelter>() != (Object)null || (Object)(object)val.GetComponent<CookingStation>() != (Object)null || (Object)(object)val.GetComponent<Beehive>() != (Object)null || (Object)(object)val.GetComponent<Fermenter>() != (Object)null || (Object)(object)val.GetComponent<SapCollector>() != (Object)null));
			}
			return value;
		}

		private byte[] Watch(byte[] body)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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)
			StringBuilder stringBuilder = new StringBuilder("{\"zones\":[");
			bool flag = true;
			foreach (Vector2s item in ReadZones(body))
			{
				ulong num = 0uL;
				foreach (ZDO item2 in ZoneZdos(item))
				{
					int prefab = item2.GetPrefab();
					ulong num2 = (ulong)((((ZDOID)(ref item2.m_uid)).UserID * -7046029254386353131L) ^ (((ZDOID)(ref item2.m_uid)).ID * -4417276706812531889L) ^ ((long)(uint)prefab * 1609587929392839161L));
					num2 ^= (ulong)(Moves(prefab) ? 0 : ((long)item2.DataRevision * 2870177450012600261L + 1));
					num += (ulong)((long)(num2 ^ (num2 >> 29)) * -4658895280553007687L);
				}
				stringBuilder.Append(flag ? "" : ",").Append('[').Append(item.x)
					.Append(',')
					.Append(item.y)
					.Append(",\"")
					.Append(num.ToString(CultureInfo.InvariantCulture))
					.Append("\"]");
				flag = false;
			}
			return Encoding.UTF8.GetBytes(stringBuilder.Append("]}").ToString());
		}

		private byte[] ZoneObjects(byte[] body)
		{
			//IL_001c: 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_0098: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ZDOID, (ConnectionType, int)> links = SnapshotLinks();
			List<(ZDOID, byte[])> list = new List<(ZDOID, byte[])>();
			foreach (Vector2s item in ReadZones(body))
			{
				foreach (ZDO item2 in ZoneZdos(item))
				{
					ZPackage val = new ZPackage();
					WriteZdo(val, item2, links);
					list.Add((item2.m_uid, val.GetArray()));
				}
			}
			ZPackage val2 = new ZPackage();
			val2.Write(list.Count);
			foreach (var item3 in list)
			{
				var (val3, array) = item3;
				val2.Write(((ZDOID)(ref val3)).UserID);
				val2.Write(((ZDOID)(ref val3)).ID);
				val2.Write(array);
			}
			return val2.GetArray();
		}

		private static int LinkHash(ZDOID source)
		{
			return (int)(((uint)(int)(((ZDOID)(ref source)).UserID * 486187739) ^ (((ZDOID)(ref source)).ID * 16777619)) | 1);
		}

		private static Dictionary<ZDOID, (ConnectionType Type, int Hash)> SnapshotLinks()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			//IL_004f: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ZDOID, (ConnectionType, int)> dictionary = new Dictionary<ZDOID, (ConnectionType, int)>();
			List<(ZDOID, ConnectionType, int)> list = new List<(ZDOID, ConnectionType, int)>();
			foreach (ZDOID allConnectionZDOID in ZDOExtraData.GetAllConnectionZDOIDs())
			{
				ZDOConnection connection = ZDOExtraData.GetConnection(allConnectionZDOID);
				if (connection != null && (int)connection.m_type != 0)
				{
					int num = LinkHash(allConnectionZDOID);
					Links[num] = (connection.m_type, allConnectionZDOID, connection.m_target);
					dictionary[allConnectionZDOID] = (connection.m_type, num);
					if (connection.m_target != ZDOID.None)
					{
						list.Add((connection.m_target, (ConnectionType)(connection.m_type | 0x10), num));
					}
				}
			}
			foreach (var (key, item, item2) in list)
			{
				if (!dictionary.ContainsKey(key))
				{
					dictionary[key] = (item, item2);
				}
			}
			return dictionary;
		}

		private static void Relink(ZDO made, ConnectionType type, int hash)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0024: 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_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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00cd: 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_00e1: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			if (!Links.TryGetValue(hash, out (ConnectionType, ZDOID, ZDOID) value))
			{
				return;
			}
			bool flag = (type & 0x10) == 0;
			ZDOID val = (flag ? value.Item2 : value.Item3);
			if (ZDOMan.instance.GetZDO(val) != null)
			{
				return;
			}
			if (flag)
			{
				if (value.Item3 == ZDOID.None || ZDOMan.instance.GetZDO(value.Item3) != null)
				{
					made.SetConnection(value.Item1, value.Item3);
				}
				Links[hash] = (value.Item1, made.m_uid, value.Item3);
			}
			else
			{
				Links[hash] = (value.Item1, value.Item2, made.m_uid);
			}
			foreach (ZDOID allConnectionZDOID in ZDOExtraData.GetAllConnectionZDOIDs())
			{
				ZDOConnection connection = ZDOExtraData.GetConnection(allConnectionZDOID);
				if (connection != null && connection.m_target == val)
				{
					ZDO zDO = ZDOMan.instance.GetZDO(allConnectionZDOID);
					if (zDO != null)
					{
						zDO.UpdateConnection(connection.m_type, made.m_uid);
					}
				}
			}
		}

		private static void WriteZdo(ZPackage pkg, ZDO zdo, Dictionary<ZDOID, (ConnectionType Type, int Hash)> links)
		{
			//IL_000e: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00ed: Expected I4, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_011b: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Expected I4, but got Unknown
			List<KeyValuePair<int, float>> list = default(List<KeyValuePair<int, float>>);
			List<KeyValuePair<int, Vector3>> list2 = default(List<KeyValuePair<int, Vector3>>);
			List<KeyValuePair<int, Quaternion>> list3 = default(List<KeyValuePair<int, Quaternion>>);
			List<KeyValuePair<int, int>> list4 = default(List<KeyValuePair<int, int>>);
			List<KeyValuePair<int, long>> list5 = default(List<KeyValuePair<int, long>>);
			List<KeyValuePair<int, string>> list6 = default(List<KeyValuePair<int, string>>);
			List<KeyValuePair<int, byte[]>> list7 = default(List<KeyValuePair<int, byte[]>>);
			ZDOConnection val = default(ZDOConnection);
			ZDOExtraData.GetData(zdo.m_uid, ref list, ref list2, ref list3, ref list4, ref list5, ref list6, ref list7, ref val);
			int num = 0;
			(ConnectionType, int) value;
			bool flag = links.TryGetValue(zdo.m_uid, out value);
			if (flag)
			{
				num |= 1;
			}
			if (list.Count > 0)
			{
				num |= 2;
			}
			if (list2.Count > 0)
			{
				num |= 4;
			}
			if (list3.Count > 0)
			{
				num |= 8;
			}
			if (list4.Count > 0)
			{
				num |= 0x10;
			}
			if (list5.Count > 0)
			{
				num |= 0x20;
			}
			if (list6.Count > 0)
			{
				num |= 0x40;
			}
			if (list7.Count > 0)
			{
				num |= 0x80;
			}
			if (zdo.Persistent)
			{
				num |= 0x100;
			}
			if (zdo.Distant)
			{
				num |= 0x200;
			}
			num |= (zdo.Type & 3) << 10;
			? val2;
			if (!(ZdoRotation != null))
			{
				Quaternion rotation = zdo.GetRotation();
				val2 = ((Quaternion)(ref rotation)).eulerAngles;
			}
			else
			{
				val2 = (Vector3)ZdoRotation.GetValue(zdo);
			}
			Vector3 val3 = (Vector3)val2;
			int num2;
			if (!(Mathf.Abs(val3.x) > 1E-05f) && !(Mathf.Abs(val3.y) > 1E-05f))
			{
				num2 = ((Mathf.Abs(val3.z) > 1E-05f) ? 1 : 0);
				if (num2 == 0)
				{
					goto IL_0166;
				}
			}
			else
			{
				num2 = 1;
			}
			num |= 0x1000;
			goto IL_0166;
			IL_0166:
			pkg.Write((ushort)num);
			pkg.Write(zdo.GetPosition());
			pkg.Write(zdo.GetPrefab());
			if (num2 != 0)
			{
				pkg.WriteSmallRotation(val3);
			}
			if ((num & 0xFF) != 0)
			{
				if (flag)
				{
					pkg.Write((byte)(int)value.Item1);
					pkg.Write(value.Item2);
				}
				Section(pkg, list, delegate(float v)
				{
					pkg.Write(v);
				});
				Section(pkg, list2, delegate(Vector3 v)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					pkg.Write(v);
				});
				Section(pkg, list3, delegate(Quaternion v)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					pkg.Write(v);
				});
				Section(pkg, list4, delegate(int v)
				{
					pkg.Write(v);
				});
				Section(pkg, list5, delegate(long v)
				{
					pkg.Write(v);
				});
				Section(pkg, list6, delegate(string v)
				{
					pkg.Write(v);
				});
				Section(pkg, list7, delegate(byte[] v)
				{
					pkg.Write(v);
				});
			}
		}

		private static void Section<T>(ZPackage pkg, List<KeyValuePair<int, T>> items, Action<T> write)
		{
			if (items.Count == 0)
			{
				return;
			}
			pkg.WriteNumItems(items.Count);
			foreach (KeyValuePair<int, T> item in items)
			{
				pkg.Write(item.Key);
				write(item.Value);
			}
		}
	}
}