Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PerfectFlatten v2.0.1
plugins/PerfectFlatten.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using ModCompatibility; using Splatform; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PerfectFlatten")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.1.0")] [assembly: AssemblyInformationalVersion("2.0.1")] [assembly: AssemblyProduct("PerfectFlatten")] [assembly: AssemblyTitle("PerfectFlatten")] [assembly: AssemblyVersion("2.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PerfectFlatten { [BepInPlugin("local.perfectflatten", "PerfectFlatten", "2.0.1")] [DefaultExecutionOrder(-1000)] public sealed class Plugin : BaseUnityPlugin { private sealed class PendingEdit { public List<Heightmap> Maps; public List<TerrainComp> Compilers; public ZNetView[] Views; public uint[] Revisions; public float StableSince; public float Deadline; } [HarmonyPatch] private static class Buttons { private static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[3] { "GetButton", "GetButtonDown", "GetButtonUp" }; foreach (string text in array) { yield return AccessTools.Method(typeof(ZInput), text, new Type[1] { typeof(string) }, (Type[])null); } } private static bool Prefix(string __0, ref bool __result) { if (!Capture || (__0 != "Attack" && __0 != "JoyAttack" && __0 != "JoyPlace" && __0 != "AutoRun")) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")] private static class Wheel { private static bool Prefix(ref float __result) { if (!Capture || !instance.Ready()) { return true; } __result = 0f; return false; } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static class PreventPlacement { [HarmonyPriority(0)] private static bool Prefix(Player __instance, ref bool __result) { if (!Capture || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Player), "PlacePiece")] private static class PreventDirectPlacement { [HarmonyPriority(0)] private static bool Prefix(Player __instance) { if (Capture) { return (Object)(object)__instance != (Object)(object)Player.m_localPlayer; } return true; } } [HarmonyPatch(typeof(Player), "SetControls")] private static class PreventAttack { private static void Prefix(Player __instance, ref bool __1, ref bool __2, ref bool __10) { if (Capture && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { __1 = false; __2 = false; __10 = false; } } } [Serializable] public sealed class ZoneFile { public int schema = 2; public List<BuildZone> zones = new List<BuildZone>(); } public const string Id = "local.perfectflatten"; private static Plugin instance; private Harmony harmony; private MethodInfo operate; private MethodInfo reload; private MethodInfo takeInput; private bool active; private bool aimed; private bool square = true; private float diameter = 8f; private float targetY; private float nextApply; private Vector3 center; private string status = ""; private PendingEdit pending; private const string Query = "PerfectFlatten_Zones_v2"; private const string Answer = "PerfectFlatten_Answer_v2"; private ZoneFile zoneFile = new ZoneFile(); private ZoneFile preview = new ZoneFile(); private readonly Dictionary<ZRpc, float> peers = new Dictionary<ZRpc, float>(); private readonly Dictionary<ZRpc, float> throttles = new Dictionary<ZRpc, float>(); private ZNet zoneNetwork; private bool zonesLoaded; private bool zonesReady; private bool awaitingApproval; private bool commitApproval; private float nextNetwork; private float nextPreview; private float approvalDeadline; private int approvalId; private string zonePath; private PendingEdit commitRequest; private static bool Capture { get { if (Object.op_Implicit((Object)(object)instance) && instance.active && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return !((Character)Player.m_localPlayer).IsDead(); } return false; } } private void CheckApi() { operate = ApiContract.Method(typeof(TerrainComp), "DoOperation", typeof(void), false, typeof(Vector3), typeof(Vector3), typeof(Settings)); reload = ApiContract.Method(typeof(TerrainComp), "CheckLoad", typeof(void), false); takeInput = ApiContract.Method(typeof(PlayerController), "TakeInput", typeof(bool), false, typeof(bool)); ApiContract.Method(typeof(TerrainComp), "IsOwner", typeof(bool), false); ApiContract.Method(typeof(Heightmap), "GetAndCreateTerrainCompiler", typeof(TerrainComp), false); ApiContract.Method(typeof(Heightmap), "FindHeightmap", typeof(Heightmap), true, typeof(Vector3)); ApiContract.Method(typeof(Heightmap), "FindHeightmap", typeof(void), true, typeof(Vector3), typeof(float), typeof(List<Heightmap>)); ApiContract.Method(typeof(Heightmap), "Poke", typeof(void), false, typeof(int), typeof(bool)); ApiContract.Method(typeof(Heightmap), "WorldToVertex", typeof(void), false, typeof(Vector3), typeof(int).MakeByRefType(), typeof(int).MakeByRefType()); ApiContract.Method(typeof(Heightmap), "GetHeight", typeof(float), false, typeof(int), typeof(int)); ApiContract.Field(typeof(Heightmap), "m_scale", typeof(float)); ApiContract.Field(typeof(Heightmap), "m_width", typeof(int)); string[] array = new string[7] { "m_level", "m_square", "m_raise", "m_smooth", "m_paintCleared", "m_rotation", "m_halfOffset" }; foreach (string name in array) { ApiContract.Field(typeof(Settings), name, typeof(bool)); } ApiContract.Field(typeof(Settings), "m_levelRadius", typeof(float)); ApiContract.Field(typeof(Settings), "m_levelOffset", typeof(float)); ApiContract.Method(typeof(ZNetView), "ClaimOwnership", typeof(void), false); ApiContract.Method(typeof(ZNetView), "GetZDO", typeof(ZDO), false); ApiContract.Method(typeof(ZNetView), "IsOwner", typeof(bool), false); ApiContract.Method(typeof(ZNetView), "IsValid", typeof(bool), false); ApiContract.Method(typeof(ZNet), "IsAdmin", typeof(bool), false, typeof(string)); ApiContract.Method(typeof(PrivateArea), "CheckAccess", typeof(bool), true, typeof(Vector3), typeof(float), typeof(bool), typeof(bool)); array = new string[3] { "GetButton", "GetButtonDown", "GetButtonUp" }; foreach (string name2 in array) { ApiContract.Method(typeof(ZInput), name2, typeof(bool), true, typeof(string)); } ApiContract.Method(typeof(ZInput), "GetMouseScrollWheel", typeof(float), true); ApiContract.Method(typeof(Player), "TryPlacePiece", typeof(bool), false, typeof(Piece)); ApiContract.Method(typeof(Player), "PlacePiece", typeof(void), false, typeof(Piece), typeof(Vector3), typeof(Quaternion), typeof(bool), typeof(bool)); ApiContract.Method(typeof(Player), "SetControls", typeof(void), false, typeof(Vector3), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool)); } private void SetStatus(string message) { status = message; ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0047: 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_0069: 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) instance = this; try { CheckApi(); harmony = new Harmony("local.perfectflatten"); harmony.PatchAll(typeof(Plugin).Assembly); RegisterZoneCommands(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("PerfectFlatten 2.0.1: API checks passed on Valheim " + ((object)Version.CurrentVersion/*cast due to .constrained prefix*/).ToString() + ". Admin-approved zones required.")); if (((object)Version.CurrentVersion/*cast due to .constrained prefix*/).ToString() != "1.0.15") { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Game version not audited for this release. Required API signatures match; gameplay compatibility is not guaranteed."); } } catch (Exception ex) { active = false; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ((Behaviour)this).enabled = false; ((BaseUnityPlugin)this).Logger.LogError((object)("PerfectFlatten disabled before use: " + ex)); } } private bool Ready() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene() || !Object.op_Implicit((Object)(object)Hud.instance) || GameCamera.InFreeFly()) { return false; } if (InventoryGui.IsVisible() || Minimap.IsOpen() || StoreGui.IsVisible() || Hud.IsPieceSelectionVisible() || Hud.InRadial() || PlayerController.HasInputDelay) { return false; } PlayerController component = ((Component)localPlayer).GetComponent<PlayerController>(); if (Object.op_Implicit((Object)(object)component)) { return (bool)takeInput.Invoke(component, new object[1] { false }); } return false; } private void Update() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) ZoneNetworkTick(); if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || ((Character)Player.m_localPlayer).IsDead()) { active = false; aimed = false; pending = null; CancelApproval(); return; } if (active && ZInput.GetKeyDown((KeyCode)27, true)) { active = false; pending = null; CancelApproval(); return; } if (!Ready()) { aimed = false; CancelApproval(); if (pending != null) { pending = null; SetStatus("Anulowano: otwarto menu lub postac nie moze edytowac."); } return; } if (ZInput.GetKeyDown((KeyCode)287, true)) { active = !active; pending = null; CancelApproval(); targetY = ((Component)Player.m_localPlayer).transform.position.y; status = "Aim at terrain. Height stays fixed; Shift+wheel adjusts it; Alt+wheel changes size."; if (active && Aim()) { targetY = center.y; } ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Tool {0}; target Y={1:0.00}", active ? "ON" : "OFF", targetY)); } if (!active || awaitingApproval) { return; } if (pending != null) { try { PollEdit(); return; } catch (Exception ex) { pending = null; active = false; ((BaseUnityPlugin)this).Logger.LogError((object)ex); return; } } aimed = Aim(); if (ZInput.GetKeyDown((KeyCode)113, true)) { square = !square; } Mouse current = Mouse.current; float num = ((current != null) ? ((InputControl<Vector2>)(object)current.scroll).ReadValue().y : 0f); if (num != 0f) { if (ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true)) { targetY = Mathf.Clamp(targetY + Mathf.Sign(num) * 0.25f, -1000f, 3000f); } else { diameter = Mathf.Clamp(diameter + Mathf.Sign(num) * 2f, 2f, 50f); } } Mouse current2 = Mouse.current; if (current2 == null || !current2.leftButton.wasPressedThisFrame || !(Time.unscaledTime >= nextApply)) { return; } if (!aimed) { SetStatus("Nie wykonano: wyceluj w teren do 40 m od postaci."); return; } nextApply = Time.unscaledTime + 0.5f; try { RequestApproval(commit: false); } catch (Exception ex2) { active = false; ((BaseUnityPlugin)this).Logger.LogError((object)ex2); ((BaseUnityPlugin)this).Logger.LogError((object)"Tool disabled after failure. Inspect terrain before continuing; an edit may be partial."); } } private bool Aim() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; RaycastHit val = default(RaycastHit); if (!Object.op_Implicit((Object)(object)main) || !Physics.Raycast(main.ViewportPointToRay(new Vector3(0.5f, 0.5f)), ref val, 60f, LayerMask.GetMask(new string[1] { "terrain" }), (QueryTriggerInteraction)1)) { return false; } Heightmap component = ((Component)((RaycastHit)(ref val)).collider).GetComponent<Heightmap>(); if (!Object.op_Implicit((Object)(object)component) || component.IsDistantLod || Vector3.Distance(((RaycastHit)(ref val)).point, ((Component)Player.m_localPlayer).transform.position) > 40f) { return false; } center = ((RaycastHit)(ref val)).point; center.x = Mathf.Floor(center.x / component.m_scale + 0.5f) * component.m_scale; center.z = Mathf.Floor(center.z / component.m_scale + 0.5f) * component.m_scale; return true; } private void Apply() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Requested {0} size={1:0} m, center={2}, target Y={3:0.00}", square ? "square" : "circle", diameter, center, targetY)); float num = diameter / 2f + 1f; if (!PrivateArea.CheckAccess(center, num * 1.414214f, true, true)) { SetStatus("Nie wykonano: obszar chroniony przez ward."); return; } for (float num2 = 0f - num; num2 <= num; num2 += 1f) { for (float num3 = 0f - num; num3 <= num; num3 += 1f) { Heightmap val = Heightmap.FindHeightmap(center + new Vector3(num2, 0f, num3)); if (!Object.op_Implicit((Object)(object)val) || val.IsDistantLod) { SetStatus("Nie wykonano: caly obszar musi byc zaladowany. Podejdz blizej."); return; } } } List<Heightmap> list = new List<Heightmap>(); Heightmap.FindHeightmap(center, num, list); List<TerrainComp> list2 = new List<TerrainComp>(); foreach (Heightmap item in list) { if (!item.IsDistantLod) { TerrainComp andCreateTerrainCompiler = item.GetAndCreateTerrainCompiler(); if (!Object.op_Implicit((Object)(object)andCreateTerrainCompiler)) { SetStatus("Nie wykonano: brak kompilatora terenu."); return; } if (!list2.Contains(andCreateTerrainCompiler)) { list2.Add(andCreateTerrainCompiler); } } } if (list2.Count == 0) { SetStatus("Nie wykonano: brak terenu."); return; } PendingEdit pendingEdit = new PendingEdit { Maps = list, Compilers = list2, Views = (ZNetView[])(object)new ZNetView[list2.Count], Revisions = new uint[list2.Count], StableSince = Time.unscaledTime, Deadline = Time.unscaledTime + 5f }; for (int i = 0; i < list2.Count; i++) { ZNetView component = ((Component)list2[i]).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { SetStatus("Nie wykonano: dane sieciowe terenu niedostepne."); return; } pendingEdit.Views[i] = component; } for (int j = 0; j < list2.Count; j++) { reload.Invoke(list2[j], null); pendingEdit.Views[j].ClaimOwnership(); pendingEdit.Revisions[j] = pendingEdit.Views[j].GetZDO().DataRevision; } pending = pendingEdit; SetStatus($"Przygotowanie calego obszaru {diameter:0} m ({list2.Count} fragmentow)..."); } private void PollEdit() { //IL_00da: Unknown result type (might be due to invalid IL or missing references) PendingEdit pendingEdit = pending; if (Time.unscaledTime >= pendingEdit.Deadline) { pending = null; SetStatus("Nie wykonano: wlasnosc lub dane obszaru nie ustabilizowaly sie. Sprobuj ponownie."); return; } for (int i = 0; i < pendingEdit.Views.Length; i++) { ZNetView val = pendingEdit.Views[i]; if (!Object.op_Implicit((Object)(object)val) || !val.IsValid() || !Object.op_Implicit((Object)(object)pendingEdit.Compilers[i])) { pending = null; SetStatus("Anulowano: obszar zostal wyladowany."); return; } if (!val.IsOwner()) { pendingEdit.StableSince = Time.unscaledTime; return; } uint dataRevision = val.GetZDO().DataRevision; if (dataRevision != pendingEdit.Revisions[i]) { pendingEdit.Revisions[i] = dataRevision; pendingEdit.StableSince = Time.unscaledTime; } } if (!(Time.unscaledTime - pendingEdit.StableSince < 0.75f)) { pending = null; if (!PrivateArea.CheckAccess(center, (diameter / 2f + 1f) * 1.414214f, true, true)) { SetStatus("Anulowano: brak dostepu do obszaru."); return; } commitRequest = pendingEdit; RequestApproval(commit: true); } } private void ApplyOwned(List<Heightmap> maps, List<TerrainComp> compilers) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_00fd: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) float num = diameter / 2f; foreach (TerrainComp compiler in compilers) { reload.Invoke(compiler, null); } foreach (Heightmap map in maps) { if (!map.IsDistantLod) { map.Poke(0, false); } } foreach (TerrainComp compiler2 in compilers) { if (!compiler2.IsOwner()) { SetStatus("Anulowano: zmienil sie wlasciciel obszaru."); return; } } Settings val = new Settings { m_level = true, m_levelRadius = num, m_levelOffset = 0f, m_square = square, m_raise = false, m_smooth = false, m_paintCleared = false, m_rotation = false, m_halfOffset = false }; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(center.x, targetY, center.z); foreach (TerrainComp compiler3 in compilers) { operate.Invoke(compiler3, new object[3] { val2, Vector3.zero, val }); } ReportResult(maps, num); } private void ReportResult(List<Heightmap> maps, float radius) { //IL_003e: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_011e: Unknown result type (might be due to invalid IL or missing references) int num = 0; int num2 = 0; float num3 = 0f; HashSet<Vector2> hashSet = new HashSet<Vector2>(); int num4 = default(int); int num5 = default(int); Vector2 item = default(Vector2); foreach (Heightmap map in maps) { if (map.IsDistantLod) { continue; } map.Poke(0, false); map.WorldToVertex(center, ref num4, ref num5); float num6 = radius / map.m_scale; int num7 = Mathf.CeilToInt(num6); for (int i = Math.Max(0, num5 - num7); i <= Math.Min(map.m_width, num5 + num7); i++) { for (int j = Math.Max(0, num4 - num7); j <= Math.Min(map.m_width, num4 + num7); j++) { if (!square) { Vector2 val = new Vector2((float)(j - num4), (float)(i - num5)); if (((Vector2)(ref val)).magnitude > num6) { continue; } } ((Vector2)(ref item))..ctor(((Component)map).transform.position.x + (float)(j - map.m_width / 2) * map.m_scale, ((Component)map).transform.position.z + (float)(i - map.m_width / 2) * map.m_scale); if (hashSet.Add(item)) { float num8 = map.GetHeight(j, i) + ((Component)map).transform.position.y - targetY; if (num8 > 0.02f) { num++; } if (num8 < -0.02f) { num2++; } num3 = Mathf.Max(num3, Mathf.Abs(num8)); } } } } status = ((num + num2 == 0) ? "Wyrownano teren do zadanej wysokosci." : ($"Niepelne wyrownanie: {num} punktow za wysoko, {num2} za nisko (max {num3:0.00} m).\n" + "Limit gry +/-8 m lub inny mod. Powtarzanie klikniec nie znosi limitu.")); ((BaseUnityPlugin)this).Logger.LogInfo((object)status); } private void OnGUI() { //IL_0025: 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_00a5: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (!active || !Ready()) { return; } GUI.Box(new Rect(20f, 80f, 740f, 150f), string.Format("PerfectFlatten | {0}: {1:0} m | Y: {2:0.00} m\n", square ? "Square side" : "Circle diameter", diameter, targetY) + "F6 / Esc: exit | Alt+wheel / Wheel: size | Shift+wheel: height | Q: shape | LMB: flatten\n" + (aimed ? (ZoneHint() + "\n" + status) : "Aim at terrain within 40 m.")); if (aimed && (int)Event.current.type == 7 && Object.op_Implicit((Object)(object)Camera.main)) { int num = (square ? 4 : 64); for (int i = 0; i < num; i++) { DrawEdge(Point(i, num), Point((i + 1) % num, num)); } } } private Vector3 Point(int i, int n) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) float num = diameter / 2f; if (square) { return new Vector3(center.x + ((i == 0 || i == 3) ? (0f - num) : num), targetY, center.z + ((i < 2) ? (0f - num) : num)); } float num2 = (float)i * MathF.PI * 2f / (float)n; return new Vector3(center.x + Mathf.Cos(num2) * num, targetY, center.z + Mathf.Sin(num2) * num); } private void DrawEdge(Vector3 a, Vector3 b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0035: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_008b: 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_00a4: 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_00b0: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; Vector3 val = main.WorldToScreenPoint(a); Vector3 val2 = main.WorldToScreenPoint(b); if (!(val.z < main.nearClipPlane) && !(val2.z < main.nearClipPlane)) { Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(val.x, (float)Screen.height - val.y); Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(val2.x, (float)Screen.height - val2.y); Matrix4x4 matrix = GUI.matrix; Color color = GUI.color; GUI.color = Color.cyan; GUIUtility.RotateAroundPivot(Mathf.Atan2(val4.y - val3.y, val4.x - val3.x) * 57.29578f, val3); GUI.DrawTexture(new Rect(val3.x, val3.y, Vector2.Distance(val3, val4), 2f), (Texture)(object)Texture2D.whiteTexture); GUI.matrix = matrix; GUI.color = color; } } private void OnDestroy() { ClearZoneNetwork(); active = false; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private void CancelApproval() { awaitingApproval = false; commitRequest = null; approvalId++; } private void ClearZoneNetwork() { foreach (ZRpc key in peers.Keys) { key.Unregister("PerfectFlatten_Zones_v2"); key.Unregister("PerfectFlatten_Answer_v2"); } peers.Clear(); throttles.Clear(); CancelApproval(); pending = null; active = false; zonesLoaded = (zonesReady = false); zoneNetwork = null; nextNetwork = (nextPreview = 0f); zoneFile = new ZoneFile(); preview = new ZoneFile(); } private void LoadZones() { if (zonesLoaded || !Object.op_Implicit((Object)(object)zoneNetwork) || !zoneNetwork.IsServer() || ZNet.World == null) { return; } zonePath = Path.Combine(Paths.ConfigPath, "PerfectFlatten", "world-" + ZNet.World.m_uid + ".zones.json"); try { zoneFile = (File.Exists(zonePath) ? JsonUtility.FromJson<ZoneFile>(File.ReadAllText(zonePath)) : new ZoneFile()); if (zoneFile == null || zoneFile.schema != 2 || zoneFile.zones == null || zoneFile.zones.Count > 100 || zoneFile.zones.Any((BuildZone z) => z == null || !ValidName(z.name) || !ZoneRules.Finite(z.x) || !ZoneRules.Finite(z.z) || !ZoneRules.Finite(z.radius) || z.radius < 5f || z.radius > 200f)) { throw new InvalidDataException("Invalid zone file"); } zonesReady = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Building zones loaded: " + zoneFile.zones.Count + "; " + zonePath)); } catch (Exception ex) { zonesReady = false; ((BaseUnityPlugin)this).Logger.LogError((object)("Zone loading failed; edits blocked: " + ex.Message)); } zonesLoaded = true; } private void SaveZones(ZoneFile updated) { Directory.CreateDirectory(Path.GetDirectoryName(zonePath)); string text = zonePath + ".tmp"; File.WriteAllText(text, JsonUtility.ToJson((object)updated, true)); if (File.Exists(zonePath)) { File.Replace(text, zonePath, zonePath + ".bak"); } else { File.Move(text, zonePath); } zoneFile = updated; } private static bool ValidName(string name) { if (name != null) { return Regex.IsMatch(name, "^[A-Za-z0-9_-]{1,40}$"); } return false; } private void ZoneNetworkTick() { if ((Object)(object)zoneNetwork != (Object)(object)ZNet.instance) { ClearZoneNetwork(); } zoneNetwork = ZNet.instance; if (awaitingApproval && Time.unscaledTime > approvalDeadline) { CancelApproval(); SetStatus("Brak odpowiedzi serwera. Edycja zablokowana."); } if (!Object.op_Implicit((Object)(object)zoneNetwork) || Time.unscaledTime < nextNetwork) { return; } nextNetwork = Time.unscaledTime + 0.25f; LoadZones(); HashSet<ZRpc> hashSet = new HashSet<ZRpc>(); foreach (ZNetPeer peer in zoneNetwork.GetPeers()) { if (!peer.IsReady()) { continue; } ZRpc rpc = peer.m_rpc; hashSet.Add(rpc); if (!peers.ContainsKey(rpc)) { peers.Add(rpc, Time.unscaledTime); if (zoneNetwork.IsServer()) { rpc.Register<ZPackage>("PerfectFlatten_Zones_v2", (Action<ZRpc, ZPackage>)HandleQuery); } else { rpc.Register<ZPackage>("PerfectFlatten_Answer_v2", (Action<ZRpc, ZPackage>)HandleAnswer); } } } ZRpc[] array = peers.Keys.ToArray(); foreach (ZRpc val in array) { if (!hashSet.Contains(val)) { val.Unregister("PerfectFlatten_Zones_v2"); val.Unregister("PerfectFlatten_Answer_v2"); peers.Remove(val); throttles.Remove(val); } } if (!zoneNetwork.IsServer() && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Time.unscaledTime >= nextPreview && !awaitingApproval) { nextPreview = Time.unscaledTime + 5f; Send("policy", 0, ""); } } private void RegisterZoneCommands() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0020: 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_004b: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand("pf_zone_add", "name radius [Platform_UserID] - admin, zone at your position", (ConsoleEvent)delegate(ConsoleEventArgs args) { if (args.Args.Length < 3 || args.Args.Length > 4) { args.Context.AddString("pf_zone_add DomKawula 40 [Steam_...]"); } else { Send("add", 0, string.Join(" ", args.Args.Skip(1))); } }, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); new ConsoleCommand("pf_zone_remove", "name - admin removes a zone", (ConsoleEvent)delegate(ConsoleEventArgs args) { if (args.Args.Length != 2) { args.Context.AddString("pf_zone_remove DomKawula"); } else { Send("remove", 0, args.Args[1]); } }, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); new ConsoleCommand("pf_zone_list", "list approved building zones", (ConsoleEvent)delegate { Send("list", 0, ""); }, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void Send(string action, int id, string text) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { SetStatus("Dolacz do swiata postacia."); return; } ZoneNetworkTick(); ZPackage val = new ZPackage(); val.Write(action); val.Write(id); val.Write(text); if (action == "edit") { val.Write(center); val.Write(targetY); val.Write(diameter); val.Write(square); } if (zoneNetwork.IsServer()) { val.SetPos(0); HandleQuery(null, val); return; } ZRpc serverRPC = zoneNetwork.GetServerRPC(); if (serverRPC == null) { SetStatus("Brak polaczenia z serwerem."); return; } serverRPC.Invoke("PerfectFlatten_Zones_v2", new object[1] { val }); } private bool Actor(ZRpc rpc, out Vector3 position, out string identity, out bool admin) { //IL_000e: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; identity = ""; admin = false; if (rpc == null) { if (!zoneNetwork.IsServer() || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return false; } position = ((Component)Player.m_localPlayer).transform.position; identity = ((object)Unsafe.As<PlatformUserID, PlatformUserID>(ref UserInfo.GetLocalUser().UserId)/*cast due to .constrained prefix*/).ToString(); admin = true; return true; } ZNetPeer val = ((IEnumerable<ZNetPeer>)zoneNetwork.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc && p.IsReady())); if (val == null) { return false; } ZDO zDO = ZDOMan.instance.GetZDO(val.m_characterID); if (zDO == null) { return false; } position = zDO.GetPosition(); identity = val.m_socket.GetHostName(); admin = zoneNetwork.IsAdmin(identity); return true; } private unsafe void HandleQuery(ZRpc rpc, ZPackage data) { //IL_010e: 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_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)zoneNetwork) || !zoneNetwork.IsServer()) { return; } string text = ""; int id = 0; try { text = data.ReadString(); id = data.ReadInt(); string text2 = data.ReadString(); if (text2.Length > 200) { return; } if (text == "edit" && rpc != null) { if (throttles.TryGetValue(rpc, out var value) && Time.unscaledTime - value < 0.1f) { return; } throttles[rpc] = Time.unscaledTime; } LoadZones(); if (!zonesReady) { Respond(rpc, text, id, ok: false, "Strefy niedostepne; edycja zablokowana."); return; } if (!Actor(rpc, out var playerPos, out var identity, out var admin)) { Respond(rpc, text, id, ok: false, "Serwer nie rozpoznal postaci."); return; } switch (text) { case "edit": { Vector3 point = data.ReadVector3(); float num = data.ReadSingle(); float size = data.ReadSingle(); bool box = data.ReadBool(); bool flag = ZoneRules.Finite(point.x) && ZoneRules.Finite(point.y) && ZoneRules.Finite(point.z) && ZoneRules.Finite(num) && num >= -1000f && num <= 3000f && ZoneRules.Finite(size) && size >= 2f && size <= 50f && Vector3.Distance(playerPos, point) <= 42f && this.zoneFile.zones.Any((BuildZone z) => (string.IsNullOrEmpty(z.player) || z.player == identity) && ZoneRules.Contains(z, playerPos.x, playerPos.z, 2f, square: false) && ZoneRules.Contains(z, point.x, point.z, size, box)); Respond(rpc, text, id, flag, flag ? "Zgoda serwera." : "Odmowa: postac i CALY obrys musza byc w jednej dozwolonej strefie."); ManualLogSource logger = ((BaseUnityPlugin)this).Logger; string[] obj = new string[6] { "Zone edit ", flag ? "approved" : "denied", " for ", identity, " at ", null }; Vector3 val = point; obj[5] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); logger.LogInfo((object)string.Concat(obj)); return; } case "policy": Respond(rpc, text, id, ok: true, ""); return; case "list": { string text3 = string.Join("\n", this.zoneFile.zones.Select((BuildZone z) => z.name + ": X=" + z.x.ToString("0", CultureInfo.InvariantCulture) + " Z=" + z.z.ToString("0", CultureInfo.InvariantCulture) + " promien=" + z.radius + "m; gracz=" + (string.IsNullOrEmpty(z.player) ? "wszyscy" : z.player))); Respond(rpc, text, id, ok: true, (text3.Length == 0) ? "Brak stref. Administrator: pf_zone_add nazwa promien" : text3); return; } } if (!admin) { Respond(rpc, text, id, ok: false, "Tylko administrator serwera moze zmieniac strefy."); return; } ZoneFile zoneFile = new ZoneFile { zones = new List<BuildZone>(this.zoneFile.zones) }; if (text == "add") { string[] parts = text2.Split(' '); if (parts.Length < 2 || parts.Length > 3 || !ValidName(parts[0]) || !float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !ZoneRules.Finite(result) || result < 5f || result > 200f || zoneFile.zones.Count >= 100) { Respond(rpc, text, id, ok: false, "Nazwa: litery/cyfry/_/-. Promien: 5-200 m, max 100 stref."); return; } if (zoneFile.zones.Any((BuildZone z) => z.name.Equals(parts[0], StringComparison.OrdinalIgnoreCase))) { Respond(rpc, text, id, ok: false, "Nazwa juz istnieje. Najpierw usun stara strefe."); return; } zoneFile.zones.Add(new BuildZone { name = parts[0], x = playerPos.x, z = playerPos.z, radius = result, player = ((parts.Length == 3) ? parts[2] : "") }); } else { if (!(text == "remove")) { return; } if (zoneFile.zones.RemoveAll((BuildZone z) => z.name.Equals(text2, StringComparison.OrdinalIgnoreCase)) == 0) { Respond(rpc, text, id, ok: false, "Nie znaleziono strefy."); return; } } SaveZones(zoneFile); Respond(rpc, text, id, ok: true, "Zapisano strefy serwera."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Zones changed by " + identity + ": " + text + " " + text2)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); Respond(rpc, text, id, ok: false, "Blad serwera; operacja odrzucona."); } } private void Respond(ZRpc rpc, string action, int id, bool ok, string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(action); val.Write(id); val.Write(ok); val.Write(message); val.Write(zonesReady ? JsonUtility.ToJson((object)zoneFile) : ""); if (rpc == null) { val.SetPos(0); HandleAnswer(null, val); } else { rpc.Invoke("PerfectFlatten_Answer_v2", new object[1] { val }); } } private void HandleAnswer(ZRpc rpc, ZPackage data) { //IL_00fe: 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_0116: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)zoneNetwork) || (zoneNetwork.IsServer() ? (rpc != null) : (rpc != zoneNetwork.GetServerRPC()))) { return; } try { string text = data.ReadString(); int num = data.ReadInt(); bool flag = data.ReadBool(); string text2 = data.ReadString(); string text3 = data.ReadString(); if (text3.Length > 100000) { return; } preview = ((text3.Length > 0) ? JsonUtility.FromJson<ZoneFile>(text3) : new ZoneFile()); if (text == "edit") { if (!awaitingApproval || num != approvalId) { return; } awaitingApproval = false; if (!flag || !active || !Ready() || Time.unscaledTime > approvalDeadline) { commitRequest = null; SetStatus(flag ? "Anulowano edycje." : text2); return; } if (Vector3.Distance(((Component)Player.m_localPlayer).transform.position, center) > 40f || !PrivateArea.CheckAccess(center, (diameter / 2f + 1f) * 1.414214f, true, true)) { commitRequest = null; SetStatus("Anulowano: zasieg lub ward."); return; } if (!commitApproval) { Apply(); return; } PendingEdit pendingEdit = commitRequest; commitRequest = null; if (pendingEdit == null || pendingEdit.Compilers.Any((TerrainComp c) => !Object.op_Implicit((Object)(object)c) || !c.IsOwner()) || pendingEdit.Maps.Any((Heightmap m) => !Object.op_Implicit((Object)(object)m))) { SetStatus("Anulowano: zmienily sie dane terenu."); } else { ApplyOwned(pendingEdit.Maps, pendingEdit.Compilers); } } else if (text != "policy") { SetStatus(text2); if (Object.op_Implicit((Object)(object)Console.instance)) { ((Terminal)Console.instance).AddString(text2); } } } catch (Exception ex) { CancelApproval(); pending = null; active = false; ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } private void RequestApproval(bool commit) { if (!commit && !zonesReady && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { LoadZones(); } awaitingApproval = true; commitApproval = commit; approvalDeadline = Time.unscaledTime + 5f; approvalId++; SetStatus("Sprawdzanie zgody serwera..."); Send("edit", approvalId, ""); } private string ZoneHint() { ZoneFile zoneFile = ((Object.op_Implicit((Object)(object)zoneNetwork) && zoneNetwork.IsServer()) ? this.zoneFile : preview); if (zoneFile == null || zoneFile.zones == null || !zoneFile.zones.Any((BuildZone z) => ZoneRules.Contains(z, center.x, center.z, diameter, square))) { return "POZA STREFA lub obrys za duzy. Edycja zablokowana."; } return "Obrys w strefie budowy. Dostep potwierdza serwer."; } } [Serializable] public sealed class BuildZone { public string name; public string player; public float x; public float z; public float radius; } public static class ZoneRules { public static bool Finite(float v) { if (!float.IsNaN(v)) { return !float.IsInfinity(v); } return false; } public static bool Contains(BuildZone zone, float x, float z, float diameter, bool square) { if (zone == null || !Finite(zone.x) || !Finite(zone.z) || !Finite(zone.radius) || zone.radius <= 0f || !Finite(x) || !Finite(z) || !Finite(diameter) || diameter < 2f || diameter > 50f) { return false; } double num = (double)diameter / 2.0 + 1.0; double num2 = Math.Abs(x - zone.x); double num3 = Math.Abs(z - zone.z); if (!square) { return Math.Sqrt(num2 * num2 + num3 * num3) + num <= (double)zone.radius; } return (num2 + num) * (num2 + num) + (num3 + num) * (num3 + num) <= (double)(zone.radius * zone.radius); } } } namespace ModCompatibility { internal static class ApiContract { private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; internal static MethodInfo Method(Type owner, string name, Type result, bool isStatic, params Type[] arguments) { MethodInfo method = owner.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, arguments, null); if (method == null || method.ReturnType != result || method.IsStatic != isStatic || method.ContainsGenericParameters) { throw new MissingMethodException("Incompatible API: " + owner.FullName + "." + name + " (arguments, result or static/instance changed)"); } return method; } internal static void Field(Type owner, string name, Type type, bool isStatic = false) { FieldInfo field = owner.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != type || field.IsStatic != isStatic) { throw new MissingFieldException("Incompatible API: " + owner.FullName + "." + name + " (field type or static/instance changed)"); } } } }