Decompiled source of Valheim Ultimate DevTool v0.3.3

plugins/ValheimCheatMenu.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[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("ValheimCheatMenu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Valheim Ultimate DevTool")]
[assembly: AssemblyFileVersion("0.3.3.0")]
[assembly: AssemblyInformationalVersion("0.3.3")]
[assembly: AssemblyProduct("ValheimCheatMenu")]
[assembly: AssemblyTitle("ValheimCheatMenu")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.3.0")]
[module: UnverifiableCode]
[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 ValheimCheatMenu
{
	[BepInPlugin("com.valheimcheatmenu.local", "Valheim Ultimate DevTool", "0.3.3")]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class BaseRestoreSlot
		{
			internal int Index;

			internal EditState State;
		}

		private sealed class BaseRestorePlan
		{
			internal BaseSnapshot Snapshot;

			internal ZNetScene Scene;

			internal long Player;

			internal int Present;

			internal int Blocked;

			internal List<BaseRestoreSlot> Missing = new List<BaseRestoreSlot>();

			internal Dictionary<int, ZDOID> Existing = new Dictionary<int, ZDOID>();
		}

		private sealed class DeletedBuilding
		{
			internal Piece Original;

			internal Piece Restored;

			internal bool RestoredOnce;

			internal ZDOID Id;

			internal ZDOID RestoredId;

			internal ZDO Zdo;

			internal EditState State;

			internal readonly HashSet<ZDOID> ExistingAnchors = new HashSet<ZDOID>();
		}

		private sealed class BuildingDeletion
		{
			internal long World;

			internal long Player;

			internal ZNetScene Scene;

			internal int Skipped;

			internal readonly List<DeletedBuilding> Records = new List<DeletedBuilding>();
		}

		private sealed class EditState
		{
			internal GameObject Prefab;

			internal Vector3 Position;

			internal Vector3 Scale;

			internal Quaternion Rotation;

			internal float Health;

			internal float Maximum;

			internal int? DoorState;

			internal long Creator;

			internal int CreatorIndex;

			internal List<KeyValuePair<int, float>> Floats = new List<KeyValuePair<int, float>>();

			internal List<KeyValuePair<int, Vector3>> Vectors = new List<KeyValuePair<int, Vector3>>();

			internal List<KeyValuePair<int, Quaternion>> Quaternions = new List<KeyValuePair<int, Quaternion>>();

			internal List<KeyValuePair<int, int>> Ints = new List<KeyValuePair<int, int>>();

			internal List<KeyValuePair<int, long>> Longs = new List<KeyValuePair<int, long>>();

			internal List<KeyValuePair<int, string>> Strings = new List<KeyValuePair<int, string>>();

			internal List<KeyValuePair<int, byte[]>> Bytes = new List<KeyValuePair<int, byte[]>>();
		}

		private sealed class EditChange
		{
			internal Piece Current;

			internal ZDO LiveZdo;

			internal EditState Before;

			internal EditState After;

			internal bool Replacement;

			internal bool Placement;
		}

		private sealed class BuildingFuel
		{
			internal Piece Piece;

			internal Component Device;

			internal float Maximum;

			internal ItemDrop[] Fuels;

			internal string Kind;

			internal MethodInfo Setter;
		}

		private sealed class BuildingRepairRecord
		{
			internal Piece Piece;

			internal ZDO Zdo;

			internal float Before;

			internal float After;
		}

		private sealed class BuildingUndo
		{
			internal string Name;

			internal List<Piece> Selection;

			internal List<ZDOID> SelectionIds;

			internal List<BuildingRepairRecord> Repairs;

			internal List<EditChange> Edits;

			internal List<TerrainUndo> Terrain;

			internal BuildingDeletion Deleted;

			internal HammerPlacedPiece HammerPlacement;

			internal Func<bool> Restore;
		}

		private sealed class BuildingJob
		{
			internal bool Fuel;

			internal List<Piece> Pieces;

			internal int Index;

			internal int Changed;

			internal int Skipped;

			internal int Full;

			internal Vector3 Center;

			internal float Radius;

			internal readonly List<BuildingRepairRecord> Repairs = new List<BuildingRepairRecord>();
		}

		[HarmonyPatch(typeof(Attack), "Start")]
		private static class CreatureLookAttackPatch
		{
			private static void Postfix(Humanoid character, bool __result)
			{
				Plugin creatureAttackPlugin = _creatureAttackPlugin;
				if (__result && !((Object)(object)creatureAttackPlugin == (Object)null) && !((Object)(object)character == (Object)null) && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && !((Object)(object)character != (Object)(object)creatureAttackPlugin._creatureLookOwner))
				{
					PlayCreatureLookAttack(creatureAttackPlugin._creatureAttackAnimators);
					ZNetView component = ((Component)character).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner())
					{
						ZDO zDO = component.GetZDO();
						zDO.Set(CreatureAttackKey, zDO.GetInt(CreatureAttackKey, 0) + 1, false);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Character), "OnDeath")]
		private static class WaveDeath
		{
			private static void Postfix(Character __instance)
			{
				if ((Object)(object)WaveTools != (Object)null)
				{
					WaveTools._waveActors.Remove(__instance);
				}
			}
		}

		private sealed class EffectEntry
		{
			public StatusEffect Template;

			public string Name;

			public string Key;

			public int Hash;
		}

		private sealed class AppliedEffectTimer
		{
			public SEMan Owner;

			public StatusEffect Effect;

			public float Until;
		}

		private sealed class EquipmentSlot
		{
			public string Id;

			public string Prefab;

			public string Name;
		}

		private sealed class EquipmentSet
		{
			public string Id;

			public string Name;

			public long Owner;

			public List<EquipmentSlot> Items = new List<EquipmentSlot>();
		}

		private sealed class EspRig
		{
			public Character Owner;

			public Collider Collider;

			public SkinnedMeshRenderer Body;

			public readonly List<KeyValuePair<Transform, Transform>> Links = new List<KeyValuePair<Transform, Transform>>();

			public float RefreshAt;
		}

		private sealed class HammerPlacedPiece
		{
			internal ZDOID Id;
		}

		private readonly struct HudKeyRow
		{
			internal readonly string Key;

			internal readonly string Russian;

			internal readonly string English;

			internal HudKeyRow(string key, string russian, string english)
			{
				Key = key;
				Russian = russian;
				English = english;
			}
		}

		private struct ButtonMotion
		{
			internal float Hover;

			internal float Selection;

			internal float UpdatedAt;

			internal float ClickedAt;
		}

		private sealed class MenuFeature
		{
			public string Id;

			public string Name;

			public string Description;

			public string Aliases;

			public string Section;

			public string Page;

			public bool Toggle;

			public ConfigEntry<KeyboardShortcut> Binding;
		}

		private sealed class ShellPage
		{
			public string Section;

			public string Name;

			public string Hint;

			public int LegacyTab;

			public Action<Rect> Draw;
		}

		private sealed class ItemSearchEntry
		{
			public GameObject Prefab;

			public string PrefabName;

			public string DisplayName;

			public string TokenName;

			public ItemType ItemType;

			public Sprite Icon;

			public int MaxStackSize;

			public string Description;

			public bool IsFood;

			public bool IsTrophy;
		}

		private sealed class SpawnCreatureEntry
		{
			public GameObject Prefab;

			public string PrefabName;

			public string DisplayName;

			public float BaseHealth;

			public bool IsBoss;

			public string Resistances;
		}

		private sealed class WorldMapMarker
		{
			public Vector3 Position;

			public string Name;

			public string Kind;

			public string Key;

			public string IconName;
		}

		private sealed class RemoteCreatureLook
		{
			internal string Prefab;

			internal GameObject Root;

			internal GameObject Model;

			internal GameObject Visual;

			internal ZDO Data;

			internal int LastAttack;

			internal (Animator Animator, bool SideSpeed, bool Grounded)[] Locomotion;

			internal (Animator Animator, int Trigger)[] Attacks;

			internal readonly HashSet<Renderer> Hidden = new HashSet<Renderer>();
		}

		private sealed class SavedTeleport
		{
			public string Id;

			public string Name;

			public long World;

			public Vector3 Position;

			public float Yaw;

			public int Icon;

			public bool Visible = true;

			public SavedTeleport Copy()
			{
				return (SavedTeleport)MemberwiseClone();
			}

			public bool Matches(SavedTeleport other)
			{
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				if (other != null && Id == other.Id && World == other.World && Name == other.Name && ((Vector3)(ref Position)).Equals(other.Position) && Yaw.Equals(other.Yaw) && Icon == other.Icon)
				{
					return Visible == other.Visible;
				}
				return false;
			}
		}

		private sealed class SkillLevelDraft
		{
			public int Level;

			public bool Dirty;
		}

		private sealed class StorageResult
		{
			public Container Chest;

			public string Name;

			public string Contents;

			public List<ItemData> Items;

			public int Stacks;

			public long Count;

			public float Distance;
		}

		private sealed class TerrainVertex
		{
			internal int Index;

			internal float BeforeLevel;

			internal float BeforeSmooth;

			internal float AfterLevel;

			internal float AfterSmooth;

			internal bool BeforeModified;

			internal bool AfterModified;
		}

		private sealed class TerrainUndo
		{
			internal TerrainComp Compiler;

			internal Heightmap Map;

			internal ZDO Zdo;

			internal Vector3 Point;

			internal float BoundsRadius;

			internal readonly List<TerrainVertex> Vertices = new List<TerrainVertex>();

			internal readonly List<TerrainMaskChange> Mask = new List<TerrainMaskChange>();

			internal bool MaskApplied;

			internal CultivatorBiomePaint.BrushStamp Cover;

			internal List<Heightmap> CoverMaps;

			internal int ChangeCount => Vertices.Count + (MaskApplied ? Mask.Count : 0) + (Cover?.Changes.Count ?? 0);
		}

		private struct TerrainMaskChange
		{
			internal int Index;

			internal Color Before;

			internal Color After;

			internal bool BeforeModified;
		}

		private sealed class ThemeSurface
		{
			internal readonly Texture2D[] Parts = (Texture2D[])(object)new Texture2D[9];

			internal int Width;

			internal int Height;

			internal int Corner;
		}

		private enum WorldBuildMode
		{
			None,
			FirstCorner,
			SecondCorner,
			SelectionReady,
			PlaceFollow,
			PlaceAdjust,
			TerrainBrush,
			FlyingHammer
		}

		private ConfigEntry<string> _baseSnapshotConfig;

		private List<BaseSnapshot> _baseSnapshots = new List<BaseSnapshot>();

		private string _baseSelectedId;

		private string _baseName;

		private string _baseStatus = "Выдели целую базу двумя точками и заранее сохрани снимок.";

		private Vector2 _baseLibraryScroll;

		private Vector2 _baseSettingsScroll;

		private BaseRestorePlan _baseRestorePreview;

		private bool _baseLinksDirty;

		private float _baseLinksSaveAt;

		private bool _bridgeRails = true;

		private bool _bridgeSupports = true;

		private int _bridgeLayers = 1;

		private int _bridgeInterval = 2;

		private readonly Dictionary<GameObject, GeneratorModule> _bridgeModules = new Dictionary<GameObject, GeneratorModule>();

		private ConfigEntry<string> _blueprintConfig;

		private List<BuildingBlueprint> _blueprints = new List<BuildingBlueprint>();

		private string _blueprintSelectedId;

		private string _blueprintName = "Новый чертёж";

		private string _blueprintPreviewId;

		private string _blueprintDeleteId;

		private string _blueprintStatus = "Выдели строительные детали и сохрани их как чертёж.";

		private string _blueprintSaveStatus = "Выдели постройку, задай имя и нажми «Сохранить». Устройства и сундуки будут пропущены.";

		private Vector3 _blueprintAnchor;

		private bool _blueprintHasAnchor;

		private string _blueprintX = "0";

		private string _blueprintY = "0";

		private string _blueprintZ = "0";

		private string _blueprintYaw = "0";

		private Vector2 _blueprintListScroll;

		private Vector2 _blueprintSettingsScroll;

		private Vector2 _blueprintDetailScroll;

		private BuildingDeletion _deletePreview;

		private static readonly int EditPoseKey = StringExtensionMethods.GetStableHashCode("ValheimCheatMenu.EditedPose");

		private static readonly MethodInfo EditSetupColliders = AccessTools.Method(typeof(WearNTear), "SetupColliders", (Type[])null, (Type[])null);

		private static readonly MethodInfo EditClearSupport = AccessTools.Method(typeof(WearNTear), "ClearCachedSupport", (Type[])null, (Type[])null);

		private static readonly MethodInfo EditUpdateBiome = AccessTools.Method(typeof(WearNTear), "UpdateBiome", (Type[])null, (Type[])null);

		private static readonly FieldInfo EditHeightmap = AccessTools.Field(typeof(WearNTear), "m_heightmap");

		private static readonly FieldInfo EditConnectedHeightmap = AccessTools.Field(typeof(WearNTear), "m_connectedHeightMap");

		private static readonly FieldInfo EditCreator = AccessTools.Field(typeof(Piece), "m_creator");

		private static readonly FieldInfo EditCreatorIndex = AccessTools.Field(typeof(Piece), "m_creatorPlatformUserIDIndex");

		private List<EditChange> _editPreview;

		private int _editMode;

		private string _editX = "0";

		private string _editY = "0";

		private string _editZ = "0";

		private string _editYaw = "0";

		private string _editTargetSearch = "";

		private string _editSource;

		private float _editMoveStep = 1f;

		private float _editRotateStep = 15f;

		private float _editNetworkAt;

		private float _editSupportAt;

		private GameObject _editTarget;

		private readonly List<GameObject> _editPrefabs = new List<GameObject>();

		private ZNetScene _editCatalogScene;

		private List<string> _editPrefabNames;

		private int _editPrefabIndex;

		private bool _editCatalogStarted;

		private readonly List<Piece> _editNetworkPieces = new List<Piece>();

		private int _editNetworkIndex;

		private readonly HashSet<Piece> _editRefreshSupport = new HashSet<Piece>();

		private Vector2 _editSelectedScroll;

		private Vector2 _editSettingsScroll;

		private Vector2 _editCatalogScroll;

		private string _editStatus = "Выдели детали на странице «Объекты и ремонт». Затем настрой действие и создай предпросмотр.";

		private ZNetScene _buildingAuditScene;

		private GameObject _editGhostRoot;

		private Material _editGhostMaterial;

		private readonly List<Bounds> _editGhostBounds = new List<Bounds>();

		private static readonly Dictionary<Type, MethodInfo> BuildingFuelSetters = new Dictionary<Type, MethodInfo>();

		private int _generatorShape;

		private int _generatorMaterial;

		private int _generatorAcross = 3;

		private int _generatorAlong = 3;

		private bool _generatorDoorway;

		private BuildingBlueprint _generatorDraft;

		private string _generatorStatus = "Настрой конструкцию и открой голубой предпросмотр в мире. До размещения постройка не создаётся.";

		private Vector2 _generatorControlsScroll;

		private Vector2 _generatorDetailsScroll;

		private GameObject _generatorMeasuredPrefab;

		private int _generatorMeasuredShape;

		private GeneratorModule _generatorMeasuredModule;

		private readonly string[] _generatorShapes = new string[5] { "Платформа", "Стена", "Лестница", "Мост", "Башня" };

		private static readonly string[,] GeneratorPrefabs = new string[5, 2]
		{
			{ "wood_floor", "stone_floor_2x2" },
			{ "woodwall", "stone_wall_2x1" },
			{ "wood_stair", "stone_stair" },
			{ "wood_floor", "stone_floor_2x2" },
			{ "wood_floor", "stone_floor_2x2" }
		};

		private readonly BuildingSelectionState<ZDOID> _buildingSelection = new BuildingSelectionState<ZDOID>();

		private float _buildingResolveAt;

		private readonly HashSet<Piece> _buildingHighlighted = new HashSet<Piece>();

		private readonly List<Piece> _buildingHighlightRemoved = new List<Piece>();

		private static readonly int BuildingTint = Shader.PropertyToID("_Color");

		private static readonly int BuildingEmission = Shader.PropertyToID("_EmissionColor");

		private readonly List<Piece> _buildingNearby = new List<Piece>();

		private readonly HashSet<Piece> _buildingSelected = new HashSet<Piece>();

		private readonly List<BuildingUndo> _buildingHistory = new List<BuildingUndo>();

		private readonly Dictionary<Piece, Bounds> _buildingSelectionBounds = new Dictionary<Piece, Bounds>();

		private BuildingJob _buildingJob;

		private Player _buildingPlayer;

		private ZNetScene _buildingScene;

		private int _buildingRadius = 30;

		private bool _buildingPlayerOnly = true;

		private bool _buildingShowSelection = true;

		private float _buildingScanAt;

		private float _buildingBoundsAt;

		private string _buildingSearch = "";

		private string _buildingStatus = "Выбери отдельные объекты или выдели группу в радиусе.";

		private Vector2 _buildingListScroll;

		private Vector2 _buildingActionScroll;

		private Vector2 _fuelListScroll;

		private Vector2 _fuelActionScroll;

		private bool _fuelLights = true;

		private bool _fuelSmelters = true;

		private bool _fuelOvens = true;

		private bool _fuelShields;

		private const int BuildingSelectionLimit = 10000;

		private const int BuildingHighlightLimit = 500;

		private const string LargeBuildingSelectionWarning = "Большое выделение может вызвать просадки FPS и задержки. Подсвечиваются до 500 деталей.";

		internal static Plugin CameraTools;

		private bool _freeCamera;

		private bool _photoMode;

		private bool _oldFreeFly;

		private bool _oldHudVisible;

		private GameCamera _controlledCamera;

		private Hud _photoHud;

		private Camera _mainPhotoCamera;

		private Camera _skyPhotoCamera;

		private float _oldMainFov;

		private float _oldSkyFov;

		private float _cameraSpeed = 10f;

		private float _cameraFov = 65f;

		private float _cameraYaw;

		private float _cameraPitch;

		private Player _cameraPlayer;

		private bool _espEnabled;

		private bool _espMobs = true;

		private bool _espBosses = true;

		private bool _espTamed = true;

		private bool _espPlayers;

		private float _espRadius = 100f;

		private float _espNextScan;

		private readonly List<Character> _espCharacters = new List<Character>();

		private GUIStyle _espLabel;

		private Vector2 _cameraPageScroll;

		private static readonly FieldInfo CameraField = AccessTools.Field(typeof(GameCamera), "m_camera");

		private static readonly FieldInfo SkyField = AccessTools.Field(typeof(GameCamera), "m_skyCamera");

		private static readonly FieldInfo FreeFlyField = AccessTools.Field(typeof(GameCamera), "m_freeFly");

		private const int MaxCatalogCreationQuality = 10000;

		private GameObject _appearanceRoot;

		private GameObject _appearanceModel;

		private VisEquipment _appearanceVis;

		private Camera _appearanceCamera;

		private Light _appearanceKeyLight;

		private RenderTexture _appearanceTexture;

		private Player _appearanceOwner;

		private Player _sizeOwner;

		private Vector3 _sizeOriginal;

		private string _appearanceHair;

		private string _appearanceBeard;

		private string _appearanceStatus = "";

		private Vector3 _appearanceColor;

		private int _appearanceSex;

		private bool _appearanceArmor;

		private bool _appearanceDirty;

		private bool _appearanceFailed;

		private bool _appearanceDragging;

		private float _appearanceYaw;

		private float _appearanceSize = 1f;

		private Vector2 _appearanceScroll;

		private readonly List<Material> _appearanceMaterials = new List<Material>();

		private static readonly MethodInfo AppearanceUpdate = AccessTools.Method(typeof(VisEquipment), "UpdateVisuals", (Type[])null, (Type[])null);

		internal static bool InfiniteAmmoEnabled;

		internal static bool InstantBowEnabled;

		internal static bool InstantCrossbowEnabled;

		private Vector2 _combatPageScroll;

		private bool _combatFocusEsp;

		internal static Plugin AiTools;

		private readonly Dictionary<int, AiDirective> _aiDirectives = new Dictionary<int, AiDirective>();

		private Character _aiSelected;

		private Character _aiAttackTarget;

		private Player _aiSessionPlayer;

		private readonly List<Character> _aiNearby = new List<Character>();

		private Vector2 _aiListScroll;

		private Vector2 _aiActionScroll;

		private float _aiRadius = 30f;

		private float _aiScanAt;

		private bool _aiBulk;

		private string _aiStatus = "";

		private static readonly FieldInfo AiTarget = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");

		private static readonly FieldInfo AiStatic = AccessTools.Field(typeof(MonsterAI), "m_targetStatic");

		private static readonly MethodInfo AiSetAlert = AccessTools.Method(typeof(BaseAI), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null);

		private static readonly MethodInfo AiFollow = AccessTools.Method(typeof(BaseAI), "Follow", new Type[2]
		{
			typeof(GameObject),
			typeof(float)
		}, (Type[])null);

		private static readonly int CreatureForwardSpeed = Animator.StringToHash("forward_speed");

		private static readonly int CreatureSideSpeed = Animator.StringToHash("sideway_speed");

		private static readonly int CreatureOnGround = Animator.StringToHash("onGround");

		private static Plugin _creatureAttackPlugin;

		private static readonly string[] CreatureAttackPrefixes = new string[12]
		{
			"attack", "bite", "claw", "swipe", "slash", "punch", "stomp", "slam", "shoot", "spit",
			"peck", "kick"
		};

		private bool _appearanceMobMode;

		private SpawnCreatureEntry _appearanceMobChoice;

		private string _creatureLookSearch = "";

		private string _creatureLookPreviousSearch;

		private int _creatureLookCatalogCount = -1;

		private Vector2 _creatureLookScroll;

		private readonly List<SpawnCreatureEntry> _creatureLookMatches = new List<SpawnCreatureEntry>();

		private string _creatureLookStatus = "";

		private Player _creatureLookOwner;

		private GameObject _creatureLookRoot;

		private GameObject _creatureLookModel;

		private GameObject _creatureLookPlayerVisual;

		private readonly List<(Animator Animator, bool SideSpeed, bool Grounded)> _creatureLookAnimators = new List<(Animator, bool, bool)>();

		private readonly List<(Animator Animator, int Trigger)> _creatureAttackAnimators = new List<(Animator, int)>();

		private readonly HashSet<Renderer> _creatureLookHidden = new HashSet<Renderer>();

		private readonly List<Renderer> _creatureLookRenderers = new List<Renderer>();

		private float _creatureLookNextRefresh;

		internal static Plugin WaveTools;

		private WavePlan _waveDraft = new WavePlan();

		private WavePlan _waveRun;

		private bool _waveUsesDefaultName = true;

		private readonly WaveClock _waveClock = new WaveClock();

		private List<WavePlan> _wavePresets = new List<WavePlan>();

		private ConfigEntry<string> _waveConfig;

		private ConfigEntry<bool> _waveHudConfig;

		private readonly Dictionary<int, string> _waveActorKinds = new Dictionary<int, string>();

		private float _waveHudUntil;

		private readonly List<Character> _waveActors = new List<Character>();

		private List<WaveEntry> _waveQueue;

		private int _waveSpawnIndex;

		private Player _wavePlayer;

		private ZNetScene _waveScene;

		private Vector3 _waveAnchor;

		private bool _waveHasAnchor;

		private float _waveSpawnAt;

		private string _waveSearch = "";

		private string _waveStatus = "Укажи точку появления и добавь существ в состав.";

		private Vector2 _waveCatalogScroll;

		private Vector2 _waveSetupScroll;

		private Vector2 _waveControlScroll;

		private readonly List<GameObject> _bossProjectiles = new List<GameObject>();

		private ZNetScene _bossProjectileScene;

		private Vector2 _bossProjectileScroll;

		private string _bossProjectileSearch = "";

		private static readonly string[] BossDamageNames = new string[7] { "Дробящий", "Рубящий", "Колющий", "Огонь", "Мороз", "Молния", "Яд" };

		private string _bossHelperSearch = "";

		private Vector2 _bossHelperScroll;

		private ConfigEntry<string> _bossConfig;

		private List<CustomBossSpec> _bossTemplates = new List<CustomBossSpec>();

		private CustomBossSpec _bossDraft = new CustomBossSpec
		{
			Name = null
		};

		private SpawnCreatureEntry _bossBase;

		private string _bossSearch = "";

		private string _bossHealth = "1000";

		private string _bossDamage = "2";

		private string _bossSelectedId;

		private string _bossDeleteId;

		private string _bossStatus = "Выбери основу. Награды настраиваются отдельно; поведение и атаки остаются от основы.";

		private Vector2 _bossListScroll;

		private Vector2 _bossTemplateScroll;

		private Vector2 _bossSettingsScroll;

		private GameObject _bossPreviewInstance;

		private Vector3 _bossPreviewBaseScale;

		private float _bossPreviewSize;

		private int _bossSettingsPage;

		private bool _bossSummoning;

		private string _bossRewardSearch = "";

		private Vector2 _bossRewardCatalogScroll;

		private readonly List<EffectEntry> _effectCatalog = new List<EffectEntry>();

		private readonly List<AppliedEffectTimer> _appliedEffectTimers = new List<AppliedEffectTimer>();

		private ObjectDB _effectCatalogOwner;

		private EffectEntry _selectedEffect;

		private string _effectSearch = "";

		private string _effectSeconds = "60";

		private string _effectDamage = "10";

		private string _effectsStatus = "";

		private bool _onlyActiveEffects;

		private bool _showHiddenEffects;

		private Vector2 _effectsGridScroll;

		private Vector2 _effectsInfoScroll;

		private Vector2 _effectsPageScroll;

		private const string EquipmentIdentityKey = "ValheimCheatMenu.EquipmentId";

		private List<EquipmentSet> _equipmentSets = new List<EquipmentSet>();

		private ConfigEntry<string> _equipmentSetsConfig;

		private string _equipmentSetName = "Новый комплект";

		private string _equipmentSetId;

		private string _equipmentSetStatus = "";

		private Vector2 _equipmentSetScroll;

		private Vector2 _equipmentDetailScroll;

		private bool _espSkeleton = true;

		private bool _espBoxes = true;

		private readonly Dictionary<int, EspRig> _espRigs = new Dictionary<int, EspRig>();

		private bool _flyingHammerCatalogWasOpen;

		private Vector2 _flyingHammerScroll;

		private static readonly HudKeyRow[] FlyingHammerKeys = new HudKeyRow[8]
		{
			new HudKeyRow("WASD", "Лететь", "Fly"),
			new HudKeyRow("Space / Ctrl", "Подняться / опуститься", "Ascend / descend"),
			new HudKeyRow("Mouse", "Осмотреться", "Look around"),
			new HudKeyRow("ПКМ", "Открыть каталог молота", "Open build menu"),
			new HudKeyRow("ЛКМ", "Поставить / починить", "Place / repair"),
			new HudKeyRow("Wheel", "Повернуть деталь", "Rotate the piece"),
			new HudKeyRow("СКМ", "Разобрать деталь", "Dismantle the piece"),
			new HudKeyRow("Ctrl+Z", "Отменить установку / разбор", "Undo placement / dismantle")
		};

		private int _lootRadius = 30;

		private int _lootFoundStacks;

		private long _lootFoundItems;

		private float _lootScanAt;

		private float _lootCleanupAt;

		private string _lootRadiusText = "30";

		private string _lootStatus = "";

		private readonly FieldInfo _groundItemsField = AccessTools.Field(typeof(ItemDrop), "s_instances");

		private static readonly MethodInfo HammerInventoryChanged = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		private GUISkin _hudStyleSkin;

		private GUIStyle _hudHeadingStyle;

		private GUIStyle _hudBodyStyle;

		private GUIStyle _hudKeyStyle;

		private static readonly HudKeyRow[] WorldFlightKeys = new HudKeyRow[3]
		{
			new HudKeyRow("WASD", "Лететь", "Fly"),
			new HudKeyRow("Space / Ctrl", "Подняться / опуститься", "Ascend / descend"),
			new HudKeyRow("ПКМ", "Удерживай для обзора", "Hold to look around")
		};

		private HashSet<string> _favoriteItemNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private ConfigEntry<string> _favoriteItemsConfig;

		private bool _onlyFavoriteItems;

		private bool _favoriteResultsDirty;

		private Vector2 _catalogInfoScroll;

		private Vector2 _catalogEditorPageScroll;

		private string _catalogQualityText = "1";

		private string _catalogAmountText = "1";

		private string _catalogGrantStatus = "";

		private ItemSearchEntry _catalogLastInfo;

		private readonly Sprite[] _categorySprites = (Sprite[])(object)new Sprite[9];

		private GUIStyle _catalogText;

		private readonly List<Texture2D> _menuTextures = new List<Texture2D>();

		private GUISkin _menuSkin;

		private GUIStyle _menuFrame;

		private GUIStyle _menuTitle;

		private GUIStyle _menuTab;

		private GUIStyle _menuTabSelected;

		private GUIStyle _menuFooter;

		private bool _menuWasCompact;

		private int _menuScreenWidth;

		private int _menuScreenHeight;

		private int _menuFontSize;

		private InventoryGui _menuNativeSource;

		private Texture2D _menuWood;

		private Texture2D _menuButtonTexture;

		private Texture2D _menuInsetTexture;

		private Texture2D _menuHighlightTexture;

		private Texture2D _menuNativePanel;

		private Texture2D _menuNativeButton;

		private object _menuNativeFont;

		private float _menuBodyHeight;

		private static readonly Color MenuGold = new Color(0.85f, 0.69f, 0.4f);

		private static readonly Color MenuText = new Color(0.92f, 0.87f, 0.74f);

		private ConfigEntry<string> _interfaceLanguage;

		private readonly Dictionary<(int, string), ButtonMotion> _menuButtonMotion = new Dictionary<(int, string), ButtonMotion>();

		private const float MenuOpenDuration = 0.18f;

		private float _menuOpenedAt = float.NegativeInfinity;

		private Texture2D _favoriteStarFilled;

		private Texture2D _favoriteStarOutline;

		private GUIStyle _pageSmall;

		private GUIStyle _pageHeading;

		private GUIStyle _pageBadge;

		private Vector2 _creatureDetailsScroll;

		private readonly List<MenuFeature> _menuFeatures = new List<MenuFeature>();

		private ConfigEntry<KeyboardShortcut> _menuShortcut;

		private string _functionSearch = "";

		private string _captureBinding;

		private string _bindingStatus = "";

		private string _bindingSearch = "";

		private string _helpCandidate;

		private string _helpCurrent;

		private string _helpText;

		private string _highlightFeature;

		private float _helpSince;

		private float _highlightUntil;

		private int _utilityInputFrame = -1;

		private bool _searchOpen;

		private Vector2 _functionSearchScroll;

		private Vector2 _bindingScroll;

		private int _searchSelection;

		private Rect _searchRect;

		private MenuFeature _queuedFeature;

		private readonly List<ShellPage> _shellPages = new List<ShellPage>();

		private readonly List<string> _shellSections = new List<string>();

		private readonly Dictionary<string, int> _shellLastPage = new Dictionary<string, int>();

		private int _shellPage;

		private Vector2 _shellSubpageScroll;

		private Vector2 _shellPlayerScroll;

		private Vector2 _shellSkillsScroll;

		private Texture2D[] _shellIcons;

		private Texture2D[] _playerHeaderIcons;

		private Texture2D _playerOffTexture;

		private Texture2D _playerOnTexture;

		private Texture2D _playerHandleTexture;

		private GUIStyle _playerOffStyle;

		private GUIStyle _playerOnStyle;

		private GUIStyle _playerLabelStyle;

		private GUIStyle _playerHeadingStyle;

		private GUIStyle _playerTrackStyle;

		private GUIStyle _playerThumbStyle;

		private GUIStyle _playerInputStyle;

		private GUISkin _playerStyleSkin;

		private int _playerGroup;

		private Vector2 _playerSkillScroll;

		private Vector2 _playerSmallScroll;

		private GUIStyle _itemTooltipStyle;

		private GUIStyle _worldMapMarkerTooltipStyle;

		private ItemSearchEntry _hoveredItem;

		private ItemSearchEntry _selectedItem;

		private int _catalogIconsFound;

		private int _catalogIconsMissing;

		private int _catalogDuplicatesSkipped;

		private readonly HashSet<string> _itemCatalogKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		public static bool GodModeEnabled = false;

		private string _itemStatus = "Каталог предметов загружается.";

		private Vector2 _itemResultsScroll = Vector2.zero;

		private readonly List<ItemSearchEntry> _itemSearchResults = new List<ItemSearchEntry>();

		private Harmony _harmony;

		private readonly List<WorldMapMarker> _worldMapMarkers = new List<WorldMapMarker>();

		private readonly HashSet<string> _worldMapMarkerKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private IEnumerator _worldMapLocationEnumerator;

		private bool _worldMapLocationScanPending;

		private bool _worldMapLocationsScanned;

		private bool _showWorldMapBosses;

		private bool _showWorldMapTraders;

		private bool _showWorldMapPlayers;

		private Texture2D _worldMapDisplayTexture;

		private float _worldMapWorldHalfSize;

		private float _worldMapZoom = 1f;

		private Vector2 _worldMapPan = Vector2.zero;

		private bool _worldMapDragging;

		private float _worldMapNextPlayerRefresh;

		private readonly List<SpawnCreatureEntry> _spawnCatalog = new List<SpawnCreatureEntry>();

		private readonly List<SpawnCreatureEntry> _spawnSearchResults = new List<SpawnCreatureEntry>();

		private SpawnCreatureEntry _selectedSpawnCreature;

		private string _spawnSearch = "";

		private Vector2 _spawnListScroll = Vector2.zero;

		private int _spawnStars;

		private string _spawnCountText = "1";

		private const int MaxCreaturesPerSpawn = 20;

		private GameObject _spawnPreviewRoot;

		private GameObject _spawnPreviewObject;

		private int _spawnPreviewLayer = -1;

		private Character _spawnPreviewCharacter;

		private Camera _spawnPreviewCamera;

		private Light _spawnPreviewKeyLight;

		private RenderTexture _spawnPreviewTexture;

		private readonly List<Material> _spawnPreviewMaterials = new List<Material>();

		private string _spawnPreviewPrefabName = "";

		private int _spawnPreviewLevel = -1;

		private float _spawnPreviewYaw = 180f;

		private float _spawnPreviewPitch;

		private bool _spawnPreviewDragging;

		private Vector3 _spawnPreviewCenter;

		private float _spawnPreviewBaseDistance = 3f;

		private float _spawnPreviewDistance = 3f;

		private string _spawnPreviewFramedPrefabName = "";

		private float _spawnPreviewFramedDistance;

		private string _spawnStatus = "Каталог существ ещё не загружен.";

		private bool _spawnCatalogLoaded;

		private bool _spawnCatalogLoading;

		private List<string> _spawnPrefabNames;

		private int _spawnCatalogBuildIndex;

		private const int SpawnCatalogBatchSize = 30;

		private bool _showWindow;

		private Rect _windowRect = new Rect(60f, 40f, 1120f, 900f);

		private int _activeTab;

		private Vector2 _scrollPosition;

		private CursorLockMode _previousCursorLockState;

		private bool _previousCursorVisible;

		private string _itemSearch = "";

		private bool _itemCatalogLoaded;

		private string _lastAppliedItemSearch;

		private int _itemCategoryIndex;

		private int _lastAppliedItemCategory = -1;

		private readonly List<ItemSearchEntry> _itemCatalog = new List<ItemSearchEntry>();

		private bool _itemCatalogLoading;

		private int _itemCatalogBuildIndex;

		private List<GameObject> _itemCatalogSource;

		private const int ItemCatalogBatchSize = 25;

		private static bool _localizationLookupDone;

		private static Type _localizationTypeCache;

		private static MethodInfo _localizeMethodCache;

		private static object _localizationInstanceCache;

		private readonly string[] _itemCategoryNames = new string[9] { "Все", "Оружие", "Броня", "Еда", "Инструменты", "Боеприпасы", "Материалы", "Трофеи", "Другое" };

		private string _teleportX = "0";

		private string _teleportY = "40";

		private string _teleportZ = "0";

		private string _skillName = "Swords";

		private string _skillLevel = "100";

		private string[] _skillOptions = new string[0];

		private int _selectedSkillIndex;

		private bool _showSkillDropdown;

		private Vector2 _skillDropdownScroll;

		private bool _freeCraftSnapshotTaken;

		private bool _noCraftCostWasActive;

		private bool _alwaysDaySnapshotTaken;

		private bool _previousDebugTimeOfDay;

		private float _previousDebugTime;

		private readonly Dictionary<string, bool> _toggleStates = new Dictionary<string, bool>();

		private readonly Dictionary<string, bool> _originalWorldKeyStates = new Dictionary<string, bool>();

		private static readonly int CreatureLookKey = StringExtensionMethods.GetStableHashCode("ValheimCheatMenu.CreatureLook.v1");

		private static readonly int CreatureAttackKey = StringExtensionMethods.GetStableHashCode("ValheimCheatMenu.CreatureLookAttack.v1");

		private readonly Dictionary<Player, RemoteCreatureLook> _remoteCreatureLooks = new Dictionary<Player, RemoteCreatureLook>();

		private readonly List<Player> _remoteCreatureExpired = new List<Player>();

		private float _remoteCreatureRefresh;

		private List<SavedTeleport> _savedTeleports = new List<SavedTeleport>();

		private ConfigEntry<string> _savedTeleportsConfig;

		private ConfigEntry<bool> _savedPinsVisible;

		private string _savedPointName;

		private string _savedPointId;

		private string _savedPointStatus = "";

		private int _savedPointIcon;

		private Vector2 _savedPointScroll;

		private static readonly string[] SavedPinIcons = new string[5] { "Icon0", "Icon1", "Icon2", "Icon3", "Icon4" };

		private static readonly string[] SavedPinNames = new string[5] { "Значок метки 1", "Значок метки 2", "Значок метки 3", "Значок метки 4", "Значок метки 5" };

		private readonly Dictionary<SkillType, SkillLevelDraft> _skillDrafts = new Dictionary<SkillType, SkillLevelDraft>();

		private Skills _skillDraftOwner;

		private Vector2 _skillsListScroll;

		private string _skillsSearch = "";

		private string _skillsEditorStatus = "";

		private static readonly MethodInfo GetEditedSkill = AccessTools.Method(typeof(Skills), "GetSkill", new Type[1] { typeof(SkillType) }, (Type[])null);

		private const float SpawnCleanupRadius = 30f;

		private string _spawnCleanupStatus = "";

		private float _spawnCleanupNextAllowedTime;

		private Texture2D[] _spawnThemeIcons;

		private GUIStyle _spawnDangerStyle;

		private Vector2 _spawnSmallPageScroll;

		private int _storageRadius = 30;

		private int _storageCategory;

		private string _storageQuery = "";

		private string _sortStatus = "";

		private bool _storageProtectHotbar;

		private Vector2 _storageResultsScroll;

		private Vector2 _storageContentsScroll;

		private Vector2 _storageSortScroll;

		private readonly List<StorageResult> _storageResults = new List<StorageResult>();

		private Container _storageSelected;

		private float _storageNextScan;

		private float _storageActionAt;

		private static readonly string[] StorageCategories = new string[4] { "Все", "Материалы", "Еда", "Боеприпасы" };

		private static readonly MethodInfo StorageAccess = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null);

		private static readonly MethodInfo StorageLoad = AccessTools.Method(typeof(Container), "Load", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo StorageChanged = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		private static readonly FieldInfo StorageWard = AccessTools.Field(typeof(Container), "m_checkGuardStone");

		internal static bool OwnTerrainOperation;

		private static readonly FieldInfo TerrainLevel = AccessTools.Field(typeof(TerrainComp), "m_levelDelta");

		private static readonly FieldInfo TerrainSmooth = AccessTools.Field(typeof(TerrainComp), "m_smoothDelta");

		private static readonly FieldInfo TerrainModified = AccessTools.Field(typeof(TerrainComp), "m_modifiedHeight");

		private static readonly FieldInfo TerrainOperations = AccessTools.Field(typeof(TerrainComp), "m_operations");

		private static readonly FieldInfo TerrainLastPoint = AccessTools.Field(typeof(TerrainComp), "m_lastOpPoint");

		private static readonly FieldInfo TerrainLastRadius = AccessTools.Field(typeof(TerrainComp), "m_lastOpRadius");

		private static readonly MethodInfo TerrainOperation = AccessTools.Method(typeof(TerrainComp), "DoOperation", (Type[])null, (Type[])null);

		private static readonly MethodInfo TerrainSave = AccessTools.Method(typeof(TerrainComp), "Save", (Type[])null, (Type[])null);

		private static readonly MethodInfo TerrainLoad = AccessTools.Method(typeof(TerrainComp), "CheckLoad", (Type[])null, (Type[])null);

		private int _terrainMode;

		private const int MinTerrainRadius = 1;

		private const int MaxTerrainRadius = 20;

		private const int TerrainOutlineSegments = 64;

		private const int TerrainControlsHeight = 720;

		private float _terrainRadius = 5f;

		private float _terrainStrength = 0.5f;

		private float _terrainLevel;

		private bool _terrainHasLevel;

		private bool _terrainSquare;

		private bool _terrainPainting;

		private float _terrainStampAt;

		private readonly List<TerrainUndo> _terrainStroke = new List<TerrainUndo>();

		private string _terrainStatus = "Удерживай ЛКМ и веди кисть. Для выравнивания сначала выбери высоту клавишей F.";

		private readonly string[] _terrainNames = new string[4] { "Поднять", "Опустить", "Выровнять", "Сгладить" };

		private LineRenderer _terrainRing;

		private Material _terrainRingMaterial;

		private float _terrainRingAt;

		private Vector2 _terrainScroll;

		private Vector2 _terrainHudScroll;

		private static readonly HudKeyRow[] TerrainBrushKeys = new HudKeyRow[4]
		{
			new HudKeyRow("ЛКМ", "Удерживай, чтобы рисовать", "Hold to paint"),
			new HudKeyRow("F", "Взять высоту", "Sample height"),
			new HudKeyRow("Wheel", "Изменить размер кисти", "Resize the brush"),
			new HudKeyRow("Ctrl+Z", "Отменить мазок", "Undo the stroke")
		};

		private const int TerrainPaintMode = 4;

		private const int CultivatedSurface = 8;

		private const int PavedSurface = 9;

		private const int NativeSurface = 10;

		private static readonly FieldInfo TerrainMask = AccessTools.Field(typeof(TerrainComp), "m_paintMask");

		private static readonly FieldInfo TerrainMaskModified = AccessTools.Field(typeof(TerrainComp), "m_modifiedPaint");

		private static readonly Color32[] TerrainSwatches = (Color32[])(object)new Color32[11]
		{
			new Color32((byte)104, (byte)148, (byte)60, byte.MaxValue),
			new Color32((byte)55, (byte)103, (byte)67, byte.MaxValue),
			new Color32((byte)96, (byte)104, (byte)55, byte.MaxValue),
			new Color32((byte)195, (byte)216, (byte)222, byte.MaxValue),
			new Color32((byte)180, (byte)152, (byte)68, byte.MaxValue),
			new Color32((byte)110, (byte)105, (byte)145, byte.MaxValue),
			new Color32((byte)101, (byte)70, (byte)64, byte.MaxValue),
			new Color32((byte)160, (byte)192, (byte)211, byte.MaxValue),
			new Color32((byte)120, (byte)77, (byte)48, byte.MaxValue),
			new Color32((byte)138, (byte)135, (byte)128, byte.MaxValue),
			new Color32((byte)103, (byte)123, (byte)81, byte.MaxValue)
		};

		private Texture2D[] _terrainSwatchIcons;

		private int _terrainSurface;

		private ThemeSurface _panelSurface;

		private ThemeSurface _offSurface;

		private ThemeSurface _onSurface;

		private GUIStyle _playerOffTextStyle;

		private GUIStyle _playerOnTextStyle;

		private Texture2D _playerTrackTexture;

		private int _towerFloors = 2;

		private bool _towerSlabs = true;

		private bool _towerStairs = true;

		private bool _towerEntrance = true;

		private GameObject _towerStairPrefab;

		private GeneratorModule _towerStairModule;

		private const int SearchUtilityWindowId = 734202;

		private const int BindingUtilityWindowId = 734203;

		private bool _searchNeedsFocus;

		private int _bindingCaptureFrame;

		private static readonly KeyCode[] UtilityCaptureKeys = (from key in ((KeyCode[])Enum.GetValues(typeof(KeyCode))).Distinct()
			where (int)key > 0 && (int)key < 323 && !IsModifierKey(key)
			select key).ToArray();

		private static readonly int WaveHudKey = StringExtensionMethods.GetStableHashCode("ValheimCheatMenu.WaveHud.v1");

		private WaveHudView _localWaveHud;

		private WaveHudView _remoteWaveHud;

		private float _waveHudNetworkAt;

		private static readonly byte[] EmptyWaveHud = Array.Empty<byte>();

		private const int MaxWorkshopQuality = 100;

		private bool _compactItems;

		private ItemSearchEntry _catalogDrag;

		private bool _catalogDragMoved;

		private Vector2 _catalogDragStart;

		private int _catalogDragAmount;

		private ItemData _workshopItem;

		private Inventory _workshopOwner;

		private int _workshopQuality = 1;

		private GUIStyle _workshopBadgeStyle;

		private GUIStyle _workshopTooltipStyle;

		private string _transferStatus = "Открой инвентарь или сундук до F6. Для перетаскивания сдвинь меню в сторону.";

		private static readonly FieldInfo GridElements = AccessTools.Field(typeof(InventoryGrid), "m_elements");

		private GUIStyle _transferMessageStyle;

		private Texture2D[] _workshopThemeIcons;

		private Vector2 _workshopSmallPageScroll;

		private WorldBuildMode _worldBuildMode;

		private readonly HashSet<Piece> _worldBuildCandidates = new HashSet<Piece>();

		private Vector3 _worldCornerA;

		private Vector3 _worldCornerB;

		private Vector3 _worldPlacePivot;

		private Vector3 _worldBasePivot;

		private Vector3[] _worldBasePositions;

		private Quaternion[] _worldBaseRotations;

		private float _worldBaseYaw;

		private float _worldPlaceYaw;

		private float _worldScanAt;

		private float _worldRepeatAt;

		private bool _worldHadFreeCamera;

		private bool _worldPlaceValid;

		private int _worldSelectionReturnTab = 21;

		private Player _worldBuildPlayer;

		private ZNetScene _worldBuildScene;

		private CursorLockMode _worldOldCursorLock;

		private bool _worldOldCursorVisible;

		private string _worldBuildNote = "";

		private GameObject _worldVolume;

		private Mesh _worldVolumeMesh;

		private Material _worldVolumeFaceMaterial;

		private Material _worldVolumeEdgeMaterial;

		private static readonly HudKeyRow[] FirstCornerKeys = new HudKeyRow[2]
		{
			new HudKeyRow("ЛКМ", "Поставить первый угол", "Set the first corner"),
			new HudKeyRow("F", "Поставить угол у камеры", "Set the corner at the camera")
		};

		private static readonly HudKeyRow[] SecondCornerKeys = new HudKeyRow[4]
		{
			new HudKeyRow("ЛКМ", "Поставить второй угол", "Set the second corner"),
			new HudKeyRow("F", "Поставить угол у камеры", "Set the corner at the camera"),
			new HudKeyRow("Backspace", "Вернуться к первому углу", "Return to the first corner"),
			new HudKeyRow("Enter", "Принять выделение", "Confirm selection")
		};

		private static readonly HudKeyRow[] SelectionReadyKeys = new HudKeyRow[2]
		{
			new HudKeyRow("Backspace", "Изменить второй угол", "Adjust the second corner"),
			new HudKeyRow("Enter", "Принять выделение", "Confirm selection")
		};

		private static readonly HudKeyRow[] PlaceFollowKeys = new HudKeyRow[3]
		{
			new HudKeyRow("ЛКМ", "Зафиксировать копию", "Pin the copy"),
			new HudKeyRow("Q / E", "Повернуть на 15°", "Rotate by 15°"),
			new HudKeyRow("Shift", "Точный поворот на 1°", "Rotate by 1°")
		};

		private static readonly HudKeyRow[] PlaceAdjustKeys = new HudKeyRow[7]
		{
			new HudKeyRow("ЛКМ", "Переставить копию", "Pin at a new point"),
			new HudKeyRow("Arrows", "Сдвинуть на 1 м", "Nudge by 1 m"),
			new HudKeyRow("PgUp / PgDn", "Поднять / опустить копию", "Raise / lower the copy"),
			new HudKeyRow("Q / E", "Повернуть на 15°", "Rotate by 15°"),
			new HudKeyRow("Shift", "Точная подгонка (0,1 м / 1°)", "Fine adjustment (0.1 m / 1°)"),
			new HudKeyRow("R", "Снова следовать за курсором", "Follow the cursor again"),
			new HudKeyRow("Enter", "Разместить копию", "Place the copy")
		};

		private string _worldBossFilter = "";

		private bool _worldBossListOpen;

		private Vector2 _worldBossListScroll;

		private readonly Dictionary<string, Sprite> _nativeMapIcons = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

		private Minimap _nativeMapIconOwner;

		private static readonly string[] WorldBossNames = new string[7] { "Эйктюр", "Древний", "Масса костей", "Моудер", "Яглут", "Королева", "Фейдер" };

		private Texture2D[] _worldHeadingIcons;

		private GUIStyle _worldTooltipSkin;

		private Vector2 _worldSmallPageScroll;

		private int BuildingSelectionCount => _buildingSelection.Keys.Count;

		private bool WaveRunning
		{
			get
			{
				if (_waveClock.Phase != WavePhase.Spawning && _waveClock.Phase != WavePhase.Fighting)
				{
					return _waveClock.Phase == WavePhase.Delay;
				}
				return true;
			}
		}

		internal bool FlyingHammerActive => _worldBuildMode == WorldBuildMode.FlyingHammer;

		private float MenuContentWidth => Mathf.Max(280f, ((Rect)(ref _windowRect)).width - 76f);

		private float MenuCatalogGridWidth => Mathf.Max(96f, ((Rect)(ref _windowRect)).width - (float)(_compactItems ? 265 : 550));

		private float MenuCatalogHeight => Mathf.Clamp(_menuBodyHeight - 165f, 220f, 850f);

		private float MenuIconCellSize => Mathf.Clamp((float)Screen.height / 1080f * 96f, 76f, 120f);

		private float WorkshopInventoryWidth
		{
			get
			{
				if (!_compactItems)
				{
					return MenuContentWidth * 0.55f;
				}
				return MenuContentWidth;
			}
		}

		private float MenuMapSize => Mathf.Max(180f, Mathf.Min(MenuContentWidth - 230f, _menuBodyHeight - 90f));

		private float MenuSpawnListWidth
		{
			get
			{
				if (!_compactItems)
				{
					return Mathf.Clamp(MenuContentWidth * 0.24f, 260f, 400f);
				}
				return Mathf.Min(220f, MenuContentWidth * 0.35f);
			}
		}

		private float MenuSpawnPreviewSize
		{
			get
			{
				if (!_compactItems)
				{
					return Mathf.Clamp((MenuContentWidth - MenuSpawnListWidth) * 0.48f, 240f, 440f);
				}
				return Mathf.Min(340f, MenuContentWidth - MenuSpawnListWidth - 45f);
			}
		}

		internal static bool InfiniteStaminaEnabled { get; private set; }

		internal static bool InfiniteEitrEnabled { get; private set; }

		internal static bool InfiniteCarryWeightEnabled { get; private set; }

		internal static bool NoFallDamageEnabled { get; private set; }

		internal static bool IncreasedSpeedEnabled { get; private set; }

		internal static float RunSpeedMultiplier { get; private set; } = 1f;

		internal static float JumpHeightMultiplier { get; private set; } = 1f;

		internal static float SwimSpeedMultiplier { get; private set; } = 1f;

		internal static bool FlyModeEnabled { get; private set; }

		internal static bool InfiniteDurabilityEnabled { get; private set; }

		internal static bool AlwaysDayEnabled { get; private set; }

		internal static bool TerrainRadiusEnabled { get; private set; }

		internal static bool WorkOutdoorsEnabled { get; private set; }

		internal static bool AllInventoryRecipesEnabled { get; private set; }

		internal static bool InfiniteCoinsEnabled { get; private set; }

		internal static bool InfiniteCoinsPurchaseInProgress { get; set; }

		internal static bool FreeUpgradeEnabled { get; private set; }

		internal static bool MenuInputBlocked { get; private set; }

		internal static int EscapeCloseFrame { get; private set; } = -1;

		private float TerrainBrushBoundsRadius => (_terrainRadius + 1f) * (_terrainSquare ? Mathf.Sqrt(2f) : 1f);

		internal static bool WorldBuildInputBlocked { get; private set; }

		private bool WorldSelecting
		{
			get
			{
				if (_worldBuildMode >= WorldBuildMode.FirstCorner)
				{
					return _worldBuildMode <= WorldBuildMode.SelectionReady;
				}
				return false;
			}
		}

		private BaseSnapshot SelectedBaseSnapshot()
		{
			return _baseSnapshots.FirstOrDefault((BaseSnapshot s) => s.Shape.Id == _baseSelectedId);
		}

		private void InitializeBaseRecovery()
		{
			_baseSnapshotConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Building", "BaseSnapshots", "", "До 10 снимков баз: исходный мир, координаты и свойства строительных деталей.");
			_baseSnapshots = BaseSnapshotCodec.Read(_baseSnapshotConfig.Value);
		}

		private void SaveBaseLibrary()
		{
			_baseSnapshotConfig.Value = BaseSnapshotCodec.Write(_baseSnapshots);
			if (!((BaseUnityPlugin)this).Config.SaveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			_baseLinksDirty = false;
		}

		private void RedirectBaseSnapshotIds(ZDOID before, ZDOID after)
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			foreach (BaseSnapshot item in _baseSnapshots.Where((BaseSnapshot s) => s.World == ZNet.instance.GetWorldUID()))
			{
				foreach (BasePartData datum in item.Data)
				{
					if (datum.User == ((ZDOID)(ref before)).UserID && datum.Id == ((ZDOID)(ref before)).ID)
					{
						datum.User = ((ZDOID)(ref after)).UserID;
						datum.Id = ((ZDOID)(ref after)).ID;
						_baseLinksDirty = true;
					}
				}
			}
		}

		private void FlushBaseSnapshotLinks()
		{
			if (!_baseLinksDirty || _baseSnapshotConfig == null || Time.unscaledTime < _baseLinksSaveAt)
			{
				return;
			}
			_baseLinksSaveAt = Time.unscaledTime + 2f;
			try
			{
				SaveBaseLibrary();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[Base snapshot links] " + ex.Message));
			}
		}

		private void SaveBaseSnapshot(bool update)
		{
			//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_00ee: 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_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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || (Object)(object)ZNet.instance == (Object)null || _buildingJob != null)
			{
				return;
			}
			CancelEditPreview();
			SyncBuildingSelection(force: true);
			try
			{
				BaseSnapshot baseSnapshot = (update ? SelectedBaseSnapshot() : null);
				if (update && (baseSnapshot == null || baseSnapshot.World != ZNet.instance.GetWorldUID()))
				{
					throw new InvalidOperationException("Выбери снимок текущего мира");
				}
				if (!update && _baseSnapshots.Count >= 10)
				{
					throw new InvalidOperationException("Уже сохранено 10 баз. Выбери снимок для обновления");
				}
				if (BuildingSelectionCount != _buildingSelected.Count)
				{
					throw new InvalidOperationException("Часть выделения не загружена. Подойди к базе и повтори выделение");
				}
				List<Piece> list = _buildingSelected.Where((Piece p) => (Object)(object)p != (Object)null && p.IsPlacedByPlayer() && BuildingAccess(p, owner: false) && EditDestination(((Component)p).transform.position) && StaticBuilding(((Component)p).gameObject, allowBlueprintDoor: true) && StaticBuilding(BuildingPrefab(p), allowBlueprintDoor: true)).ToList();
				if (list.Count == 0)
				{
					throw new InvalidOperationException("Нет доступных строительных деталей. Выдели базу двумя точками");
				}
				Vector3 val = Vector3.zero;
				foreach (Piece item in list)
				{
					val += ((Component)item).transform.position;
				}
				val /= (float)list.Count;
				BaseSnapshot baseSnapshot2 = new BaseSnapshot();
				baseSnapshot2.World = ZNet.instance.GetWorldUID();
				baseSnapshot2.Origin = new float[3] { val.x, val.y, val.z };
				baseSnapshot2.Shape = new BuildingBlueprint
				{
					Id = ((baseSnapshot == null) ? Guid.NewGuid().ToString("N") : baseSnapshot.Shape.Id),
					Name = (_baseName ?? MenuLanguage.Text("Моя база")).Trim()
				};
				BaseSnapshot baseSnapshot3 = baseSnapshot2;
				Dictionary<Vector3Int, List<EditState>> dictionary = new Dictionary<Vector3Int, List<EditState>>();
				foreach (Piece item2 in list)
				{
					EditState s = CaptureEditState(item2);
					Vector3 val2 = s.Position - val;
					Quaternion normalized = ((Quaternion)(ref s.Rotation)).normalized;
					Vector3Int val3 = Vector3Int.FloorToInt(s.Position);
					for (int num = -1; num <= 1; num++)
					{
						for (int num2 = -1; num2 <= 1; num2++)
						{
							for (int num3 = -1; num3 <= 1; num3++)
							{
								if (dictionary.TryGetValue(val3 + new Vector3Int(num3, num2, num), out var value) && value.Any(delegate(EditState old)
								{
									//IL_001c: 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_0027: Unknown result type (might be due to invalid IL or missing references)
									//IL_002c: 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_0040: Unknown result type (might be due to invalid IL or missing references)
									//IL_0050: 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)
									//IL_005b: Unknown result type (might be due to invalid IL or missing references)
									//IL_0060: Unknown result type (might be due to invalid IL or missing references)
									bool samePrefab = (Object)(object)s.Prefab == (Object)(object)old.Prefab;
									Vector3 val4 = s.Position - old.Position;
									float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
									float angle = Quaternion.Angle(s.Rotation, old.Rotation);
									val4 = s.Scale - old.Scale;
									return BaseRecoveryRules.SameSlot(samePrefab, sqrMagnitude, angle, ((Vector3)(ref val4)).sqrMagnitude);
								}))
								{
									throw new InvalidOperationException("В выделении есть наложенные одинаковые детали");
								}
							}
						}
					}
					if (!dictionary.TryGetValue(val3, out var value2))
					{
						dictionary.Add(val3, value2 = new List<EditState>());
					}
					value2.Add(s);
					baseSnapshot3.Shape.Pieces.Add(new BlueprintPiece
					{
						Prefab = ((Object)s.Prefab).name,
						Values = new float[11]
						{
							val2.x,
							val2.y,
							val2.z,
							normalized.x,
							normalized.y,
							normalized.z,
							normalized.w,
							s.Scale.x,
							s.Scale.y,
							s.Scale.z,
							Mathf.Clamp01(s.Health / s.Maximum)
						}
					});
					ZDOID uid = BuildingView(item2).GetZDO().m_uid;
					baseSnapshot3.Data.Add(new BasePartData
					{
						User = ((ZDOID)(ref uid)).UserID,
						Id = ((ZDOID)(ref uid)).ID,
						State = PackBaseState(s)
					});
				}
				if (!baseSnapshot3.Valid())
				{
					throw new InvalidOperationException("Проверь имя (1–48 символов) и выделенные детали.");
				}
				List<BaseSnapshot> baseSnapshots = _baseSnapshots.ToList();
				if (baseSnapshot == null)
				{
					_baseSnapshots.Add(baseSnapshot3);
				}
				else
				{
					_baseSnapshots[_baseSnapshots.IndexOf(baseSnapshot)] = baseSnapshot3;
				}
				try
				{
					SaveBaseLibrary();
				}
				catch
				{
					_baseSnapshots = baseSnapshots;
					throw;
				}
				_baseSelectedId = baseSnapshot3.Shape.Id;
				_baseStatus = "Снимок «" + baseSnapshot3.Shape.Name + "» сохранён: " + list.Count + " деталей. Пропущено: " + (_buildingSelected.Count - list.Count) + ".";
			}
			catch (Exception ex)
			{
				_baseStatus = "Снимок не сохранён: " + ex.Message;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[Base snapshot] " + ex));
			}
		}

		private bool SameBasePose(Piece piece, EditState state)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0055: 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_0060: 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)
			if ((Object)(object)piece != (Object)null)
			{
				bool samePrefab = (Object)(object)BuildingPrefab(piece) == (Object)(object)state.Prefab;
				Vector3 val = ((Component)piece).transform.position - state.Position;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				float angle = Quaternion.Angle(((Component)piece).transform.rotation, state.Rotation);
				val = ((Component)piece).transform.localScale - state.Scale;
				return BaseRecoveryRules.SameSlot(samePrefab, sqrMagnitude, angle, ((Vector3)(ref val)).sqrMagnitude);
			}
			return false;
		}

		private EditState BaseSlotState(BaseSnapshot site, int index)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			BlueprintPiece blueprintPiece = site.Shape.Pieces[index];
			float[] values = blueprintPiece.Values;
			GameObject prefab = ZNetScene.instance.GetPrefab(blueprintPiece.Prefab);
			if (!StaticBuilding(prefab, allowBlueprintDoor: true))
			{
				throw new InvalidOperationException("Недоступная деталь: " + blueprintPiece.Prefab);
			}
			EditState obj = new EditState
			{
				Prefab = prefab,
				Position = new Vector3(site.Origin[0] + values[0], site.Origin[1] + values[1], site.Origin[2] + values[2])
			};
			Quaternion val = new Quaternion(values[3], values[4], values[5], values[6]);
			obj.Rotation = ((Quaternion)(ref val)).normalized;
			obj.Scale = new Vector3(values[7], values[8], values[9]);
			obj.Maximum = prefab.GetComponent<WearNTear>().m_health;
			EditState editState = obj;
			editState.Health = editState.Maximum * values[10];
			if (!BuildingRules.Finite(editState.Health) || editState.Health <= 0f)
			{
				throw new InvalidOperationException("Некорректная прочность детали");
			}
			UnpackBaseState(editState, site.Data[index].State);
			return editState;
		}

		private int ClassifyBaseSlot(BaseSnapshot site, int index, EditState state, out Piece present)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			present = null;
			if (!EditDestination(state.Position) || ZDOMan.instance == null)
			{
				return 2;
			}
			BasePartData basePartData = site.Data[index];
			ZDOID val = default(ZDOID);
			((ZDOID)(ref val))..ctor(basePartData.User, basePartData.Id);
			GameObject val2 = ZNetScene.instance.FindInstance(val);
			if ((Object)(object)val2 != (Object)null)
			{
				Piece component = val2.GetComponent<Piece>();
				if ((Object)(object)component != (Object)null && BuildingAccess(component, owner: false) && SameBasePose(component, state) && BuildingHealth(component, ((Component)component).GetComponent<WearNTear>()) > 0f)
				{
					present = component;
					return 0;
				}
				return 2;
			}
			if (ZDOMan.instance.GetZDO(val) != null)
			{
				return 2;
			}
			List<Piece> list = new List<Piece>();
			Piece.GetAllPiecesInRadius(state.Position, 0.2f, list);
			foreach (Piece item in list)
			{
				if (BuildingAccess(item, owner: false) && SameBasePose(item, state) && (Object)(object)((Component)item).GetComponent<WearNTear>() != (Object)null && BuildingHealth(item, ((Component)item).GetComponent<WearNTear>()) > 0f)
				{
					present = item;
					return 0;
				}
			}
			if (list.Any(delegate(Piece p)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: 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)
				if ((Object)(object)p != (Object)null)
				{
					Vector3 val3 = ((Component)p).transform.position - state.Position;
					if (((Vector3)(ref val3)).sqrMagnitude <= 0.0025f)
					{
						return !ExpectedBaseNeighbor(site, index, p);
					}
				}
				return false;
			}))
			{
				return 2;
			}
			return 1;
		}

		private bool ExpectedBaseNeighbor(BaseSnapshot site, int except, Piece piece)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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)
			GameObject val = BuildingPrefab(piece);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			for (int i = 0; i < site.Shape.Pieces.Count; i++)
			{
				if (i != except && !(site.Shape.Pieces[i].Prefab != ((Object)val).name))
				{
					float[] values = site.Shape.Pieces[i].Values;
					Vector3 val2 = ((Component)piece).transform.position - new Vector3(site.Origin[0] + values[0], site.Origin[1] + values[1], site.Origin[2] + values[2]);
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					Quaternion rotation = ((Component)piece).transform.rotation;
					Quaternion val3 = new Quaternion(values[3], values[4], values[5], values[6]);
					float angle = Quaternion.Angle(rotation, ((Quaternion)(ref val3)).normalized);
					val2 = ((Component)piece).transform.localScale - new Vector3(values[7], values[8], values[9]);
					if (BaseRecoveryRules.SameSlot(samePrefab: true, sqrMagnitude, angle, ((Vector3)(ref val2)).sqrMagnitude))
					{
						return true;
					}
				}
			}
			return false;
		}

		private void PrepareBaseRecovery()
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			BaseSnapshot baseSnapshot = SelectedBaseSnapshot();
			Player localPlayer = Player.m_localPlayer;
			CancelEditPreview();
			if (baseSnapshot == null || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || (Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || _buildingJob != null)
			{
				return;
			}
			if (baseSnapshot.World != ZNet.instance.GetWorldUID())
			{
				_baseStatus = "Снимок принадлежит другому миру. Восстановление доступно только в исходном мире.";
				return;
			}
			BaseRestorePlan baseRestorePlan = new BaseRestorePlan
			{
				Snapshot = baseSnapshot,
				Scene = ZNetScene.instance,
				Player = localPlayer.GetPlayerID()
			};
			for (int i = 0; i < baseSnapshot.Shape.Pieces.Count; i++)
			{
				try
				{
					EditState state = BaseSlotState(baseSnapshot, i);
					Piece present;
					switch (ClassifyBaseSlot(baseSnapshot, i, state, out present))
					{
					case 0:
						baseRestorePlan.Present++;
						baseRestorePlan.Existing[i] = BuildingView(present).GetZDO().m_uid;
						break;
					case 1:
						baseRestorePlan.Missing.Add(new BaseRestoreSlot
						{
							Index = i,
							State = state
						});
						break;
					default:
						baseRestorePlan.Blocked++;
						break;
					}
				}
				catch (Exception ex)
				{
					baseRestorePlan.Blocked++;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Base check] " + ex.Message));
				}
			}
			_baseStatus = "Целых: " + baseRestorePlan.Present + ". Недостающих: " + baseRestorePlan.Missing.Count + ". Изменённых, занятых или недоступных: " + baseRestorePlan.Blocked + ".";
			if (baseRestorePlan.Missing.Count == 0)
			{
				return;
			}
			try
			{
				_baseRestorePreview = baseRestorePlan;
				_editPreview = baseRestorePlan.Missing.Select((BaseRestoreSlot s) => new EditChange
				{
					Placement = true,
					After = s.State
				}).ToList();
				BuildEditGhosts();
				_baseStatus += " Голубой — только недостающие части. Проверь предпросмотр и нажми «Восстановить».";
			}
			catch (Exception ex2)
			{
				CancelEditPreview();
				_baseStatus = "Предпросмотр не создан: " + ex2.Message;
			}
		}

		private void ApplyBaseRecovery()
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			BaseRestorePlan baseRestorePreview = _baseRestorePreview;
			Player localPlayer = Player.m_localPlayer;
			if (baseRestorePreview == null || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || _buildingJob != null || (Object)(object)baseRestorePreview.Scene != (Object)(object)ZNetScene.instance || (Object)(object)ZNet.instance == (Object)null || baseRestorePreview.Snapshot.World != ZNet.instance.GetWorldUID() || baseRestorePreview.Player != localPlayer.GetPlayerID())
			{
				return;
			}
			int num = 0;
			List<EditChange> list = new List<EditChange>();
			foreach (BaseRestoreSlot item in baseRestorePreview.Missing)
			{
				try
				{
					Piece present;
					switch (ClassifyBaseSlot(baseRestorePreview.Snapshot, item.Index, item.State, out present))
					{
					case 0:
						baseRestorePreview.Existing[item.Index] = BuildingView(present).GetZDO().m_uid;
						num++;
						break;
					default:
						num++;
						break;
					case 1:
					{
						Piece val = CreateEditedPiece(item.State, item.State, allowBlueprintDoor: true);
						ZNetView val2 = BuildingView(val);
						list.Add(new EditChange
						{
							Current = val,
							LiveZdo = val2.GetZDO(),
							After = item.State,
							Placement = true
						});
						baseRestorePreview.Existing[item.Index] = val2.GetZDO().m_uid;
						try
						{
							RefreshEditedWear(val);
						}
						catch (Exception ex)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("[Base support] " + ex.Message));
						}
						break;
					}
					}
				}
				catch (Exception ex2)
				{
					num++;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Base restore] " + ex2));
				}
			}
			if (list.Count > 0)
			{
				PushBuildingUndo(new BuildingUndo
				{
					Name = "Восстановление базы: " + list.Count,
					Edits = list
				});
			}
			foreach (KeyValuePair<int, ZDOID> item2 in baseRestorePreview.Existing)
			{
				BasePartData basePartData = baseRestorePreview.Snapshot.Data[item2.Key];
				ZDOID value = item2.Value;
				basePartData.User = ((ZDOID)(ref value)).UserID;
				value = item2.Value;
				basePartData.Id = ((ZDOID)(ref value)).ID;
			}
			_baseStatus = "Восстановлено: " + list.Count + ". Пропущено при применении: " + num + ". Целые детали не изменены. Ctrl+Z отменяет добавление.";
			try
			{
				SaveBaseLibrary();
			}
			catch (Exception ex3)
			{
				_baseStatus = _baseStatus + " Не удалось сохранить новые ссылки снимка: " + ex3.Message;
			}
			Physics.SyncTransforms();
			ClearEditedNeighbors();
			CancelEditPreview();
			_buildingScanAt = (_buildingBoundsAt = 0f);
			_buildingStatus = (_editStatus = _baseStatus);
		}

		private void DrawBaseRecovery(Rect area)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0478: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0570: Unknown result type (might be due to invalid IL or missing references)
			//IL_0598: Unknown result type (might be due to invalid IL or missing references)
			//IL_0648: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0757: Unknown result type (might be due to invalid IL or missing references)
			//IL_079b: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e9: Unknown result type (might be due to invalid IL or missing references)
			EnsureWorkshopTheme();
			SyncBuildingSelection();
			Rect panel = default(Rect);
			((Rect)(ref panel))..ctor(0f, 0f, ((Rect)(ref area)).width * 0.35f, ((Rect)(ref area)).height);
			Rect panel2 = default(Rect);
			((Rect)(ref panel2))..ctor(((Rect)(ref area)).width * 0.35f + 12f, 0f, ((Rect)(ref area)).width * 0.65f - 12f, ((Rect)(ref area)).height);
			WorkshopPanel(panel, "СНИМКИ БАЗ", 0);
			WorkshopPanel(panel2, "ВОССТАНОВЛЕНИЕ БАЗЫ", 1);
			BuildingText(new Rect(16f, 74f, ((Rect)(ref panel)).width - 32f, 54f), "Снимков: " + _baseSnapshots.Count + " / 10");
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(14f, 140f, ((Rect)(ref panel)).width - 28f, Mathf.Max(20f, ((Rect)(ref panel)).height - 156f));
			_baseLibraryScroll = GUI.BeginScrollView(val, _baseLibraryScroll, new Rect(0f, 0f, ((Rect)(ref val)).width - 22f, Mathf.Max(((Rect)(ref val)).height, (float)(_baseSnapshots.Count * 92))));
			foreach (var item in _baseSnapshots.Select((BaseSnapshot s, int i) => new { s, i }))
			{
				bool flag = (Object)(object)ZNet.instance != (Object)null && item.s.World == ZNet.instance.GetWorldUID();
				if (WorldButton(new Rect(0f, (float)(item.i * 92), ((Rect)(ref val)).width - 24f, 84f), item.s.Shape.Name + "\n" + item.s.Shape.Pieces.Count + " деталей" + (flag ? "" : " · другой мир"), item.s.Shape.Id == _baseSelectedId) && _baseSelectedId != item.s.Shape.Id)
				{
					CancelEditPreview();
					_baseSelectedId = item.s.Shape.Id;
					_baseName = item.s.Shape.Name;
					_baseStatus = "Выбран снимок «" + item.s.Shape.Name + "». Подойди к исходному месту базы и проверь восстановление.";
				}
			}
			GUI.EndScrollView();
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref panel2)).x + 22f, 74f, ((Rect)(ref panel2)).width - 44f, ((Rect)(ref panel2)).height - 90f);
			_baseSettingsScroll = GUI.BeginScrollView(val2, _baseSettingsScroll, new Rect(0f, 0f, ((Rect)(ref val2)).width - 22f, Mathf.Max(((Rect)(ref val2)).height, 1200f)));
			float num = ((Rect)(ref val2)).width - 24f;
			float num2 = 0f;
			bool enabled = GUI.enabled;
			BaseSnapshot baseSnapshot = SelectedBaseSnapshot();
			BuildingText(new Rect(0f, num2, num, 76f), "Сохрани снимок, пока база целая. Позже восстановятся только отсутствующие части в исходном мире и на исходных местах. Сундуки и устройства не входят в снимок.");
			num2 += 88f;
			GUI.enabled = enabled && _buildingJob == null && (Object)(object)Player.m_localPlayer != (Object)null;
			if (WorldButton(new Rect(0f, num2, num, 44f), "ВЫДЕЛИТЬ БАЗУ ДВУМЯ ТОЧКАМИ", selected: true))
			{
				BeginWorldBuildingSelection(25);
			}
			num2 += 52f;
			BuildingText(new Rect(0f, num2, num, 34f), "Выделено: " + BuildingSelectionCount + " / " + 10000);
			num2 += 40f;
			if (BuildingSelectionCount > 500)
			{
				BuildingText(new Rect(0f, num2, num, 52f), "Большое выделение может вызвать просадки FPS и задержки. Подсвечиваются до 500 деталей.");
				num2 += 58f;
			}
			_baseName = DraftNameField(new Rect(0f, num2, num, 40f), _baseName, "Моя база");
			num2 += 50f;
			if (WorldButton(new Rect(0f, num2, num, 44f), "СОХРАНИТЬ НОВЫЙ СНИМОК БАЗЫ"))
			{
				SaveBaseSnapshot(update: false);
			}
			num2 += 52f;
			GUI.enabled = enabled && _buildingJob == null && baseSnapshot != null && (Object)(object)ZNet.instance != (Object)null && baseSnapshot.World == ZNet.instance.GetWorldUID();
			if (WorldButton(new Rect(0f, num2, num, 42f), "ОБНОВИТЬ СНИМОК ИЗ ВЫДЕЛЕНИЯ"))
			{
				SaveBaseSnapshot(update: true);
			}
			num2 += 52f;
			WaveSectionHeading(new Rect(0f, num2, num, 36f), "ВОССТАНОВЛЕНИЕ ИЗ СНИМКА");
			num2 += 44f;
			BuildingText(new Rect(0f, num2, num, 58f), (baseSnapshot == null) ? "Выбери сохранённую базу слева" : (baseSnapshot.Shape.Name + " · " + baseSnapshot.Shape.Pieces.Count + " деталей\nМесто: " + string.Join(" / ", baseSnapshot.Origin.Select((float n) => n.ToString("0.#")))));
			num2 += 70f;
			if (WorldButton(new Rect(0f, num2, num, 46f), "ПРОВЕРИТЬ И ПОКАЗАТЬ НЕДОСТАЮЩЕЕ"))
			{
				PrepareBaseRecovery();
			}
			num2 += 54f;
			GUI.enabled = enabled && _buildingJob == null && _baseRestorePreview != null;
			if (WorldButton(new Rect(0f, num2, num, 42f), "ПОКАЗАТЬ ПРЕДПРОСМОТР В ИГРЕ"))
			{
				SetMenuVisible(visible: false);
			}
			num2 += 50f;
			if (WorldButton(new Rect(0f, num2, num, 48f), "ВОССТАНОВИТЬ НЕДОСТАЮЩИЕ ЧАСТИ", selected: true))
			{
				ApplyBaseRecovery();
			}
			num2 += 56f;
			if (WorldButton(new Rect(0f, num2, num, 40f), "ОТМЕНИТЬ ПРЕДПРОСМОТР"))
			{
				CancelEditPreview();
				_baseStatus = "Предпросмотр отменён.";
			}
			num2 += 48f;
			GUI.enabled = enabled && _buildingJob == null && _buildingHistory.Count > 0;
			if (WorldButton(new Rect(0f, num2, num, 42f), "ОТМЕНИТЬ ДОБАВЛЕНИЕ · CTRL+Z"))
			{
				UndoBuildingAction();
				_baseStatus = _buildingStatus;
			}
			num2 += 50f;
			GUI.enabled = enabled;
			WaveCard(new Rect(0f, num2, num, 146f));
			BuildingText(new Rect(10f, num2 + 8f, num - 20f, 130f), _baseStatus);
			num2 += 160f;
			BuildingText(new Rect(0f, num2, num, 120f), "Проверка и восстановление — в пределах 100 м от персонажа. Перемещённые/изменённые детали и занятые места пропускаются. Существующие детали не ремонтируются и не заменяются. Снимки сохраняются между запусками.");
			GUI.EndScrollView();
		}

		private static void WriteSnapshotList<T>(BinaryWriter w, List<KeyValuePair<int, T>> rows, Action<T> write)
		{
			if (rows.Count > 256)
			{
				throw new InvalidOperationException("Слишком много свойств детали");
			}
			w.Write(rows.Count);
			foreach (KeyValuePair<int, T> row in rows)
			{
				w.Write(row.Key);
				write(row.Value);
			}
		}

		private static List<KeyValuePair<int, T>> ReadSnapshotList<T>(BinaryReader r, Func<T> read)
		{
			int num = r.ReadInt32();
			if (num < 0 || num > 256)
			{
				throw new FormatException("Слишком много свойств детали");
			}
			List<KeyValuePair<int, T>> list = new List<KeyValuePair<int, T>>();
			for (int i = 0; i < num; i++)
			{
				list.Add(new KeyValuePair<int, T>(r.ReadInt32(), read()));
			}
			return list;
		}

		private static string PackBaseState(EditState s)
		{
			using MemoryStream memoryStream = new MemoryStream();
			BinaryWriter w = new BinaryWriter(memoryStream);
			try
			{
				w.Write(1);
				w.Write(s.Creator);
				w.Write(s.CreatorIndex);
				w.Write(s.DoorState.HasValue);
				if (s.DoorState.HasValue)
				{
					w.Write(s.DoorState.Value);
				}
				WriteSnapshotList(w, s.Floats, delegate(float v)
				{
					w.Write(v);
				});
				WriteSnapshotList(w, s.Vectors, delegate(Vector3 v)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_0017: Unknown result type (might be due to invalid IL or missing references)
					//IL_0028: Unknown result type (might be due to invalid IL or missing references)
					w.Write(v.x);
					w.Write(v.y);
					w.Write(v.z);
				});
				WriteSnapshotList(w, s.Quaternions, delegate(Quaternion v)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_0017: Unknown result type (might be due to invalid IL or missing references)
					//IL_0028: Unknown result type (might be due to invalid IL or missing references)
					//IL_0039: Unknown result type (might be due to invalid IL or missing references)
					w.Write(v.x);
					w.Write(v.y);
					w.Write(v.z);
					w.Write(v.w);
				});
				WriteSnapshotList(w, s.Ints, delegate(int v)
				{
					w.Write(v);
				});
				WriteSnapshotList(w, s.Longs, delegate(long v)
				{
					w.Write(v);
				});
				WriteSnapshotList(w, s.Strings, delegate(string v)
				{
					w.Write(v ?? "");
				});
				WriteSnapshotList(w, s.Bytes, delegate(byte[] v)
				{
					w.Write((v != null) ? v.Length : 0);
					if (v != null)
					{
						w.Write(v);
					}
				});
				w.Flush();
				string text = Convert.ToBase64String(memoryStream.ToArray());
				if (text.Length > 16384)
				{
					throw new InvalidOperationException("Слишком много данных детали");
				}
				UnpackBaseState(new EditState(), text);
				return text;
			}
			finally
			{
				if (w != null)
				{
					((IDisposable)w).Dispose();
				}
			}
		}

		private static void UnpackBaseState(EditState s, string data)
		{
			using MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(data));
			BinaryReader r = new BinaryReader(memoryStream);
			try
			{
				if (r.ReadInt32() != 1)
				{
					throw new FormatException("Неизвестный формат свойств");
				}
				s.Creator = r.ReadInt64();
				s.CreatorIndex = r.ReadInt32();
				s.DoorState = (r.ReadBoolean() ? new int?(r.ReadInt32()) : ((int?)null));
				Func<float> f = delegate
				{
					float num = r.ReadSingle();
					if (!BuildingRules.Finite(num))
					{
						throw new FormatException();
					}
					return num;
				};
				s.Floats = ReadSnapshotList(r, f);
				s.Vectors = ReadSnapshotList(r, (Func<Vector3>)(() => new Vector3(f(), f(), f())));
				s.Quaternions = ReadSnapshotList(r, (Func<Quaternion>)(() => new Quaternion(f(), f(), f(), f())));
				s.Ints = ReadSnapshotList(r, r.ReadInt32);
				s.Longs = ReadSnapshotList(r, r.ReadInt64);
				s.Strings = ReadSnapshotList(r, delegate
				{
					string text = r.ReadString();
					if (text.Length > 2048)
					{
						throw new FormatException();
					}
					return text;
				});
				s.Bytes = ReadSnapshotList(r, delegate
				{
					int num = r.ReadInt32();
					if (num < 0 || num > 8192)
					{
						throw new FormatException();
					}
					byte[] array = r.ReadBytes(num);
					if (array.Length != num)
					{
						throw new EndOfStreamException();
					}
					return array;
				});
				if (memoryStream.Position != memoryStream.Length)
				{
					throw new FormatException("Лишние данные снимка");
				}
			}
			finally
			{
				if (r != null)
				{
					((IDisposable)r).Dispose();
				}
			}
		}

		private void DrawBlueprintNumber(string label, ref string text, float step, float min, float max, float width, ref float y)
		{
			string obj = text;
			DrawEditNumber(label, ref text, step, min, max, width, ref y);
			if (obj != text)
			{
				BlueprintDraftChanged();
			}
		}

		private void DrawBlueprints(Rect area)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			//IL_0575: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_062d: Unknown result type (might be due to invalid IL or missing references)
			//IL_065e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0795: Unknown result type (might be due to invalid IL or missing references)
			//IL_080d: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0941: Unknown result type (might be due to invalid IL or missing references)
			//IL_0973: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a02: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a46: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a6f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ad0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b0c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bdc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c0b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c98: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d20: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d7d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dcc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e90: Unknown result type (might be due to invalid IL or missing references)
			//IL_0efa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f22: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fd2: Unknown result type (might be due to invalid IL or missing references)
			//IL_101f: Unknown result type (might be due to invalid IL or missing references)
			//IL_106f: Unknown result type (might be due to invalid IL or missing references)
			EnsureWorkshopTheme();
			SyncBuildingSelection();
			float num = 12f;
			float num2 = ((Rect)(ref area)).width * 0.29f;
			float num3 = ((Rect)(ref area)).width * 0.37f;
			Rect panel = default(Rect);
			((Rect)(ref panel))..ctor(0f, 0f, num2, ((Rect)(ref area)).height);
			Rect panel2 = default(Rect);
			((Rect)(ref panel2))..ctor(num2 + num, 0f, num3, ((Rect)(ref area)).height);
			Rect panel3 = default(Rect);
			((Rect)(ref panel3))..ctor(((Rect)(ref panel2)).xMax + num, 0f, ((Rect)(ref area)).width - ((Rect)(ref panel2)).xMax - num, ((Rect)(ref area)).height);
			WorkshopPanel(panel, "БИБЛИОТЕКА ЧЕРТЕЖЕЙ", 0);
			WorkshopPanel(panel2, "РАЗМЕЩЕНИЕ КОПИИ", 1);
			WorkshopPanel(panel3, "СОСТАВ И СОХРАНЕНИЕ", 2);
			bool enabled = GUI.enabled;
			BuildingBlueprint blueprint = SelectedBlueprint();
			BuildingText(new Rect(16f, 74f, ((Rect)(ref panel)).width - 32f, 36f), "Выделено: " + BuildingSelectionCount + " · Чертежей: " + _blueprints.Count + " / 30");
			GUI.enabled = enabled && _buildingJob == null && (Object)(object)Player.m_localPlayer != (Object)null;
			if (WorldButton(new Rect(16f, 114f, ((Rect)(ref panel)).width - 32f, 44f), "ВЫДЕЛИТЬ ПОСТРОЙКУ В МИРЕ", selected: true))
			{
				BeginWorldBuildingSelection();
			}
			GUI.enabled = enabled;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(14f, 168f, ((Rect)(ref panel)).width - 28f, Mathf.Max(20f, ((Rect)(ref panel)).height - 266f));
			_blueprintListScroll = GUI.BeginScrollView(val, _blueprintListScroll, new Rect(0f, 0f, ((Rect)(ref val)).width - 20f, Mathf.Max(((Rect)(ref val)).height, (float)(_blueprints.Count * 92))));
			GUI.enabled = enabled && _buildingJob == null;
			Rect rect = default(Rect);
			for (int i = 0; i < _blueprints.Count; i++)
			{
				BuildingBlueprint buildingBlueprint = _blueprints[i];
				((Rect)(ref rect))..ctor(0f, (float)(i * 92), ((Rect)(ref val)).width - 22f, 82f);
				if (WorldButton(rect, "", buildingBlueprint.Id == _blueprintSelectedId) && buildingBlueprint.Id != _blueprintSelectedId)
				{
					CancelEditPreview();
					_blueprintDeleteId = null;
					_blueprintSelectedId = buildingBlueprint.Id;
					_blueprintName = buildingBlueprint.Name;
					blueprint = buildingBlueprint;
					_blueprintStatus = "Выбран чертёж «" + buildingBlueprint.Name + "». Задай точку размещения и создай предпросмотр.";
				}
				BuildingText(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 8f, ((Rect)(ref rect)).width - 16f, 38f), buildingBlueprint.Name);
				BuildingText(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 47f, ((Rect)(ref rect)).width - 16f, 28f), "Деталей: " + buildingBlueprint.Pieces.Count);
			}
			GUI.enabled = enabled;
			GUI.EndScrollView();
			Rect rect2 = default(Rect);
			((Rect)(ref rect2))..ctor(((Rect)(ref val)).x, ((Rect)(ref panel)).yMax - 54f, ((Rect)(ref val)).width, 38f);
			GUI.enabled = enabled && _buildingJob == null && blueprint != null;
			if (blueprint != null && blueprint.Id == _blueprintDeleteId)
			{
				string text = string.Format(MenuLanguage.Text("Удалить чертёж «{0}»?"), blueprint.Name);
				BuildingText(new Rect(((Rect)(ref rect2)).x, ((Rect)(ref rect2)).y - 34f, ((Rect)(ref rect2)).width, 32f), text);
				float num4 = (((Rect)(ref rect2)).width - 6f) / 2f;
				if (WorldButton(new Rect(((Rect)(ref rect2)).x, ((Rect)(ref rect2)).y, num4, ((Rect)(ref rect2)).height), "Удалить", selected: true) && DeleteSelectedBlueprint(blueprint))
				{
					blueprint = null;
				}
				if (WorldButton(new Rect(((Rect)(ref rect2)).x + num4 + 6f, ((Rect)(ref rect2)).y, num4, ((Rect)(ref rect2)).height), "Отмена"))
				{
					_blueprintDeleteId = null;
				}
			}
			else if (WorldButton(rect2, "Удалить чертёж"))
			{
				_blueprintDeleteId = blueprint.Id;
			}
			GUI.enabled = enabled;
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref panel2)).x + 16f, 74f, ((Rect)(ref panel2)).width - 32f, ((Rect)(ref panel2)).height - 90f);
			_blueprintSettingsScroll = GUI.BeginScrollView(val2, _blueprintSettingsScroll, new Rect(0f, 0f, ((Rect)(ref val2)).width - 20f, Mathf.Max(((Rect)(ref val2)).height, 1120f)));
			float num5 = ((Rect)(ref val2)).width - 22f;
			float num6 = 0f;
			BuildingText(new Rect(0f, num6, num5, 52f), (blueprint == null) ? "Выбери чертёж слева" : (blueprint.Name + " · " + blueprint.Pieces.Count + " деталей"));
			num6 += 62f;
			GUI.enabled = enabled && _buildingJob == null && (Object)(object)Player.m_localPlayer != (Object)null;
			if (WorldButton(new Rect(0f, num6, num5, 44f), "ТОЧКА НА ЗЕМЛЕ ПЕРЕД ПЕРСОНАЖЕМ"))
			{
				SetBlueprintAnchor();
			}
			num6 += 52f;
			BuildingText(new Rect(0f, num6, num5, 52f), _blueprintHasAnchor ? ("Точка: " + _blueprintAnchor.x.ToString("0.#") + " / " + _blueprintAnchor.y.ToString("0.#") + " / " + _blueprintAnchor.z.ToString("0.#")) : "Точка не задана");
			num6 += 62f;
			DrawBlueprintNumber("Смещение X, м", ref _blueprintX, _editMoveStep, -50f, 50f, num5, ref num6);
			DrawBlueprintNumber("Смещение Y — высота, м", ref _blueprintY, _editMoveStep, -50f, 50f, num5, ref num6);
			DrawBlueprintNumber("Смещение Z, м", ref _blueprintZ, _editMoveStep, -50f, 50f, num5, ref num6);
			DrawBlueprintNumber("Поворот, °", ref _blueprintYaw, _editRotateStep, -180f, 180f, num5, ref num6);
			if (W