Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MoveBuildPieces v1.1.1
MoveBuildPieces.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] namespace Obelisk.MoveBuildPieces; [BepInPlugin("obelisk.valheim.movebuildpieces", "MoveBuildPieces", "1.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class MoveBuildPiecesPlugin : BaseUnityPlugin { public const string PluginGuid = "obelisk.valheim.movebuildpieces"; public const string PluginName = "MoveBuildPieces"; public const string PluginVersion = "1.1.1"; private static ConfigEntry<bool> _enabled; private static ConfigEntry<MoveActivationMode> _moveMode; private static ConfigEntry<KeyboardShortcut> _buildModeMoveHotkey; private static ConfigEntry<KeyboardShortcut> _worldModeMoveHotkey; private static ConfigEntry<KeyboardShortcut> _mixedModeMoveHotkey; private static ConfigEntry<bool> _requireKnownPiece; private static ConfigEntry<bool> _blockTerrainModifiers; private static ConfigEntry<bool> _blockDynamicObjects; private static ConfigEntry<float> _moveLockTimeoutSeconds; private Harmony _harmony; internal static bool IsEnabled => _enabled.Value; internal static MoveActivationMode ActiveMode => _moveMode.Value; internal static KeyboardShortcut BuildModeMoveHotkey => _buildModeMoveHotkey.Value; internal static KeyboardShortcut WorldModeMoveHotkey => _worldModeMoveHotkey.Value; internal static KeyboardShortcut MixedModeMoveHotkey => _mixedModeMoveHotkey.Value; internal static bool RequireKnownPiece => MoveController.ResolveRequireKnownPiece(_requireKnownPiece.Value); internal static bool BlockTerrainModifiers => MoveController.ResolveBlockTerrainModifiers(_blockTerrainModifiers.Value); internal static bool BlockDynamicObjects => MoveController.ResolveBlockDynamicObjects(_blockDynamicObjects.Value); internal static float MoveLockTimeoutSeconds { get { float value = _moveLockTimeoutSeconds.Value; return MoveController.ResolveMoveLockTimeout((float.IsNaN(value) || float.IsInfinity(value)) ? 45f : Mathf.Clamp(value, 5f, 300f)); } } private void Awake() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable moving already built player-built pieces."); _moveMode = ((BaseUnityPlugin)this).Config.Bind<MoveActivationMode>("General", "Move mode", MoveActivationMode.Mixed, "Choose whether moving works in build mode, world mode, or both through Mixed mode."); _buildModeMoveHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Build mode move hotkey", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), "Press while hovering a buildable player-built piece in build mode to start or cancel moving it."); _worldModeMoveHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "World mode move hotkey", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), "Press while hovering a buildable player-built piece outside build mode to start or cancel moving it."); _mixedModeMoveHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Mixed mode move hotkey", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), "Press in or outside build mode to start or cancel moving a piece while Move mode is Mixed."); _requireKnownPiece = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "Require known piece", false, "Only allow moving pieces the player has learned. Disable to move player-built pieces before learning their recipes."); _blockTerrainModifiers = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "Block terrain modifiers", true, "Do not move pieces that contain TerrainModifier or TerrainOp components."); _blockDynamicObjects = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "Block dynamic objects", true, "Do not move ships, carts, characters, or pieces with non-kinematic rigidbodies."); _moveLockTimeoutSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "Move lock timeout seconds", 45f, "How long a move lock can survive without being released, used as a multiplayer disconnect safety net."); MoveController.Initialize(); _harmony = new Harmony("obelisk.valheim.movebuildpieces"); _harmony.PatchAll(); AAABuildMenuCompatibility.Apply(_harmony); } private void OnDestroy() { MoveController.Reset(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal enum MoveActivationMode { BuildMenu, World, Mixed } [HarmonyPatch(typeof(Player), "Update")] internal static class PlayerUpdatePatch { private static void Postfix(Player __instance) { MoveController.Update(__instance); } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] internal static class PlayerUpdatePlacementPatch { private static bool Prefix(Player __instance) { return !MoveController.ShouldSkipVanillaUpdatePlacement(__instance); } } [HarmonyPatch(typeof(Player), "LateUpdate")] internal static class PlayerLateUpdatePatch { private static void Postfix(Player __instance) { MoveController.UpdateVisuals(__instance); } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] internal static class PlayerUpdatePlacementGhostPatch { private static bool Prefix(Player __instance) { return MoveController.ShouldRunPlacementGhostUpdate(__instance); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo overlapSphereWithMask = AccessTools.Method(typeof(Physics), "OverlapSphere", new Type[3] { typeof(Vector3), typeof(float), typeof(int) }, (Type[])null); MethodInfo filteredOverlapSphereWithMask = AccessTools.Method(typeof(PlacementPhysicsBridge), "OverlapSphere", new Type[3] { typeof(Vector3), typeof(float), typeof(int) }, (Type[])null); MethodInfo overlapSphere = AccessTools.Method(typeof(Physics), "OverlapSphere", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null); MethodInfo filteredOverlapSphere = AccessTools.Method(typeof(PlacementPhysicsBridge), "OverlapSphere", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Call && object.Equals(instruction.operand, overlapSphereWithMask)) { instruction.operand = filteredOverlapSphereWithMask; } else if (instruction.opcode == OpCodes.Call && object.Equals(instruction.operand, overlapSphere)) { instruction.operand = filteredOverlapSphere; } yield return instruction; } } } [HarmonyPatch(typeof(Player), "TestGhostClipping")] internal static class PlayerTestGhostClippingPatch { private static bool Prefix(Player __instance, GameObject ghost, float maxPenetration, ref bool __result) { return !MoveController.TryTestGhostClippingIgnoringMovedPiece(__instance, ghost, maxPenetration, out __result); } } [HarmonyPatch(typeof(Player), "IsOverlappingOtherPiece")] internal static class PlayerPieceOverlapPatch { private static bool Prefix(Player __instance, Vector3 p, Quaternion rotation, string pieceName, List<Piece> pieces, bool allowRotatedOverlap, ref bool __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return !MoveController.TryEvaluatePieceOverlapIgnoringMovedPiece(__instance, p, rotation, pieceName, pieces, allowRotatedOverlap, out __result); } } [HarmonyPatch(typeof(StationExtension), "OtherExtensionInRange")] internal static class StationExtensionRangePatch { private static bool Prefix(StationExtension __instance, float radius, ref bool __result) { return !MoveController.TryEvaluateExtensionRangeIgnoringMovedPiece(__instance, radius, out __result); } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class PlayerSetControlsPatch { private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold) { MoveController.SuppressAttackControls(__instance, ref attack, ref attackHold, ref secondaryAttack, ref secondaryAttackHold); } } [HarmonyPatch(typeof(Player), "TeleportTo")] internal static class PlayerTeleportToPatch { private static void Prefix(Player __instance) { MoveController.CancelForTeleport(__instance); } } [HarmonyPatch(typeof(Player), "OnDeath")] internal static class PlayerOnDeathPatch { private static void Prefix(Player __instance) { MoveController.CancelForDeath(__instance); } } [HarmonyPatch(typeof(Player), "OnDestroy")] internal static class PlayerOnDestroyPatch { private static void Prefix(Player __instance) { MoveController.CancelForPlayerDestroyed(__instance); } } [HarmonyPatch(typeof(Door), "Interact")] internal static class DoorInteractPatch { private static void Postfix(Humanoid character, bool hold, bool __result) { if (__result && !hold) { Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { MoveController.NotifyDoorInteracted(val); } } } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] internal static class PlayerHaveRequirementsPatch { private static bool Prefix(Player __instance, Piece piece, RequirementMode mode, ref bool __result) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (MoveController.ShouldBypassRequirements(__instance, piece, mode)) { __result = true; return false; } return true; } } [HarmonyPatch(typeof(PieceTable), "UpdateAvailable", new Type[] { typeof(HashSet<string>), typeof(Player), typeof(bool), typeof(bool) })] internal static class PieceTableUpdateAvailablePatch { private static bool Prefix(PieceTable __instance) { return !MoveController.IsTemporaryPieceTable(__instance); } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] internal static class PlayerTryPlacePiecePatch { private static bool Prefix(Player __instance, Piece piece, ref bool __result) { if (!MoveController.ShouldHandlePlacement(__instance)) { return true; } __result = false; MoveController.TryFinishMove(__instance); return false; } } [HarmonyPatch(typeof(Player), "RemovePiece")] internal static class PlayerRemovePiecePatch { private static bool Prefix(Player __instance, ref bool __result) { if (!MoveController.ShouldBlockBuildAction(__instance)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Player), "CopyPiece")] internal static class PlayerCopyPiecePatch { private static bool Prefix(Player __instance, ref bool __result) { if (!MoveController.ShouldBlockBuildAction(__instance)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(ZRoutedRpc), "RPC_RoutedRPC")] internal static class RoutedRpcSenderValidationPatch { private static bool Prefix(ZRoutedRpc __instance, ZRpc rpc, ZPackage pkg) { return MoveController.ValidateRoutedRpcSender(__instance, rpc, pkg); } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class ZNetAwakePatch { private static void Postfix(ZNet __instance) { MoveController.OnNetworkStarted(__instance); } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] internal static class ZNetNewConnectionPatch { private static void Postfix(ZNetPeer peer) { MoveController.RegisterNetworkPeer(peer); } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] internal static class ZNetDestroyPatch { private static void Prefix(ZNet __instance) { MoveController.OnNetworkStopped(__instance); } } [HarmonyPatch(typeof(ZNet), "Disconnect")] internal static class ZNetDisconnectPatch { private static void Prefix(ZNetPeer peer) { MoveController.UnregisterNetworkPeer(peer); } } [HarmonyPatch(typeof(ZNetScene), "Shutdown")] internal static class ZNetSceneShutdownPatch { private static void Prefix() { MoveController.PrepareForNetworkShutdown(); } } internal sealed class MovePieceTableMarker : MonoBehaviour { } internal static class AAABuildMenuCompatibility { internal const string PluginGuid = "Azumatt.AAABuildMenu"; private const string EnhancedBuildMenuTypeName = "AAABuildMenu.EnhancedBuildMenu"; private static PropertyInfo _needsRefreshProperty; internal static void Apply(Harmony harmony) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown _needsRefreshProperty = null; if (harmony == null || !Chainloader.PluginInfos.ContainsKey("Azumatt.AAABuildMenu")) { return; } Type type = AccessTools.TypeByName("AAABuildMenu.EnhancedBuildMenu"); if (type == null) { Debug.LogWarning((object)"[MoveBuildPieces] AAABuildMenu is installed, but its enhanced menu type was not found; compatibility mode was not enabled."); return; } MethodInfo methodInfo = AccessTools.Method(type, "ApplyFilter", new Type[3] { typeof(Player), typeof(PieceTable), typeof(bool) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "CaptureMasterAndApply", new Type[2] { typeof(Player), typeof(PieceTable) }, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(AAABuildMenuCompatibility), "AllowPieceTableMutation", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo3 == null) { Debug.LogWarning((object)"[MoveBuildPieces] AAABuildMenu is installed, but its filter API was not found; compatibility mode was not enabled."); return; } try { _needsRefreshProperty = AccessTools.Property(type, "NeedsRefresh"); HarmonyMethod val = new HarmonyMethod(methodInfo3); harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Debug.Log((object)"[MoveBuildPieces] AAABuildMenu compatibility enabled."); } catch (Exception ex) { Debug.LogWarning((object)("[MoveBuildPieces] AAABuildMenu compatibility failed: " + ex.GetBaseException().Message)); } } private static bool AllowPieceTableMutation(object[] __args) { PieceTable table = null; if (__args != null) { foreach (object obj in __args) { PieceTable val = (PieceTable)((obj is PieceTable) ? obj : null); if (val != null) { table = val; break; } } } if (!MoveController.IsTemporaryPieceTable(table)) { return true; } try { PropertyInfo needsRefreshProperty = _needsRefreshProperty; if ((object)needsRefreshProperty != null && needsRefreshProperty.CanWrite) { _needsRefreshProperty.SetValue(null, false, null); } } catch { } return false; } } public static class PlacementPhysicsBridge { public static Collider[] OverlapSphere(Vector3 position, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return MoveController.FilterPlacementOverlap(Physics.OverlapSphere(position, radius)); } public static Collider[] OverlapSphere(Vector3 position, float radius, int layerMask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return MoveController.FilterPlacementOverlap(Physics.OverlapSphere(position, radius, layerMask)); } } internal static class MoveController { private enum MoveContext { Build, World } private sealed class MoveState { public Player Player; public Piece Piece; public ZNetView NetView; public string PrefabName; public MoveContext Context; public MoveActivationMode ActivationMode; public GameObject RelocateTableObject; public PieceTable OriginalBuildPieces; public PieceTable ActivePieceTable; public Vector3 OriginalPosition; public List<EffectArea> OriginalBuildAreas; public long LockPlayerId; public long LockPeerId; public long LockToken; public long LockOwnerPeerId; public long LockRequestOwnerPeerId; public float LastLockRefreshTime; public bool WaitingForMoveResult; public long MoveRequestOwnerPeerId; public float MoveRequestStartedAt; public float FirstMoveRequestStartedAt; public int MoveRequestAttempts; public float LastServerVerifyRequestAt; public float MoveFailureReceivedAt; public string MoveFailureMessage; public Vector3 PendingTargetPosition; public Quaternion PendingTargetRotation; public bool UpdateBedSpawnPoint; public Vector3 BedSpawnLocalPoint; public Vector3 BedOriginalProfileSpawnPoint; public GameObject HighlightedGhost; public bool GhostHighlighted; public bool OriginGeometryCached; public Vector3 OriginGroundPoint; public Vector3 OriginLinkPoint; public float OriginRingRadius; public bool VisualGeometryCached; public Vector3 LastGhostPosition; public Quaternion LastGhostRotation; public bool LastGhostVisible; } private sealed class PendingMoveRequest { public Player Player; public Piece Piece; public ZNetView NetView; public MoveContext Context; public MoveActivationMode ActivationMode; public long PlayerId; public long LockToken; public long ExpectedOwnerPeerId; public float StartedAt; public float LastRequestAt; } private sealed class CancelledLockRequest { public ZDOID ZdoId; public long PlayerId; public long LockToken; public long ExpectedOwnerPeerId; public float CancelledAt; } private sealed class OwnerMoveSnapshot { public Vector3 TransformPosition; public Quaternion TransformRotation; public Vector3 ZdoPosition; public Quaternion ZdoRotation; public long LastMoveToken; public long LastMovePeer; public long LastMovePlayer; public long LockOwner; public long LockPeer; public long LockToken; public long LockUntil; public string LockName; public List<RigidbodySnapshot> RigidbodyStates; public List<FieldValueSnapshot> ComponentFields; } private sealed class RigidbodySnapshot { public Rigidbody Body; public Vector3 Position; public Quaternion Rotation; public Vector3 LinearVelocity; public Vector3 AngularVelocity; } private sealed class FieldValueSnapshot { public object Target; public FieldInfo Field; public object Value; } private sealed class RaycastHitDistanceComparer : IComparer<RaycastHit> { public static readonly RaycastHitDistanceComparer Instance = new RaycastHitDistanceComparer(); public int Compare(RaycastHit x, RaycastHit y) { return ((RaycastHit)(ref x)).distance.CompareTo(((RaycastHit)(ref y)).distance); } } private static readonly FieldInfo PlacementGhostField = AccessTools.Field(typeof(Player), "m_placementGhost"); private static readonly FieldInfo BuildPiecesField = AccessTools.Field(typeof(Player), "m_buildPieces"); private static readonly FieldInfo PlacementStatusField = AccessTools.Field(typeof(Player), "m_placementStatus"); private static readonly FieldInfo EyeField = AccessTools.Field(typeof(Character), "m_eye"); private static readonly FieldInfo MaxPlaceDistanceField = AccessTools.Field(typeof(Player), "m_maxPlaceDistance"); private static readonly FieldInfo MaxInteractDistanceField = AccessTools.Field(typeof(Player), "m_maxInteractDistance"); private static readonly FieldInfo RemoveRayMaskField = AccessTools.Field(typeof(Player), "m_removeRayMask"); private static readonly FieldInfo PlaceRayMaskField = AccessTools.Field(typeof(Player), "m_placeRayMask"); private static readonly FieldInfo InteractMaskField = AccessTools.Field(typeof(Player), "m_interactMask"); private static readonly FieldInfo PlaceRotationField = AccessTools.Field(typeof(Player), "m_placeRotation"); private static readonly FieldInfo ScrollCurrentAmountField = AccessTools.Field(typeof(Player), "m_scrollCurrAmount"); private static readonly FieldInfo RotatePieceTimerField = AccessTools.Field(typeof(Player), "m_rotatePieceTimer"); private static readonly FieldInfo PieceTableAvailablePiecesField = AccessTools.Field(typeof(PieceTable), "m_availablePieces"); private static readonly FieldInfo PieceTableSelectedCategoryField = AccessTools.Field(typeof(PieceTable), "m_selectedCategory"); private static readonly FieldInfo AttackField = AccessTools.Field(typeof(Character), "m_attack"); private static readonly FieldInfo AttackHoldField = AccessTools.Field(typeof(Character), "m_attackHold"); private static readonly FieldInfo SecondaryAttackField = AccessTools.Field(typeof(Character), "m_secondaryAttack"); private static readonly FieldInfo SecondaryAttackHoldField = AccessTools.Field(typeof(Character), "m_secondaryAttackHold"); private static readonly FieldInfo QueuedAttackTimerField = AccessTools.Field(typeof(Player), "m_queuedAttackTimer"); private static readonly FieldInfo QueuedSecondAttackTimerField = AccessTools.Field(typeof(Player), "m_queuedSecondAttackTimer"); private static readonly FieldInfo AttackDrawTimeField = AccessTools.Field(typeof(Humanoid), "m_attackDrawTime"); private static readonly FieldInfo WearNTearCollidersField = AccessTools.Field(typeof(WearNTear), "m_colliders"); private static readonly FieldInfo WearNTearBoundsField = AccessTools.Field(typeof(WearNTear), "m_bounds"); private static readonly FieldInfo WearNTearClearCachedSupportField = AccessTools.Field(typeof(WearNTear), "m_clearCachedSupport"); private static readonly FieldInfo WearNTearRoofField = AccessTools.Field(typeof(WearNTear), "m_roof"); private static readonly FieldInfo WearNTearAshRoofField = AccessTools.Field(typeof(WearNTear), "m_ashroof"); private static readonly FieldInfo WearNTearBiomeField = AccessTools.Field(typeof(WearNTear), "m_biome"); private static readonly FieldInfo WearNTearHeightmapField = AccessTools.Field(typeof(WearNTear), "m_heightmap"); private static readonly FieldInfo WearNTearConnectedHeightmapField = AccessTools.Field(typeof(WearNTear), "m_connectedHeightMap"); private static readonly FieldInfo WearNTearGroundDistanceField = AccessTools.Field(typeof(WearNTear), "m_groundDist"); private static readonly FieldInfo WearNTearInAshlandsField = AccessTools.Field(typeof(WearNTear), "m_inAshlands"); private static readonly FieldInfo WearNTearLavaValueField = AccessTools.Field(typeof(WearNTear), "m_lavaValue"); private static readonly FieldInfo WearNTearLavaTimerField = AccessTools.Field(typeof(WearNTear), "m_lavaTimer"); private static readonly FieldInfo WearNTearAshTimerField = AccessTools.Field(typeof(WearNTear), "m_ashTimer"); private static readonly FieldInfo WearNTearRainTimerField = AccessTools.Field(typeof(WearNTear), "m_rainTimer"); private static readonly FieldInfo WearNTearUpdateCoverTimerField = AccessTools.Field(typeof(WearNTear), "m_updateCoverTimer"); private static readonly FieldInfo WearNTearHaveRoofField = AccessTools.Field(typeof(WearNTear), "m_haveRoof"); private static readonly FieldInfo WearNTearHaveAshRoofField = AccessTools.Field(typeof(WearNTear), "m_haveAshRoof"); private static readonly FieldInfo WearNTearShieldChangeIdField = AccessTools.Field(typeof(WearNTear), "m_shieldChangeID"); private static readonly FieldInfo WearNTearPreviousWaterVolumeField = AccessTools.Field(typeof(WearNTear), "m_previousWaterVolume"); private static readonly FieldInfo SapCollectorRootField = AccessTools.Field(typeof(SapCollector), "m_root"); private static readonly FieldInfo SapCollectorConnectedObjectField = AccessTools.Field(typeof(SapCollector), "m_connectedObject"); private static readonly FieldInfo ShieldGeneratorRadiusSentField = AccessTools.Field(typeof(ShieldGenerator), "m_radiusSent"); private static readonly FieldInfo FireplaceBiomeField = AccessTools.Field(typeof(Fireplace), "m_biome"); private static readonly FieldInfo CinderSpawnerBiomeField = AccessTools.Field(typeof(CinderSpawner), "m_biome"); private static readonly FieldInfo StaticRotationValueField = AccessTools.Field(typeof(StaticRotation), "m_rotation"); private static readonly PropertyInfo RigidbodyLinearVelocityProperty = AccessTools.Property(typeof(Rigidbody), "linearVelocity") ?? AccessTools.Property(typeof(Rigidbody), "velocity"); private static readonly EventInfo HeightmapSupportCacheEvent = typeof(Heightmap).GetEvent("m_clearConnectedWearNTearCache", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PrivateAreasField = AccessTools.Field(typeof(PrivateArea), "m_allAreas"); private static readonly FieldInfo PrivateAreaConnectionUpdateTimeField = AccessTools.Field(typeof(PrivateArea), "m_connectionUpdateTime"); private static readonly FieldInfo StationExtensionsField = AccessTools.Field(typeof(StationExtension), "m_allExtensions"); private static readonly FieldInfo CraftingStationsField = AccessTools.Field(typeof(CraftingStation), "m_allStations"); private static readonly FieldInfo CraftingStationExtensionTimerField = AccessTools.Field(typeof(CraftingStation), "m_updateExtensionTimer"); private static readonly FieldInfo EffectAreaColliderField = AccessTools.Field(typeof(EffectArea), "m_collider"); private static readonly FieldInfo EffectAreaNoMonsterAreaField = AccessTools.Field(typeof(EffectArea), "noMonsterArea"); private static readonly FieldInfo EffectAreaNoMonsterCloseAreaField = AccessTools.Field(typeof(EffectArea), "noMonsterCloseToArea"); private static readonly FieldInfo EffectAreaBurnCloseAreaField = AccessTools.Field(typeof(EffectArea), "burnCloseToArea"); private static readonly FieldInfo EffectAreaNoMonsterAreasField = AccessTools.Field(typeof(EffectArea), "s_noMonsterAreas"); private static readonly FieldInfo EffectAreaNoMonsterCloseAreasField = AccessTools.Field(typeof(EffectArea), "s_noMonsterCloseToAreas"); private static readonly FieldInfo EffectAreaBurningAreasField = AccessTools.Field(typeof(EffectArea), "s_BurningAreas"); private static readonly FieldInfo RoutedRpcFunctionsField = AccessTools.Field(typeof(ZRoutedRpc), "m_functions"); private static readonly MethodInfo SetupPlacementGhostMethod = AccessTools.Method(typeof(Player), "SetupPlacementGhost", (Type[])null, (Type[])null); private static readonly MethodInfo UpdatePlacementGhostMethod = AccessTools.Method(typeof(Player), "UpdatePlacementGhost", (Type[])null, (Type[])null); private static readonly MethodInfo UpdateAvailablePiecesListMethod = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null); private static readonly MethodInfo ClearLocalSupportCacheMethod = AccessTools.Method(typeof(WearNTear), "ClearCachedSupport", (Type[])null, (Type[])null); private static readonly MethodInfo UpdateSupportMethod = AccessTools.Method(typeof(WearNTear), "UpdateSupport", (Type[])null, (Type[])null); private static readonly MethodInfo HaveSupportMethod = AccessTools.Method(typeof(WearNTear), "HaveSupport", (Type[])null, (Type[])null); private static readonly MethodInfo PrivateAreaIsEnabledMethod = AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null); private static readonly MethodInfo PrivateAreaIsPermittedMethod = AccessTools.Method(typeof(PrivateArea), "IsPermitted", (Type[])null, (Type[])null); private static readonly FieldInfo[] WearNTearRelocationFields = new FieldInfo[19] { WearNTearCollidersField, WearNTearBoundsField, WearNTearClearCachedSupportField, WearNTearRoofField, WearNTearAshRoofField, WearNTearBiomeField, WearNTearHeightmapField, WearNTearConnectedHeightmapField, WearNTearGroundDistanceField, WearNTearInAshlandsField, WearNTearLavaValueField, WearNTearLavaTimerField, WearNTearAshTimerField, WearNTearRainTimerField, WearNTearUpdateCoverTimerField, WearNTearHaveRoofField, WearNTearHaveAshRoofField, WearNTearShieldChangeIdField, WearNTearPreviousWaterVolumeField }; private static readonly Color GhostColor = new Color(0.22f, 0.66f, 1f, 0.75f); private static readonly Color GhostEmissionColor = new Color(0.05f, 0.42f, 0.9f, 0.9f); private static readonly Color LinkColor = new Color(1f, 0.9f, 0.2f, 0.92f); private static readonly Color RingColor = new Color(1f, 0.95f, 0.35f, 0.9f); private const int RingSegments = 28; private const float LinkWidth = 0.075f; private const float DashLength = 0.35f; private const float MinRingRadius = 0.6f; private const float MaxRingRadius = 8f; private const float RingPadding = 0.25f; private const float TopLinkPadding = 0.15f; private const float DefaultLinkHeight = 1.25f; private const float MinUsefulBoundsSize = 0.05f; private static readonly HashSet<WearNTear> SupportPieces = new HashSet<WearNTear>(); private static readonly Dictionary<long, CancelledLockRequest> CancelledLockRequests = new Dictionary<long, CancelledLockRequest>(); private static readonly List<long> ExpiredRequestTokens = new List<long>(); private static readonly RaycastHit[] FloorHits = (RaycastHit[])(object)new RaycastHit[16]; private static readonly RaycastHit[] DoorInteractHits = (RaycastHit[])(object)new RaycastHit[32]; private static readonly List<Collider> BoundsColliderBuffer = new List<Collider>(); private static readonly List<Renderer> BoundsRendererBuffer = new List<Renderer>(); private static readonly List<MeshFilter> BoundsMeshFilterBuffer = new List<MeshFilter>(); private static readonly List<Transform> BoundsSnapPointBuffer = new List<Transform>(); private static Collider[] _supportColliderBuffer = (Collider[])(object)new Collider[128]; private const string TemporaryPieceTableName = "MoveBuildPieces_TemporaryPieceTable"; private const string MoveRpcName = "MoveBuildPiecesV4_Move"; private const string MoveResultRpcName = "MoveBuildPiecesV4_MoveResult"; private const string ApplyVisualRpcName = "MoveBuildPiecesV4_ApplyVisual"; private const string LockRequestRpcName = "MoveBuildPiecesV4_LockRequest"; private const string LockResponseRpcName = "MoveBuildPiecesV4_LockResponse"; private const string LockReleaseRpcName = "MoveBuildPiecesV4_LockRelease"; private const string ServerProbeRpcName = "MoveBuildPiecesV4_ServerProbe"; private const string ServerProbeResultRpcName = "MoveBuildPiecesV4_ServerProbeResult"; private const string ServerVerifyMoveRpcName = "MoveBuildPiecesV4_ServerVerifyMove"; private const string ServerVerifyMoveResultRpcName = "MoveBuildPiecesV4_ServerVerifyMoveResult"; private const int MoveProtocolVersion = 4; private static readonly int LockOwnerHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LockOwner"); private static readonly int LockPeerHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LockPeer"); private static readonly int LockTokenHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LockToken"); private static readonly int LockUntilHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LockUntil"); private static readonly int LockNameHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LockName"); private static readonly int LastMoveTokenHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LastMoveToken"); private static readonly int LastMovePeerHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LastMovePeer"); private static readonly int LastMovePlayerHash = StringExtensionMethods.GetStableHashCode("MoveBuildPieces.LastMovePlayer"); private const float PendingRequestTimeoutSeconds = 5f; private const float MoveResultTimeoutSeconds = 8f; private const float LockRefreshIntervalSeconds = 2f; private const float ServerVerificationIntervalSeconds = 0.5f; private const float ServerCapabilityLeaseSeconds = 12f; private const float MoveFailureGraceSeconds = 2.5f; private const int MaxMoveRequestAttempts = 3; private const int MaxSupportColliderBufferSize = 2048; private static MoveState _state; private static PendingMoveRequest _pendingRequest; private static GameObject _lineObject; private static LineRenderer _dashLine; private static LineRenderer _originRing; private static LineRenderer _ghostRing; private static Texture2D _dashTexture; private static int _floorMask; private static int _supportLayerMask; private static int _lastDoorInteractFrame = -1; private static Player _suppressAttackPlayer; private static float _suppressAttackUntilTime; private static float _nextCancelledRequestCleanupAt; private static long _requestTokenCounter; private static readonly List<ZRpc> RegisteredPeerRpcs = new List<ZRpc>(); private static readonly Dictionary<ZRpc, double> PeerLastVerifyTimes = new Dictionary<ZRpc, double>(); private static ZRoutedRpc _registeredRoutedRpc; private static bool _routedHandlersActive; private static ZRpc _serverRpc; private static long _serverProbeNonce; private static float _lastServerProbeAt; private static float _lastServerPolicyAckAt; private static bool _serverCapabilityConfirmed; private static bool _serverPolicyEnabled; private static bool _serverPolicyRequireKnownPiece; private static bool _serverPolicyBlockTerrainModifiers; private static bool _serverPolicyBlockDynamicObjects; private static float _serverPolicyMoveLockTimeoutSeconds = 45f; private static bool _runningFinalPlacementValidation; private static Player _placementValidationPlayer; private static Player _skipPlacementGhostPlayer; private static int _skipPlacementGhostFrame = -1; internal static bool NetworkMovesEnabled { get { if ((Object)(object)ZNet.instance != (Object)null) { if (!ZNet.instance.IsServer()) { if (IsServerCapabilityCurrent()) { return _serverPolicyEnabled; } return false; } return MoveBuildPiecesPlugin.IsEnabled; } return false; } } public static void Initialize() { Reset(); if ((Object)(object)ZNet.instance != (Object)null) { OnNetworkStarted(ZNet.instance); } } public static void Reset() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) ClearNetworkSession(); if (_state != null) { Cancel(_state.Player, showMessage: false); } if (_pendingRequest != null) { ReleaseMoveLock(_pendingRequest.NetView, _pendingRequest.PlayerId, _pendingRequest.LockToken, _pendingRequest.ExpectedOwnerPeerId); _pendingRequest = null; } foreach (CancelledLockRequest value in CancelledLockRequests.Values) { ReleaseMoveLock(ResolvePieceNetView(value.ZdoId), value.PlayerId, value.LockToken, value.ExpectedOwnerPeerId); } CancelledLockRequests.Clear(); ExpiredRequestTokens.Clear(); _suppressAttackPlayer = null; _suppressAttackUntilTime = 0f; _nextCancelledRequestCleanupAt = 0f; _lastDoorInteractFrame = -1; _floorMask = 0; _supportLayerMask = 0; _runningFinalPlacementValidation = false; _placementValidationPlayer = null; _skipPlacementGhostPlayer = null; _skipPlacementGhostFrame = -1; DestroyLine(); } public static void OnNetworkStarted(ZNet network) { ClearNetworkSession(); if (!((Object)(object)network == (Object)null)) { RegisterGlobalRoutedRpcs(); _serverCapabilityConfirmed = network.IsServer(); _serverProbeNonce = CreateRequestToken(); List<ZNetPeer> peers = network.GetPeers(); for (int i = 0; i < peers.Count; i++) { RegisterNetworkPeer(peers[i]); } } } public static void OnNetworkStopped(ZNet network) { if ((Object)(object)network == (Object)null || (Object)(object)network == (Object)(object)ZNet.instance) { ClearNetworkSession(); } } public static void PrepareForNetworkShutdown() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (_state != null) { Cancel(_state.Player, showMessage: false); } if (_pendingRequest != null) { CancelPendingRequest(_pendingRequest.Player, showMessage: false, null); } foreach (CancelledLockRequest value in CancelledLockRequests.Values) { try { ReleaseMoveLock(ResolvePieceNetView(value.ZdoId), value.PlayerId, value.LockToken, value.ExpectedOwnerPeerId); } catch { } } } public static void RegisterNetworkPeer(ZNetPeer peer) { ZRpc val = peer?.m_rpc; if (val == null) { return; } for (int i = 0; i < RegisteredPeerRpcs.Count; i++) { if (RegisteredPeerRpcs[i] == val) { return; } } val.Register<int, long>("MoveBuildPiecesV4_ServerProbe", (Action<ZRpc, int, long>)HandleServerProbe); val.Register<ZPackage>("MoveBuildPiecesV4_ServerProbeResult", (Action<ZRpc, ZPackage>)HandleServerProbeResult); val.Register<ZPackage>("MoveBuildPiecesV4_ServerVerifyMove", (Action<ZRpc, ZPackage>)HandleServerVerifyMove); val.Register<ZPackage>("MoveBuildPiecesV4_ServerVerifyMoveResult", (Action<ZRpc, ZPackage>)HandleServerVerifyMoveResult); RegisteredPeerRpcs.Add(val); if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { _serverRpc = val; _serverCapabilityConfirmed = false; _lastServerProbeAt = 0f; _lastServerPolicyAckAt = 0f; } } public static void UnregisterNetworkPeer(ZNetPeer peer) { ZRpc val = peer?.m_rpc; if (val == null) { return; } val.Unregister("MoveBuildPiecesV4_ServerProbe"); val.Unregister("MoveBuildPiecesV4_ServerProbeResult"); val.Unregister("MoveBuildPiecesV4_ServerVerifyMove"); val.Unregister("MoveBuildPiecesV4_ServerVerifyMoveResult"); for (int num = RegisteredPeerRpcs.Count - 1; num >= 0; num--) { if (RegisteredPeerRpcs[num] == val) { RegisteredPeerRpcs.RemoveAt(num); } } PeerLastVerifyTimes.Remove(val); if (_serverRpc == val) { _serverRpc = null; InvalidateServerCapability(null); } } private static void ClearNetworkSession() { UnregisterGlobalRoutedRpcs(); for (int i = 0; i < RegisteredPeerRpcs.Count; i++) { ZRpc val = RegisteredPeerRpcs[i]; if (val != null) { val.Unregister("MoveBuildPiecesV4_ServerProbe"); val.Unregister("MoveBuildPiecesV4_ServerProbeResult"); val.Unregister("MoveBuildPiecesV4_ServerVerifyMove"); val.Unregister("MoveBuildPiecesV4_ServerVerifyMoveResult"); } } RegisteredPeerRpcs.Clear(); PeerLastVerifyTimes.Clear(); _serverRpc = null; _serverProbeNonce = 0L; _lastServerProbeAt = 0f; _lastServerPolicyAckAt = 0f; _serverCapabilityConfirmed = false; _serverPolicyEnabled = false; _serverPolicyRequireKnownPiece = false; _serverPolicyBlockTerrainModifiers = true; _serverPolicyBlockDynamicObjects = true; _serverPolicyMoveLockTimeoutSeconds = 45f; } private static void UpdateServerCapability() { float realtimeSinceStartup = Time.realtimeSinceStartup; if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && _serverCapabilityConfirmed && (_lastServerPolicyAckAt <= 0f || realtimeSinceStartup - _lastServerPolicyAckAt > 12f)) { InvalidateServerCapability("MoveBuildPieces server protocol stopped responding"); } float num = (_serverCapabilityConfirmed ? 5f : 1f); if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && _serverRpc != null && _serverRpc.IsConnected() && !(realtimeSinceStartup - _lastServerProbeAt < num)) { _lastServerProbeAt = realtimeSinceStartup; _serverRpc.Invoke("MoveBuildPiecesV4_ServerProbe", new object[2] { 4, _serverProbeNonce }); } } private static void InvalidateServerCapability(string message) { bool num = _state != null || _pendingRequest != null; _serverCapabilityConfirmed = false; _serverPolicyEnabled = false; _lastServerPolicyAckAt = 0f; _lastServerProbeAt = 0f; _serverProbeNonce = CreateRequestToken(); if (_state != null) { Cancel(_state.Player, showMessage: false); } if (_pendingRequest != null) { CancelPendingRequest(_pendingRequest.Player, showMessage: false, null); } if (num && !string.IsNullOrEmpty(message)) { Message(Player.m_localPlayer, message); } } private static void HandleServerProbe(ZRpc rpc, int protocolVersion, long nonce) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && protocolVersion == 4 && nonce != 0L && TryGetReadyPeer(rpc, out var _)) { ZPackage val = new ZPackage(); val.Write(4); val.Write(nonce); val.Write(MoveBuildPiecesPlugin.IsEnabled); val.Write(MoveBuildPiecesPlugin.RequireKnownPiece); val.Write(MoveBuildPiecesPlugin.BlockTerrainModifiers); val.Write(MoveBuildPiecesPlugin.BlockDynamicObjects); val.Write(MoveBuildPiecesPlugin.MoveLockTimeoutSeconds); rpc.Invoke("MoveBuildPiecesV4_ServerProbeResult", new object[1] { val }); } } private static void HandleServerProbeResult(ZRpc rpc, ZPackage package) { if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || rpc != _serverRpc || package == null) { return; } try { int num = package.ReadInt(); long num2 = package.ReadLong(); bool flag = package.ReadBool(); bool serverPolicyRequireKnownPiece = package.ReadBool(); bool serverPolicyBlockTerrainModifiers = package.ReadBool(); bool serverPolicyBlockDynamicObjects = package.ReadBool(); float num3 = package.ReadSingle(); if (num != 4 || num2 != _serverProbeNonce || float.IsNaN(num3) || float.IsInfinity(num3)) { return; } bool flag2 = _state != null || _pendingRequest != null; _serverPolicyEnabled = flag; _serverPolicyRequireKnownPiece = serverPolicyRequireKnownPiece; _serverPolicyBlockTerrainModifiers = serverPolicyBlockTerrainModifiers; _serverPolicyBlockDynamicObjects = serverPolicyBlockDynamicObjects; _serverPolicyMoveLockTimeoutSeconds = Mathf.Clamp(num3, 5f, 300f); _serverCapabilityConfirmed = true; _lastServerPolicyAckAt = Time.realtimeSinceStartup; if (!flag && flag2) { if (_state != null) { Cancel(_state.Player, showMessage: false); } if (_pendingRequest != null) { CancelPendingRequest(_pendingRequest.Player, showMessage: false, null); } Message(Player.m_localPlayer, "MoveBuildPieces is disabled by the server policy"); } } catch { } } private static void HandleServerVerifyMove(ZRpc rpc, ZPackage package) { //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_012d: 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_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || package == null || !TryGetReadyPeer(rpc, out var peer)) { return; } double networkTimeSeconds = GetNetworkTimeSeconds(); if (PeerLastVerifyTimes.TryGetValue(rpc, out var value) && networkTimeSeconds - value < 0.1) { return; } PeerLastVerifyTimes[rpc] = networkTimeSeconds; ZDOID val = ZDOID.None; long num = 0L; Vector3 val2 = Vector3.zero; Quaternion val3 = Quaternion.identity; bool flag = false; try { val = package.ReadZDOID(); long num2 = package.ReadLong(); num = package.ReadLong(); val2 = package.ReadVector3(); val3 = package.ReadQuaternion(); object obj; if (((ZDOID)(ref peer.m_characterID)).IsNone()) { obj = null; } else { ZDOMan instance = ZDOMan.instance; obj = ((instance != null) ? instance.GetZDO(peer.m_characterID) : null); } ZDO val4 = (ZDO)obj; ZDOMan instance2 = ZDOMan.instance; ZDO zdo = ((instance2 != null) ? instance2.GetZDO(val) : null); flag = MoveBuildPiecesPlugin.IsEnabled && val4 != null && val4.GetOwner() == peer.m_uid && val4.GetLong(ZDOVars.s_playerID, 0L) == num2 && IsCommittedMove(zdo, peer.m_uid, num2, num, val2, val3); } catch { flag = false; } ZPackage val5 = new ZPackage(); val5.Write(val); val5.Write(num); val5.Write(val2); val5.Write(val3); val5.Write(flag); rpc.Invoke("MoveBuildPiecesV4_ServerVerifyMoveResult", new object[1] { val5 }); } private static void HandleServerVerifyMoveResult(ZRpc rpc, ZPackage package) { //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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || rpc != _serverRpc || package == null) { return; } try { ZDOID val = package.ReadZDOID(); long num = package.ReadLong(); Vector3 val2 = package.ReadVector3(); Quaternion val3 = package.ReadQuaternion(); if (package.ReadBool() && _serverCapabilityConfirmed && NetworkMovesEnabled && _state != null && _state.WaitingForMoveResult && _state.LockToken == num && !((Object)(object)_state.NetView == (Object)null) && _state.NetView.IsValid() && !(_state.NetView.GetZDO().m_uid != val) && !(Vector3.Distance(_state.PendingTargetPosition, val2) > 0.001f) && !(Quaternion.Angle(_state.PendingTargetRotation, val3) > 0.01f)) { MoveState state = _state; ReleaseMoveLock(state.NetView, state.LockPlayerId, state.LockToken, state.LockOwnerPeerId); ApplyVisualMoveLocally(state.NetView, val2, val3); FinishSuccessfulMove(state.Player, state.Piece, val2, val3); } } catch { } } private static bool TryGetReadyPeer(ZRpc rpc, out ZNetPeer peer) { peer = null; if (rpc == null || (Object)(object)ZNet.instance == (Object)null) { return false; } List<ZNetPeer> peers = ZNet.instance.GetPeers(); for (int i = 0; i < peers.Count; i++) { ZNetPeer val = peers[i]; if (val != null && val.m_rpc == rpc && val.IsReady() && val.m_uid != 0L && !((ZDOID)(ref val.m_characterID)).IsNone()) { peer = val; return true; } } return false; } private static void RegisterGlobalRoutedRpcs() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null && (_registeredRoutedRpc != instance || !_routedHandlersActive)) { UnregisterGlobalRoutedRpcs(); instance.Register<ZDOID, long, long, Vector3, Quaternion>("MoveBuildPiecesV4_Move", (Method<ZDOID, long, long, Vector3, Quaternion>)HandleRoutedMoveRpc); instance.Register<ZDOID, bool, string, long>("MoveBuildPiecesV4_MoveResult", (Method<ZDOID, bool, string, long>)HandleRoutedMoveResultRpc); instance.Register<ZDOID, long, Vector3, Quaternion>("MoveBuildPiecesV4_ApplyVisual", (Method<ZDOID, long, Vector3, Quaternion>)HandleRoutedVisualMoveRpc); instance.Register<ZDOID, long, long, bool>("MoveBuildPiecesV4_LockRequest", (Method<ZDOID, long, long, bool>)HandleRoutedLockRequestRpc); instance.Register<ZDOID, bool, string, long>("MoveBuildPiecesV4_LockResponse", (Method<ZDOID, bool, string, long>)HandleRoutedLockResponseRpc); instance.Register<ZDOID, long, long>("MoveBuildPiecesV4_LockRelease", (Action<long, ZDOID, long, long>)HandleRoutedLockReleaseRpc); _registeredRoutedRpc = instance; _routedHandlersActive = true; } } private static void UnregisterGlobalRoutedRpcs() { if (_registeredRoutedRpc != null && RoutedRpcFunctionsField?.GetValue(_registeredRoutedRpc) is IDictionary dictionary) { dictionary.Remove(StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_Move")); dictionary.Remove(StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_MoveResult")); dictionary.Remove(StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_ApplyVisual")); dictionary.Remove(StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_LockRequest")); dictionary.Remove(StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_LockResponse")); dictionary.Remove(StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_LockRelease")); } _routedHandlersActive = false; _registeredRoutedRpc = null; } private static bool TryResolvePieceNetView(ZDOID zdoId, out ZNetView netView) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) netView = (_routedHandlersActive ? ResolvePieceNetView(zdoId) : null); return (Object)(object)netView != (Object)null; } private static ZNetView ResolvePieceNetView(ZDOID zdoId) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (((ZDOID)(ref zdoId)).IsNone() || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return null; } ZDO zDO = ZDOMan.instance.GetZDO(zdoId); ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); if (!((Object)(object)val != (Object)null) || !val.IsValid() || val.GetZDO() != zDO || !((Object)(object)((Component)val).GetComponent<Piece>() != (Object)null)) { return null; } return val; } private static void HandleRoutedMoveRpc(long sender, ZDOID zdoId, long playerId, long lockToken, Vector3 position, Quaternion rotation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (TryResolvePieceNetView(zdoId, out var netView)) { ApplyMoveRpc(netView, sender, playerId, lockToken, position, rotation); } } private static void HandleRoutedMoveResultRpc(long sender, ZDOID zdoId, bool success, string message, long lockToken) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (TryResolvePieceNetView(zdoId, out var netView)) { ApplyMoveResultRpc(netView, sender, success, message, lockToken); } } private static void HandleRoutedVisualMoveRpc(long sender, ZDOID zdoId, long lockToken, Vector3 position, Quaternion rotation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (TryResolvePieceNetView(zdoId, out var netView)) { ApplyVisualMoveRpc(netView, sender, lockToken, position, rotation); } } private static void HandleRoutedLockRequestRpc(long sender, ZDOID zdoId, long playerId, long lockToken, bool refreshOnly) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (TryResolvePieceNetView(zdoId, out var netView)) { ApplyLockRequestRpc(netView, sender, playerId, lockToken, refreshOnly); } } private static void HandleRoutedLockResponseRpc(long sender, ZDOID zdoId, bool granted, string message, long lockToken) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (TryResolvePieceNetView(zdoId, out var netView)) { ApplyLockResponseRpc(netView, sender, granted, message, lockToken); } } private static void HandleRoutedLockReleaseRpc(long sender, ZDOID zdoId, long playerId, long lockToken) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (TryResolvePieceNetView(zdoId, out var netView)) { ApplyLockReleaseRpc(netView, sender, playerId, lockToken); } } private static bool InvokePieceRpc(ZNetView netView, long targetPeerId, string methodName, params object[] arguments) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)netView == (Object)null || !netView.IsValid() || string.IsNullOrEmpty(methodName) || ZRoutedRpc.instance == null) { return false; } object[] array = new object[arguments.Length + 1]; array[0] = netView.GetZDO().m_uid; Array.Copy(arguments, 0, array, 1, arguments.Length); ZRoutedRpc.instance.InvokeRoutedRPC(targetPeerId, methodName, array); return true; } public static bool ValidateRoutedRpcSender(ZRoutedRpc routedRpc, ZRpc rpc, ZPackage package) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (routedRpc == null || rpc == null || package == null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return true; } int pos = package.GetPos(); try { package.ReadLong(); long num = package.ReadLong(); package.ReadLong(); package.ReadZDOID(); if (!IsMoveProtocolMethod(package.ReadInt())) { return true; } List<ZNetPeer> peers = ZNet.instance.GetPeers(); for (int i = 0; i < peers.Count; i++) { ZNetPeer val = peers[i]; if (val != null && val.m_rpc == rpc) { return num != 0L && num == val.m_uid; } } return false; } catch { return false; } finally { package.SetPos(pos); } } private static bool IsMoveProtocolMethod(int methodHash) { if (methodHash != StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_Move") && methodHash != StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_MoveResult") && methodHash != StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_ApplyVisual") && methodHash != StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_LockRequest") && methodHash != StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_LockResponse")) { return methodHash == StringExtensionMethods.GetStableHashCode("MoveBuildPiecesV4_LockRelease"); } return true; } public static void Update(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } CleanupCancelledLockRequests(); UpdateServerCapability(); if (!MoveBuildPiecesPlugin.IsEnabled) { if (_state != null) { Cancel(player, showMessage: false); } if (_pendingRequest != null) { CancelPendingRequest(player, showMessage: false, null); } return; } if (_pendingRequest != null && (Object)(object)_pendingRequest.Player == (Object)(object)player && (((Character)player).IsDead() || ((Character)player).IsTeleporting())) { CancelPendingRequest(player, showMessage: false, null); } else if (_pendingRequest != null && (Object)(object)_pendingRequest.Player == (Object)(object)player && Time.realtimeSinceStartup - _pendingRequest.StartedAt > 5f) { CancelPendingRequest(player, showMessage: false, "Move lock request timed out or the object owner has an incompatible mod version"); } if (_pendingRequest != null && (!CanBeginPendingMove(_pendingRequest) || IsUiBlockingInput())) { CancelPendingRequest(player, showMessage: false, null); } if (_pendingRequest != null) { RetryPendingLockAfterOwnerChange(_pendingRequest); } if (ShouldCancelForUiOrState(player)) { Cancel(player, showMessage: false); } else { if (IsUiBlockingInput()) { return; } if ((_state == null || !TryInteractDoorInMoveMode(player)) && ShouldHandleMoveHotkey(player, out var context, out var activationMode)) { ToggleMove(player, context, activationMode); } if (_state == null) { return; } RefreshMoveLock(_state); if (_state == null) { return; } if (_state.WaitingForMoveResult) { RequestServerMoveVerification(_state); } if ((!_state.WaitingForMoveResult || !TryResolveCommittedMove(_state)) && (!_state.WaitingForMoveResult || !TryRetryMoveAfterOwnerChange(_state))) { if (_state.WaitingForMoveResult && _state.MoveFailureReceivedAt > 0f && Time.realtimeSinceStartup - _state.MoveFailureReceivedAt >= 2.5f) { Message(player, string.IsNullOrEmpty(_state.MoveFailureMessage) ? "$msg_invalidplacement" : _state.MoveFailureMessage); _state.WaitingForMoveResult = false; _state.MoveFailureReceivedAt = 0f; _state.MoveFailureMessage = null; _state.MoveRequestOwnerPeerId = 0L; _state.MoveRequestStartedAt = 0f; _state.FirstMoveRequestStartedAt = 0f; _state.MoveRequestAttempts = 0; _state.LastLockRefreshTime = 0f; } else if (_state.WaitingForMoveResult && Time.realtimeSinceStartup - _state.FirstMoveRequestStartedAt > 8f) { Message(player, "Move confirmation timed out; verify the object's position"); Cancel(player, showMessage: false); } else if (!_state.WaitingForMoveResult) { UpdateActiveMovePlacement(player); } } } } public static void UpdateVisuals(Player player) { if (MoveBuildPiecesPlugin.IsEnabled && !((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && _state != null) { UpdateLineAndGhost(player); } } public static void SuppressAttackControls(Player player, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold) { if (ShouldSuppressAttackControls(player, attack, attackHold, secondaryAttack, secondaryAttackHold)) { attack = false; attackHold = false; secondaryAttack = false; secondaryAttackHold = false; ClearQueuedAttackInput(player); } } private static bool ShouldSuppressAttackControls(Player player, bool attack, bool attackHold, bool secondaryAttack, bool secondaryAttackHold) { if (!MoveBuildPiecesPlugin.IsEnabled || (Object)(object)player == (Object)null) { return false; } if (_state != null && (Object)(object)player == (Object)(object)_state.Player) { return true; } if ((Object)(object)_suppressAttackPlayer == (Object)(object)player) { if ((attack || attackHold || secondaryAttack || secondaryAttackHold) && Time.realtimeSinceStartup <= _suppressAttackUntilTime) { return true; } _suppressAttackPlayer = null; _suppressAttackUntilTime = 0f; } return false; } public static bool ShouldHandlePlacement(Player player) { if (_state != null && (Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)_state.Player; } return false; } public static bool ShouldBlockBuildAction(Player player) { if (_state != null && (Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)_state.Player; } return false; } public static bool ShouldBypassRequirements(Player player, Piece piece, RequirementMode mode) { //IL_0014: 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_0019: Invalid comparison between Unknown and I4 if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null) { return false; } if ((int)mode != 0 && (int)mode != 2) { return false; } string prefabName = Utils.GetPrefabName(((Component)piece).gameObject); if (_state != null && (Object)(object)player == (Object)(object)_state.Player) { return prefabName == _state.PrefabName; } return false; } public static bool ShouldSkipVanillaUpdatePlacement(Player player) { if (_state != null && (Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)_state.Player; } return false; } public static void NotifyDoorInteracted(Player player) { if (_state != null && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)_state.Player) { _lastDoorInteractFrame = Time.frameCount; } } public static void CancelForTeleport(Player player) { if (_state != null && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)_state.Player) { Cancel(player, showMessage: true); } if (_pendingRequest != null && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)_pendingRequest.Player) { CancelPendingRequest(player, showMessage: false, null); } } public static void CancelForDeath(Player player) { if (_state != null && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)_state.Player) { Cancel(player, showMessage: true); } if (_pendingRequest != null && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)_pendingRequest.Player) { CancelPendingRequest(player, showMessage: false, null); } } public static void CancelForPlayerDestroyed(Player player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer)) { if (_state != null && (Object)(object)player == (Object)(object)_state.Player) { Cancel(player, showMessage: false); } if (_pendingRequest != null && (Object)(object)player == (Object)(object)_pendingRequest.Player) { CancelPendingRequest(player, showMessage: false, null); } } } public static void TryFinishMove(Player player) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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) if (_state == null || (Object)(object)player != (Object)(object)_state.Player || _state.WaitingForMoveResult) { return; } if (!IsMoveSelectionIntact(_state, player)) { Message(player, "Move cancelled because the selected build piece changed"); Cancel(player, showMessage: false); return; } if (!RunFinalPlacementValidation(player)) { Message(player, "$msg_invalidplacement"); return; } GameObject placementGhost = GetPlacementGhost(player); if ((Object)(object)placementGhost == (Object)null) { Message(player, "$msg_invalidplacement"); Cancel(player, showMessage: false); return; } PlacementStatus placementStatus = GetPlacementStatus(player); if ((int)placementStatus != 0) { Message(player, GetPlacementFailureMessage(placementStatus)); return; } Vector3 position = placementGhost.transform.position; Quaternion rotation = placementGhost.transform.rotation; if (!IsInsideOriginalBuildArea(_state, position)) { Message(player, "$msg_nobuildzone"); } else if (ValidateMoveTarget(player, _state.Piece)) { Piece piece = _state.Piece; _state.PendingTargetPosition = position; _state.PendingTargetRotation = rotation; if (!RequestMovePiece(_state, position, rotation, out var completedImmediately)) { Message(player, "$msg_invalidplacement"); } else if (!completedImmediately) { Message(player, "Moving " + Localization.instance.Localize(piece.m_name)); } else { FinishSuccessfulMove(player, piece, position, rotation); } } } private static bool RunFinalPlacementValidation(Player player) { if ((Object)(object)player == (Object)null || UpdatePlacementGhostMethod == null) { return false; } _runningFinalPlacementValidation = true; _placementValidationPlayer = player; try { UpdatePlacementGhostMethod.Invoke(player, new object[1] { true }); return true; } catch (Exception ex) { Debug.LogWarning((object)("[MoveBuildPieces] Final placement validation failed: " + ex.GetBaseException().Message)); return false; } finally { _runningFinalPlacementValidation = false; _placementValidationPlayer = null; _skipPlacementGhostPlayer = player; _skipPlacementGhostFrame = Time.frameCount; } } public static bool ShouldRunPlacementGhostUpdate(Player player) { if (_runningFinalPlacementValidation && (Object)(object)player == (Object)(object)_placementValidationPlayer) { return true; } if ((Object)(object)player == (Object)(object)_skipPlacementGhostPlayer && Time.frameCount == _skipPlacementGhostFrame) { return false; } if (Time.frameCount != _skipPlacementGhostFrame) { _skipPlacementGhostPlayer = null; _skipPlacementGhostFrame = -1; } return true; } public static Collider[] FilterPlacementOverlap(Collider[] overlaps) { Piece val = _state?.Piece; if ((Object)(object)val == (Object)null || overlaps == null || overlaps.Length == 0) { return overlaps; } int num = 0; foreach (Collider val2 in overlaps) { if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).GetComponentInParent<Piece>() == (Object)(object)val) { num++; } } if (num == 0) { return overlaps; } Collider[] array = (Collider[])(object)new Collider[overlaps.Length - num]; int num2 = 0; foreach (Collider val3 in overlaps) { if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).GetComponentInParent<Piece>() != (Object)(object)val) { array[num2++] = val3; } } return array; } public static bool TryTestGhostClippingIgnoringMovedPiece(Player player, GameObject ghost, float maxPenetration, out bool result) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) result = false; Piece val = (((Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)_state?.Player) ? _state.Piece : null); if ((Object)(object)val == (Object)null) { return false; } if ((Object)(object)ghost == (Object)null || !(PlaceRayMaskField?.GetValue(player) is int num)) { result = true; return true; } Collider[] componentsInChildren = ghost.GetComponentsInChildren<Collider>(); Collider[] array = Physics.OverlapSphere(ghost.transform.position, 10f, num); Vector3 val4 = default(Vector3); float num2 = default(float); foreach (Collider val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } foreach (Collider val3 in array) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).GetComponentInParent<Piece>() == (Object)(object)val) && Physics.ComputePenetration(val2, ((Component)val2).transform.position, ((Component)val2).transform.rotation, val3, ((Component)val3).transform.position, ((Component)val3).transform.rotation, ref val4, ref num2) && num2 > maxPenetration) { result = true; return true; } } } return true; } public static bool TryEvaluatePieceOverlapIgnoringMovedPiece(Player player, Vector3 position, Quaternion rotation, string pieceName, List<Piece> pieces, bool allowRotatedOverlap, out bool result) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) result = false; Piece val = (((Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)_state?.Player) ? _state.Piece : null); if ((Object)(object)val == (Object)null || pieces == null) { return false; } for (int i = 0; i < pieces.Count; i++) { Piece val2 = pieces[i]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val) && Vector3.Distance(position, ((Component)val2).transform.position) < 0.05f && (!allowRotatedOverlap || Quaternion.Angle(((Component)val2).transform.rotation, rotation) <= 10f) && Utils.CustomStartsWith(((Object)((Component)val2).gameObject).name, pieceName)) { result = true; break; } } return true; } public static bool TryEvaluateExtensionRangeIgnoringMovedPiece(StationExtension extension, float radius, out bool result) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) result = false; Piece val = _state?.Piece; if ((Object)(object)val == (Object)null || (Object)(object)extension == (Object)null || !(StationExtensionsField?.GetValue(null) is List<StationExtension> list)) { return false; } for (int i = 0; i < list.Count; i++) { StationExtension val2 = list[i]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)extension) && !((Object)(object)((Component)val2).GetComponentInParent<Piece>() == (Object)(object)val) && Vector3.Distance(((Component)val2).transform.position, ((Component)extension).transform.position) < radius) { result = true; break; } } return true; } private static void FinishSuccessfulMove(Player player, Piece movedPiece, Vector3 targetPosition, Quaternion targetRotation) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)movedPiece == (Object)null) { Message(player, "$msg_invalidplacement"); Cancel(player, showMessage: false); return; } MoveState state = _state; try { UpdateMovedBedSpawnPoint(state, targetPosition, targetRotation); SuppressAttackUntilRelease(player); Message(player, "Moved " + Localization.instance.Localize(movedPiece.m_name)); movedPiece.m_placeEffect.Create(targetPosition, targetRotation, ((Component)movedPiece).transform, 1f, -1); } catch (Exception ex) { Debug.LogWarning((object)("[MoveBuildPieces] Move completion effect failed: " + ex.GetBaseException().Message)); } finally { Cancel(player, showMessage: false, releaseLock: false); } } private static void UpdateMovedBedSpawnPoint(MoveState state, Vector3 targetPosition, Quaternion targetRotation) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if (state != null && state.UpdateBedSpawnPoint && !((Object)(object)Game.instance == (Object)null)) { PlayerProfile playerProfile = Game.instance.GetPlayerProfile(); if (playerProfile != null && playerProfile.HaveCustomSpawnPoint() && !(Vector3.Distance(playerProfile.GetCustomSpawnPoint(), state.BedOriginalProfileSpawnPoint) > 0.1f)) { Vector3 val = (((Object)(object)state.Piece != (Object)null) ? ((Component)state.Piece).transform.lossyScale : Vector3.one); Vector3 customSpawnPoint = targetPosition + targetRotation * Vector3.Scale(state.BedSpawnLocalPoint, val); playerProfile.SetCustomSpawnPoint(customSpawnPoint); } } } private static void SuppressAttackUntilRelease(Player player) { if (!((Object)(object)player == (Object)null)) { _suppressAttackPlayer = player; _suppressAttackUntilTime = Time.realtimeSinceStartup + 5f; ClearQueuedAttackInput(player); } } private static void ClearQueuedAttackInput(Player player) { if (!((Object)(object)player == (Object)null)) { AttackField?.SetValue(player, false); AttackHoldField?.SetValue(player, false); SecondaryAttackField?.SetValue(player, false); SecondaryAttackHoldField?.SetValue(player, false); QueuedAttackTimerField?.SetValue(player, 0f); QueuedSecondAttackTimerField?.SetValue(player, 0f); AttackDrawTimeField?.SetValue(player, 0f); } } private static bool ShouldHandleMoveHotkey(Player player, out MoveContext context, out MoveActivationMode activationMode) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) context = MoveContext.Build; activationMode = MoveBuildPiecesPlugin.ActiveMode; KeyboardShortcut val; if (_state != null && (Object)(object)player == (Object)(object)_state.Player) { context = _state.Context; activationMode = _state.ActivationMode; val = GetMoveHotkey(activationMode, context); return ((KeyboardShortcut)(ref val)).IsDown(); } if (_pendingRequest != null && (Object)(object)player == (Object)(object)_pendingRequest.Player) { context = _pendingRequest.Context; activationMode = _pendingRequest.ActivationMode; val = GetMoveHotkey(activationMode, context); return ((KeyboardShortcut)(ref val)).IsDown(); } bool flag = ((Character)player).InPlaceMode(); if (activationMode == MoveActivationMode.BuildMenu && flag) { val = MoveBuildPiecesPlugin.BuildModeMoveHotkey; if (((KeyboardShortcut)(ref val)).IsDown()) { context = MoveContext.Build; return true; } } if (activationMode == MoveActivationMode.World && !flag && !HasEquippedBuildTool(player)) { val = MoveBuildPiecesPlugin.WorldModeMoveHotkey; if (((KeyboardShortcut)(ref val)).IsDown()) { context = MoveContext.World; return true; } } if (activationMode == MoveActivationMode.Mixed) { val = MoveBuildPiecesPlugin.MixedModeMoveHotkey; if (((KeyboardShortcut)(ref val)).IsDown()) { if (flag) { context = MoveContext.Build; return true; } if (!HasEquippedBuildTool(player)) { context = MoveContext.World; return true; } } } return false; } private static KeyboardShortcut GetMoveHotkey(MoveActivationMode activationMode, MoveContext context) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (activationMode == MoveActivationMode.Mixed) { return MoveBuildPiecesPlugin.MixedModeMoveHotkey; } if (context != MoveContext.World) { return MoveBuildPiecesPlugin.BuildModeMoveHotkey; } return MoveBuildPiecesPlugin.WorldModeMoveHotkey; } private static void ToggleMove(Player player, MoveContext context, MoveActivationMode activationMode) { if (_state != null) { Cancel(player, showMessage: true); } else if (_pendingRequest != null) { CancelPendingRequest(player, showMessage: true, null); } else { StartMove(player, context, activationMode); } } private static bool TryInteractDoorInMoveMode(Player player) { if ((Object)(object)player == (Object)null || _lastDoorInteractFrame == Time.frameCount || Hud.InRadial() || (!ZInput.GetButtonDown("Use") && !ZInput.GetButtonDown("JoyUse"))) { return false; } Door val = FindDoorForMoveModeInteraction(player); if ((Object)(object)val == (Object)null) { return false; } bool flag = ZInput.GetButton("AltPlace") || ZInput.GetButton("JoyAltPlace") || ZInput.GetButton("JoyAltKeys"); if (!val.Interact((Humanoid)(object)player, false, flag)) { return false; } _lastDoorInteractFrame = Time.frameCount; return true; } private static Door FindDoorForMoveModeInteraction(Player player) { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)GameCamera.instance == (Object)null) { return null; } int num = ((InteractMaskField?.GetValue(player) is int num2) ? num2 : LayerMask.GetMask(new string[5] { "piece", "piece_nonsolid", "Default", "static_solid", "Default_small" })); object? obj = EyeField?.GetValue(player); Transform val = (Transform)((obj is Transform) ? obj : null); float num3 = ((MaxInteractDistanceField?.GetValue(player) is float num4) ? num4 : 5f); Transform transform = ((Component)GameCamera.instance).transform; GameObject placementGhost = GetPlacementGhost(player); int num5 = Physics.RaycastNonAlloc(transform.position, transform.forward, DoorInteractHits, 50f, num); Array.Sort(DoorInteractHits, 0, num5, RaycastHitDistanceComparer.Instance); for (int i = 0; i < num5; i++) { RaycastHit val2 = DoorInteractHits[i]; Collider collider = ((RaycastHit)(ref val2)).collider; if (!((Object)(object)collider == (Object)null) && !IsPlayerCollider(player, collider) && (!((Object)(object)placementGhost != (Object)null) || !((Component)collider).transform.IsChildOf(placementGhost.transform))) { if (Vector3.Distance(((Object)(object)val != (Object)null) ? val.position : ((Component)player).transform.position, ((RaycastHit)(ref val2)).point) >= num3) { return null; } Door componentInParent = ((Component)collider).GetComponentInParent<Door>(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } return null; } } return null; } private static bool IsPlayerCollider(Player player, Collider collider) { if ((Object)(object)player == (Object)null || (Object)(object)collider == (Object)null) { return false; } if ((Object)(object)collider.attachedRigidbody != (Object)null) { return (Object)(object)((Component)collider.attachedRigidbody).gameObject == (Object)(object)((Component)player).gameObject; } return false; } private static bool TryAcquireOrRequestMoveLock(Player player, Piece piece, MoveContext context, MoveActivationMode activationMode, ZNetView netView, long lockToken) { long num = (((Object)(object)player != (Object)null) ? player.GetPlayerID() : 0); long num2 = (((Object)(object)player != (Object)null) ? ((Character)player).GetOwner() : 0); if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null || (Object)(object)netView == (Object)null || !netView.IsValid() || num == 0L || num2 == 0L || lockToken == 0L) { Message(player, "$msg_invalidplacement"); return false; } if (!HasVerifiedServerProtocol()) { Message(player, "Matching MoveBuildPieces 1.1.1 is required on the server"); return false; } if (!NetworkMovesEnabled) { Message(player, "MoveBuildPieces is disabled by the server policy"); return false; } if (netView.IsOwner()) { if (!TryAcquireMoveLock(netView, num2, player, lockToken, refreshOnly: false, out var message)) { Message(player, message); return false; } return true; } _pendingRequest = new PendingMoveRequest { Player = player, Piece = piece, NetView = netView, Context = context, ActivationMode = activationMode, PlayerId = num, LockToken = lockToken, ExpectedOwnerPeerId = netView.GetZDO().GetOwner(), StartedAt = Time.realtimeSinceStartup, LastRequestAt = Time.realtimeSinceStartup }; if (_pendingRequest.ExpectedOwnerPeerId == 0L) { _pendingRequest = null; Message(player, "The object has no network owner yet"); return false; } InvokePieceRpc(netView, _pendingRequest.ExpectedOwnerPeerId, "MoveBuildPiecesV4_LockRequest", num, lockToken, false); Message(player, "Requesting move lock"); return false; } private static void RetryPendingLockAfterOwnerChange(PendingMoveRequest request) { if (!((Object)(object)request?.NetView == (Object)null) && request.NetView.IsValid() && !(Time.realtimeSinceStartup - request.LastRequestAt < 1.25f)) { ZDO zDO = request.NetView.GetZDO(); long num = ((zDO != null) ? zDO.GetOwner() : 0); if (num != 0L && num != request.ExpectedOwnerPeerId) { long expectedOwnerPeerId = request.ExpectedOwnerPeerId; ReleaseMoveLock(request.NetView, request.PlayerId, request.LockToken, expectedOwnerPeerId); request.ExpectedOwnerPeerId = num; request.LastRequestAt = Time.realtimeSinceStartup; InvokePieceRpc(request.NetView, num, "MoveBuildPiecesV4_LockRequest", request.PlayerId, request.LockToken, false); } } } private static bool TryAcquireMoveLock(ZNetView netView, long senderPeerId, Player player, long lockToken, bool refreshOnly, out string message) { //IL_01d2: Unknown result type (might be due to invalid IL or missing references) message = ""; ZDO val = (((Object)(object)netView != (Object)null && netView.IsValid()) ? netView.GetZDO() : null); long num = (((Object)(object)player != (Object)null) ? player.GetPlayerID() : 0); if (!NetworkMovesEnabled || !HasVerifiedServerProtocol() || val == null || !netView.IsOwner() || senderPeerId == 0L || num == 0L || lockToken == 0L || ((Character)player).GetOwner() != senderPeerId) { message = "$msg_invalidplacement"; return false; } long num2 = val.GetLong(LockOwnerHash, 0L); long num3 = val.GetLong(LockPeerHash, 0L); long num4 = val.GetLong(LockTokenHash, 0L); double num5 = (double)val.GetLong(LockUntilHash, 0L) / 1000.0; double networkTimeSeconds = GetNetworkTimeSeconds(); bool flag = num2 == num && num3 == senderPeerId && num4 == lockToken && num5 > networkTimeSeconds; if (refreshOnly && !flag) { message = "Move lock was lost"; return false; } if (num2 != 0L && num5 > networkTimeSeconds && (num2 != num || num3 != senderPeerId || num4 != lockToken)) { string text = val.GetString(LockNameHash, "another player"); message = "Already being moved by " + text; return false; } if (!flag && !CanGrantMoveLock(player, ((Component)netView).GetComponent<Piece>(), out message)) { return false; } float moveLockTimeoutSeconds = MoveBuildPiecesPlugin.MoveLockTimeoutSeconds; double num6 = num5 - networkTimeSeconds; if (flag && num6 > (double)moveLockTimeoutSeconds - 0.5 && num6 <= (double)moveLockTimeoutSeconds + 0.5) { return true; } val.Set(LockOwnerHash, num); val.Set(LockPeerHash, senderPeerId); val.Set(LockTokenHash, lockToken); val.Set(LockUntilHash, SecondsToMillis(networkTimeSeconds + (double)moveLockTimeoutSeconds)); string playerName = player.GetPlayerName(); val.Set(LockNameHash, string.IsNullOrWhiteSpace(playerName) ? "another player" : playerName); ZDOMan instance = ZDOMan.instance; if (instance != null) { instance.ForceSendZDO(val.m_uid); } return true; } private static void RefreshMoveLock(MoveState state) { if ((Object)(object)state?.NetView == (Object)null || !state.NetView.IsValid() || state.NetView.GetZDO() == null || Time.realtimeSinceStartup - state.LastLockRefreshTime < 2f) { return; } state.LastLockRefreshTime = Time.realtimeSinceStartup; if (state.NetView.IsOwner()) { if (!TryAcquireMoveLock(state.NetView, state.LockPeerId, state.Player, state.LockToken, refreshOnly: true, out var _)) { Message(state.Player, "Move lock was lost"); Cancel(state.Player, showMessage: false); } } else if (state.NetView.HasOwner()) { long owner = state.NetView.GetZDO().GetOwner(); if (owner == 0L) { Message(state.Player, "Move lock was lost"); Cancel(state.Player, showMessage: false); return; } state.LockRequestOwnerPeerId = owner; state.LockOwnerPeerId = owner; InvokePieceRpc(state.NetView, owner, "MoveBuildPiecesV4_LockRequest", state.LockPlayerId, state.LockToken, true); } } private static void ReleaseMoveLock(ZNetView netView, long playerId, long lockToken, long expectedOwnerPeerId = 0L) { if ((Object)(object)netView == (Object)null || !netView.IsValid() || playerId == 0L || lockToken == 0L) { return; } if (netView.IsOwner()) { ClearMoveLock(netView, ZDOMan.GetSessionID(), playerId, lockToken); return; } long num = (netView.HasOwner() ? netView.GetZDO().GetOwner() : 0); if (expectedOwnerPeerId != 0L) { InvokePieceRpc(netView, expectedOwnerPeerId, "MoveBuildPiecesV4_LockRelease", playerId, lockToken); } if (num != 0L && num != expectedOwnerPeerId) { InvokePieceRpc(netView, num, "MoveBuildPiecesV4_LockRelease", playerId, lockToken); } } private static bool ClearMoveLock(ZNetView netView, long senderPeerId, long playerId, long lockToken) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) ZDO val = (((Object)(object)netView != (Object)null && netView.IsValid()) ? netView.GetZDO() : null); if (val == null || !netView.IsOwner() || senderPeerId == 0L || playerId == 0L || lockToken == 0L || val.GetLong(LockOwnerHash, 0L) != playerId || val.GetLong(LockPeerHash, 0L) != senderPeerId || val.GetLong(LockTokenHash, 0L) != lockToken) { return false; } val.Set(LockOwnerHash, 0L); val.Set(LockPeerHash, 0L); val.Set(LockTokenHash, 0L); val.Set(LockUntilHash, 0L); val.Set(LockNameHash, ""); ZDOMan instance = ZDOMan.instance; if (instance != null) { instance.ForceSendZDO(val.m_uid); } return true; } private static void ApplyLockRequestRpc(ZNetView netView, long sender, long playerId, long lockToken, bool refreshOnly) { if (!((Object)(object)netView == (Object)null) && netView.IsValid() && netView.IsOwner()) { Player player; bool num = TryGetAuthenticatedPlayer(sender, playerId, out player); string message = ""; bool flag = num && TryAcquireMoveLock(netView, sender, player, lockToken, refreshOnly, out message); if (!num) { message = "$msg_privatezone"; } if (sender != 0L) { InvokePieceRpc(netView, sender, "MoveBuildPiecesV4_LockResponse", flag, message, lockToken); } } } private static void ApplyLockResponseRpc(ZNetView netView, long sender, bool granted, string message, long lockToken) { //IL_00a9: 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) CancelledLockRequest value; if (_state != null && (Object)(object)_state.NetView == (Object)(object)netView && _state.LockToken == lockToken && _state.LockRequestOwnerPeerId == sender) { _state.LockRequestOwnerPeerId = 0L; if (granted) { _state.LockOwnerPeerId = sender; } if (!granted) { Message(_state.Player, string.IsNullOrEmpty(message) ? "Move lock was lost" : message); Cancel(_state.Player, showMessage: false); } } else if (CancelledLockRequests.TryGetValue(lockToken, out value)) { if ((Object)(object)netView != (Object)null && netView.IsValid() && netView.GetZDO().m_uid == value.ZdoId && value.ExpectedOwnerPeerId == sender) { CancelledLockRequests.Remove(lockToken); if (granted) { ReleaseMoveLock(netView, value.PlayerId, value.LockToken, value.ExpectedOwnerPeerId); } } } else if (_pendingRequest != null && !((Object)(object)netView == (Object)null) && !((Object)(object)_pendingRequest.NetView != (Object)(object)netView) && _pendingRequest.LockToken == lockToken && _pendingRequest.ExpectedOwnerPeerId == sender) { PendingMoveRequest pendingRequest = _pendingRequest; _pendingRequest = null; if (!granted) { Message(pendingRequest.Player, string.IsNullOrEmpty(message) ? "$msg_inuse" : message); } else if (!CanBeginPendingMove(pendingRequest) || !ValidateMoveTarget(pendingRequest.Player, pendingRequest.Piece)) { ReleaseMoveLock(pendingRequest.NetView, pendingRequest.PlayerId, pendingRequest.LockToken, pendingRequest.ExpectedOwnerPeerId); } else { BeginMoveWithLockedPiece(pendingRequest.Player, pendingRequest.Piece, pendingRequest.Context, pendingRequest.ActivationMode, pendingRequest.NetView, pendingRequest.LockToken, sender); } } } private static void ApplyLockReleaseRpc(ZNetView netView, long sender, long playerId, long lockToken) { if (!((Object)(object)netView == (Object)null) && netView.IsValid() && netView.IsOwner()) { ClearMoveLock(netView, sender, playerId, lockToken); } } private static bool TryGetAuthenticatedPlayer(long senderPeerId, long playerId, out Player player) { player = null; if (senderPeerId == 0L || playerId == 0L) { return false; } List<Player> allPlayers = Player.GetAllPlayers(); for (int i = 0; i < allPlayers.Count; i++) { Player val = allPlayers[i]; if ((Object)(object)val != (Object)null && val.GetPlayerID() == playerId && ((Character)val).GetOwner() == senderPeerId && !((Character)val).IsDead() && !((Character)val).IsTeleporting()) { player = val; return true; } } return false; } private static bool CanBeginPendingMove(PendingMoveRequest request) { if (!HasVerifiedServerProtocol() || !NetworkMovesEnabled || (Object)(object)request?.Player == (Object)null || ((Character)request.Player).IsDead() || ((Character)request.Player).IsTeleporting() || (Object)(object)request.Piece == (Object)null || (Object)(object)request.NetView == (Object)null || !request.NetView.IsValid() || IsUiBlockingInput()) { return false; } bool flag = ((Character)request.Player).InPlaceMode(); if (request.Context != MoveContext.Build) { if (!flag) { return !HasEquippedBuildTool(request.Player); } return false; } return flag; } private static void CancelPendingRequest(Player player, bool showMessage, string message) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) PendingMoveRequest pendingRequest = _pendingRequest; if (pendingRequest != null && (!((Object)(object)player != (Object)null) || !((Object)(object)pendingRequest.Player != (Object)(object)player))) { _pendingRequest = null; ZDO val = (((Object)(object)pendingRequest.NetView != (Object)null && pendingRequest.NetView.IsValid()) ? pendingRequest.NetView.GetZDO() : null); if (val != null) { CancelledLockRequests[pendingRequest.LockToken] = new CancelledLockRequest { ZdoId = val.m_uid, PlayerId = pendingRequest.PlayerId, LockToken = pendingRequest.LockToken, ExpectedOwnerPeerId = pendingRequest.ExpectedOwnerPeerId, CancelledAt = Time.realtimeSinceStartup }; } try { ReleaseMoveLock(pendingRequest.NetView, pendingRequest.PlayerId, pendingRequest.LockToken, pendingRequest.ExpectedOwnerPeerId); } catch { } if (showMessage) { Message(pendingRequest.Player, "Move cancelled"); } else if (!string.IsNullOrEmpty(message)) { Message(pendingRequest.Player, message); } } } private static void CleanupCancelledLockRequests() { if (CancelledLockRequests.Count == 0) { _nextCancelledRequestCleanupAt = 0f; return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextCancelledRequestCleanupAt) { return; } _nextCancelledRequestCleanupAt = realtimeSinceStartup + 5f; ExpiredRequestTokens.Clear(); foreach (KeyValuePair<long, CancelledLockRequest> cancelledLockRequest in CancelledLockRequests) { if (realtimeSinceStartup - cancelledLockRequest.Value.CancelledAt > 310f) { ExpiredRequestTokens.Add(cancelledLockRequest.Key); } } for (int i = 0; i < ExpiredRequestTokens.Count; i++) { CancelledLockRequests.Remove(ExpiredRequestTokens[i]); } ExpiredRequestTokens.Clear(); } private static long CreateRequestToken() { long num = DateTime.UtcNow.Ticks ^ ZDOMan.GetSessionID() ^ ++_requestTokenCounter; if (num != 0L) { return num; } return ++_requestTokenCounter; } private static double GetNetworkTimeSeconds() { if (!((Object)(object)ZNet.instance != (Object)null)) { return Time.realtimeSinceStartupAsDouble; } return ZNet.instance.GetTimeSeconds(); } private static long SecondsToMillis(double seconds) { return (long)(seconds * 1000.0); } private static void UpdateActiveMovePlacement(Player player) { if (_state == null || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)_state.Player) { return; } if ((Object)(object)GetBuildPieces(player) != (Object)(object)GetRelocatePieceTable(_state)) { Cancel(player, showMessage: true); return; } RotateMoveGhost(player); if ((ZInput.GetButtonDown("Attack") || ZInput.GetButtonDown("JoyPlace")) && !Hud.InRadial()) { TryFinishMove(player); } } private static void RotateMoveGhost(Player player) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Invalid comparison between Unknown and I4 GameObject placementGhost = GetPlacementGhost(player); Piece val = (((Object)(object)placementGhost != (Object)null) ? placementGhost.GetComponent<Piece>() : null); if ((Object)(object)player == (Object)null || PlaceRotationField == null || ScrollCurrentAmountField == null || RotatePieceTimerField == null || (Object)(object)val == (Object)null || !val.m_canRotate || !placementGhost.activeInHierarchy) { return; } int num = ((PlaceRotationField.GetValue(player) is int num2) ? num2 : 0); float num3 = ((ScrollCurrentAmountField.GetValue(player) is float num4) ? num4 : 0f); num3 += ZInput.GetMouseScrollWheel(); if (num3 > player.m_scrollAmountThreshold) { num3 = 0f; num++; } else if (num3 < 0f - player.m_scrollAmountThreshold) { num3 = 0f; num--; } float num5 = 0f; bool flag = false; if (ZInput.IsGamepadActive()) { InputLayout inputLayout = ZInput.InputLayout; if ((int)inputLayout != 0) { if (inputLayout - 1 <= 1) { bool button = ZInput.GetButton("JoyRotate"); bool button2 = ZInput.GetButton("JoyRotateRight"); flag = button || button2; num5 = (button ? 0.5f : (button2 ? (-0.5f) : 0f)); } } else { num5 = ZInput.GetJoyRightStickX(true); flag = ZInput.GetButton("JoyRotate") && Mathf.Abs(num5) > 0.5f; } } float num6 = ((RotatePieceTimerField.GetValue(player) is float num7) ? num7 : 0f); if (flag) { if (num6 == 0f || num6 > 0.25f) { num += ((num5 < 0f) ? 1 : (-1)); if (num6 > 0.25f) { num6 = 0.17f; } } num6 += Time.deltaTime; } else { num6 = 0f; } PlaceRotationField.SetValue(player, num); ScrollCurrentAmountField.SetValue(player, num3); RotatePieceTimerField.SetValue(player, num6); } private static void StartMove(Player player, MoveContext context, MoveActivationMode activationMode) { bool flag = ((Character)player).InPlaceMode(); if ((context == MoveContext.Build && !flag) || (context == MoveContext.World && (flag || HasEquippedBuildTool(player)))) { return; } Piece val = ((context == MoveContext.World) ? FindWorldHoveringPiece(player) : player.GetHoveringPiece()); if ((Object)(object)val == (Object)null) { Message(player, "Hover a build piece to move it"); } else if (ValidateMoveTarget(player, val)) { ZNetView component = ((Component)val).GetComponent<ZNetView>(); long lockToken = CreateRequestToken(); if (TryAcquireOrRequestMoveLock(player, val, context, activationMode, component, lockToken)) { BeginMoveWithLockedPiece(player, val, context, activationMode, component, lockToken, component.GetZDO().GetOwner()); } } } private static void BeginMoveWithLockedPiece(Player player, Piece piece, MoveContext context, MoveActivationMode activationMode, ZNetView netView, long lockToken, long lockOwnerPeerId) { //IL_002e: 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)