Иконка ресурса

FREE PocketDimensions : 1.0.5 1.0.5

Нет прав для скачивания
C#:
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using WebSocketSharp;
namespace Oxide.Plugins {
    [Info("PocketDimensions", "Nikedemos", "1.0.5")]
    [Description("It's bigger on the inside")]
    public class PocketDimensions : RustPlugin {
        private const string VERSION = "1.0.5";
        [PluginReference]
        private Plugin CopyPaste, NoEscape, ServerRewards, Economics;
        public static PocketDimensions Instance;
#region CONST/STATIC
        public const string PREFAB_FOUNDATION_SQUARE = "assets/prefabs/building core/foundation/foundation.prefab";
        public const string PREFAB_FOUNDATION_TRIANGLE = "assets/prefabs/building core/foundation.triangle/foundation.triangle.prefab";
        public const string PREFAB_FLOOR_SQUARE = "assets/prefabs/building core/floor/floor.prefab";
        public const string PREFAB_WALL = "assets/prefabs/building core/wall/wall.prefab";
        public const string PREFAB_WALL_DOORWAY = "assets/prefabs/building core/wall.doorway/wall.doorway.prefab";
        public const string PREFAB_DOOR_METAL = "assets/prefabs/building/door.hinged/door.hinged.metal.prefab";
        public const string PREFAB_TC = "assets/prefabs/deployable/tool cupboard/cupboard.tool.deployed.prefab";
        public const string PREFAB_WOOD_STORAGE_BOX = "assets/prefabs/deployable/woodenbox/woodbox_deployed.prefab";
        public const string PREFAB_BUNKER_PORTAL = "assets/prefabs/missions/portal/bunker_door_portal.prefab";
        public const string PREFAB_MAPMARKER_GENERIC = "assets/prefabs/tools/map/genericradiusmarker.prefab";
        public const string SOCKET_NAME_DOORWAY_1 = "wall.doorway/sockets/doorway-female/1";
        public const string SOCKET_NAME_DOORWAY_2 = "wall.doorway/sockets/doorway-female/2";
        public const string FX_CODELOCK = "assets/prefabs/locks/keypad/effects/lock.code.shock.prefab";
        public const string FX_TELEPORT_APPEAR = "assets/prefabs/missions/portal/proceduraldungeon/effects/appear.prefab";
        public const string FX_TELEPORT_DISAPPEAR = "assets/prefabs/missions/portal/proceduraldungeon/effects/disappear.prefab";
        public const string ITEM_SHORTNAME_WOOD_STORAGE_BOX = "box.wooden";
        public static ItemDefinition ItemDefinitionWoodStorageBox;
        public static readonly BaseEntity.Flags FLAG_INTERNAL = BaseEntity.Flags.Reserved7;
        public static readonly BaseEntity.Flags FLAG_INDESTRUCTIBLE = BaseEntity.Flags.Reserved9;
        public static readonly BaseEntity.Flags FLAG_SPECIFIC = BaseEntity.Flags.OnFire;
        //used to mark middle foundations and external doorway
        public static readonly BasePlayer.PlayerFlags FLAG_IMMUNE_AFTER_TELEPORT = BasePlayer.PlayerFlags.Unused1;
        public static readonly BasePlayer.PlayerFlags FLAG_TOAST_TIMEOUT = BasePlayer.PlayerFlags.Unused2;
        public const string PREFIX_SHORT = "pd.";
        public const string PREFIX_LONG = "pocketdimensions.";
        public const string CMD_CHECK = PREFIX_SHORT + "check";
        public const string CMD_CONVERT = PREFIX_SHORT + "convert";
        public const string CMD_GIVE_BOX = PREFIX_SHORT + "givebox";
        public const string CMD_LOST_FOUND = PREFIX_SHORT + "lostnfound";
        public const string CMD_EMERGENCY_CLEANUP = PREFIX_SHORT + "emergencycleanup";
        public const string PERM_ADMIN = PREFIX_LONG + "admin";
        public const string PERM_ALL = PREFIX_LONG + "player.all";
        public const string PERM_DEPLOY_PICKUP = PREFIX_LONG + "deploy.pickup";
        public const string PERM_ENTER_EXIT = PREFIX_LONG + "player.enter.exit";
        public const string PERM_CONVERT_TC = PREFIX_LONG + "player.convert";
        public const string PERM_RESPAWN_IN_POCKET = PREFIX_LONG + "player.respawn";
        public const ulong SKIN_WATERBASE_TC = 1337424002;
        public static bool Unloading = false;
        public const int BREAK_TOASTS_EVERY_N_CHARACTERS = 80;
        public static Dictionary<string, string> ToastsCached;
        public static readonly Vector3 OFFSET_TC_POS_SIZE_1 = new Vector3(0F, 0.08F, -1F);
        public static readonly Vector3 OFFSET_PORTAL_POS_SIZE_1 = new Vector3(0F, 1F, 1.5F);
        public static readonly Vector3 OFFSET_PORTAL_ROT_SIZE_1 = new Vector3(270F, 0F, 0F);
        public const byte LAYER_VEHICLE_WORLD = 15;
        public const byte LAYER_DEFAULT = 0;
        public const byte LAYER_PLAYER = 17;
        public const byte LAYER_DEBRIS = 26;
        public const byte LAYER_DEPLOYED = 8;
        public const byte LAYER_RAGDOLL = 9;
        public const byte LAYER_AI = 11;
        public const byte LAYER_CONSTRUCTION = 21;
        public const byte LAYER_CONSTRUCTION_SOCKET = 22;
        public const byte LAYER_CLUTTER = 25;
        public const byte LAYER_WORLD = 16;
        public const byte LAYER_PREVENT_BUILDING = 29;
        public const int LAYERMASK_INTERESTING_ENTITIES = (1 << LAYER_VEHICLE_WORLD) | (1 << LAYER_DEFAULT) | (1 << LAYER_PLAYER) | (1 << LAYER_DEBRIS) | (1 << LAYER_DEPLOYED) | (1 << LAYER_RAGDOLL) | (1 << LAYER_AI) | (1 << LAYER_CONSTRUCTION) | (1 << LAYER_CONSTRUCTION_SOCKET) | (1 << LAYER_CLUTTER) | (1 << LAYER_WORLD) | (1 << LAYER_PREVENT_BUILDING);
        public const uint PREFAB_ID_SMALL_WOODEN_BOX = 1560881570;
#endregion
#region HOOK SUBSCRIPTIONS
        void OnServerInitialized() {
            Instance = this;
            lang.RegisterMessages(LangMessages, this);
            permission.RegisterPermission(PERM_ADMIN, this);
            permission.RegisterPermission(PERM_ALL, this);
            permission.RegisterPermission(PERM_DEPLOY_PICKUP, this);
            permission.RegisterPermission(PERM_ENTER_EXIT, this);
            permission.RegisterPermission(PERM_CONVERT_TC, this);
            permission.RegisterPermission(PERM_RESPAWN_IN_POCKET, this);
            LoadConfigData();
            ProcessConfigData();
            AddCovalenceCommand(CMD_EMERGENCY_CLEANUP, nameof(CommandEmergencyCleanup), PERM_ADMIN);
            AddCovalenceCommand(CMD_CONVERT, nameof(CommandConvert), PERM_ADMIN);
            AddCovalenceCommand(CMD_CHECK, nameof(CommandViabilityCheck), PERM_ADMIN);
            AddCovalenceCommand(CMD_GIVE_BOX, nameof(CommandGiveBox), PERM_ADMIN);
            AddCovalenceCommand(CMD_LOST_FOUND, nameof(CommandLostFound), PERM_ADMIN);
            ItemDefinitionWoodStorageBox = ItemManager.FindItemDefinition(ITEM_SHORTNAME_WOOD_STORAGE_BOX);
            SpawnedPasteRequest.RequestByPosition = new Dictionary<Vector3, SpawnedPasteRequest>();
            ReusableCardinalDirectionPositions = new Vector3[4];
            ReusableNeighbourPosTable = new Vector3[4][] {
                new Vector3[8], new Vector3[8], new Vector3[8], new Vector3[8],
            }
            ;
            ReusableFloorList = new List<BuildingBlock>();
            ReusableFoundationList = new List<BuildingBlock>();
            ReusableCombinedWallAndDoorwayList = new List<BuildingBlock>();
            ReusableShellElementList = new List<BuildingBlock>();
            ReusableExtraBaseCombatEntities = new List<BaseCombatEntity>();
            ReusableVisibilityList = new ListHashSet<BaseEntity>();
            ReusableColBuffer = new Collider[2048];
            ReusableCopypasteArgs = new string[] {
                "autoheight", "false"
            }
            ;
            ReusableMatchFoundationToCeiling = new Dictionary<BuildingBlock, BuildingBlock>(9);
            ReusableLostAndFoundArray = new DimensionalPocket[1024];
            ReusableGatherItemAmountArray = new GatherItemAmount[512];
            ReusableLostAndFoundArrayCount = 0;
            DimensionalBox.ServerCacheBox = new Dictionary<ulong, DimensionalBox>();
            DimensionalPocket.ServerCachePortal = new Dictionary<ulong, DimensionalPocket>();
            DimensionalPocket.ServerCacheShellBlockToPocket = new Dictionary<ulong, DimensionalPocket>();
            DimensionalPocket.ServerCacheBuildingIDToPocket = new Dictionary<uint, DimensionalPocket>();
            ToastsCached = new Dictionary<string, string>();
            Unloading = false;
            DimensionalPlayer.PrepareStatic();
            var findAllPortals = BaseNetworkable.serverEntities.OfType<BasePortal>().ToArray();
            BasePortal candidatePortal;
            for (var e = 0; e < findAllPortals.Length; e++) {
                candidatePortal = findAllPortals[e];
                if (!BaseNetworkableEx.IsValid(candidatePortal)) {
                    continue;
                }
                if (!IsEntityMarkedInternal(candidatePortal)) {
                    continue;
                }
                candidatePortal.gameObject.AddComponent<DimensionalPocket>();
            }
            var findAllStorageContainers = BaseNetworkable.serverEntities.OfType<StorageContainer>().ToArray();
            StorageContainer candidateContainer;
            for (var e = 0; e < findAllStorageContainers.Length; e++) {
                candidateContainer = findAllStorageContainers[e];
                if (!BaseNetworkableEx.IsValid(candidateContainer)) {
                    continue;
                }
                if (!IsEntityMarkedInternal(candidateContainer)) {
                    continue;
                }
                candidateContainer.gameObject.AddComponent<DimensionalBox>();
            }
            CheckAllLocks();
            CheckAllVendingMachines();
            ConversionGuiManager.Initialize();
            PositionCheckResult.Reset();
            foreach (var player in BasePlayer.activePlayerList) {
                OnPlayerConnected(player);
            }
        }
        public void CheckAllVendingMachines() {
            if (Configuration.DimensionaPocketsAllowVendingMachineBroadcast) {
                return;
            }
            var findAllVendingMachines = BaseNetworkable.serverEntities.OfType<VendingMachine>().ToArray();
            VendingMachine candidateMachine;
            for (var e = 0; e < findAllVendingMachines.Length; e++) {
                candidateMachine = findAllVendingMachines[e];
                OnEntitySpawned(candidateMachine);
            }
        }
        public void CheckAllLocks() {
            if (Configuration.DimensionalBoxesAllowLockingWithLocks) {
                return;
            }
            var findAllLocks = BaseNetworkable.serverEntities.OfType<BaseLock>().ToArray();
            BaseLock candidateLock;
            for (var e = 0; e < findAllLocks.Length; e++) {
                candidateLock = findAllLocks[e];
                OnEntitySpawned(candidateLock);
            }
        }
        void Unload() {
            Unloading = true;
            foreach (var player in BasePlayer.activePlayerList) {
                ConversionGuiManager.PlayerHideAllUI(player);
            }
            ConversionGuiManager.Cleanup();
            InternalBehaviour.DetachEverythingInternal();
            DimensionalBox.ServerCacheBox = null;
            DimensionalPocket.ServerCachePortal = null;
            DimensionalPocket.ServerCacheShellBlockToPocket = null;
            DimensionalPocket.ServerCacheBuildingIDToPocket = null;
            ToastsCached = null;
            ReusableNeighbourPosTable = null;
            ReusableCardinalDirectionPositions = null;
            ReusableFloorList = null;
            ReusableFoundationList = null;
            ReusableCombinedWallAndDoorwayList = null;
            ReusableVisibilityList = null;
            ReusableColBuffer = null;
            ReusableCopypasteArgs = null;
            ReusableMatchFoundationToCeiling = null;
            ReusableLostAndFoundArray = null;
            ReusableGatherItemAmountArray = null;
            ReusableShellElementList = null;
            ReusableExtraBaseCombatEntities = null;
            ItemDefinitionWoodStorageBox = null;
            SpawnedPasteRequest.RequestByPosition = null;
            DimensionalPlayer.UnloadStatic();
            PositionCheckResult.Reset();
            Instance = null;
            Unloading = false;
        }
        object OnPlayerCommand(BasePlayer player, string command, string[] args) {
            if (Instance == null) {
                return null;
            }
            if (!PositionWithinDimensionLayer(player.transform.position)) {
                return null;
            }
            if (!Configuration.ForbiddenCommandsCheckingEnabled) {
                return null;
            }
            if (Configuration.ForbiddenCommandsInsideDimensions.IsNullOrEmpty()) {
                return null;
            }
            if (!Configuration.ForbiddenCommandsInsideDimensions.Contains(command)) {
                return null;
            }
            if (HasAdminPermission(player)) {
                return null;
            }
            ToastPlayer(player, MSG(MSG_COMMAND_FORBIDDEN_INSIDE, player.UserIDString, command));
            return true;
        }
        //RemoverTool fix
        object canRemove(BasePlayer player, StorageContainer container) {
            if (container == null) {
                return null;
            }
            if (container.PrefabName != PREFAB_WOOD_STORAGE_BOX) {
                return null;
            }
            if (!IsEntityMarkedInternal(container)) {
                return null;
            }
            return true;
            //return non null
        }
        //TruePVE fix
        object CanEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo) {
            if (!BaseNetworkableEx.IsValid(entity)) {
                return null;
            }
            if (hitInfo == null) {
                return null;
            }
            if (!hitInfo.damageTypes.Has(Rust.DamageType.Generic)) {
                return null;
            }
            if (Mathf.Abs(hitInfo.damageTypes.Get(Rust.DamageType.Generic) - SPECIAL_DAMAGE_AMOUNT) > 0.001F) {
                return null;
            }
            return true;
        }
        void OnEntitySpawned(VendingMachine machine) {
            if (Instance == null) {
                return;
            }
            if (Instance.Configuration.DimensionaPocketsAllowVendingMachineBroadcast) {
                //nothing to see here
                return;
            }
            machine.Invoke(() => {
                if (Instance == null) {
                    return;
                }
                if (machine == null) {
                    return;
                }
                if (!machine.IsBroadcasting()) {
                    return;
                }
                var buildingID = machine.buildingID;
                if (buildingID == 0) {
                    return;
                }
                if (!DimensionalPocket.ServerCacheBuildingIDToPocket.ContainsKey(buildingID)) {
                    return;
                }
                machine.SetFlag(BaseEntity.Flags.Reserved4, false);
                machine.UpdateMapMarker();
            }
            , 0.02F);
        }
        void OnToggleVendingBroadcast(VendingMachine machine, BasePlayer player) {
            OnEntitySpawned(machine);
            if (Instance == null) {
                return;
            }
            if (Instance.Configuration.DimensionaPocketsAllowVendingMachineBroadcast) {
                //nothing to see here
                return;
            }
            if (!machine.IsBroadcasting()) {
                return;
            }
            var buildingID = machine.buildingID;
            if (buildingID == 0) {
                return;
            }
            if (!DimensionalPocket.ServerCacheBuildingIDToPocket.ContainsKey(buildingID)) {
                return;
            }
            ToastPlayer(player, MSG(MSG_NO_VENDING_MACHINE_BROADCASTING_IN_POCKETS, player.UserIDString));
        }
        object OnSleepingBagValidCheck(SleepingBag sleepingBag, ulong playerID, bool ignoreTimers) {
            if (Instance == null) {
                return null;
            }
            if (sleepingBag == null) {
                return null;
            }
            var player = BasePlayer.FindByID(playerID);
            if (player == null) {
                return null;
            }
            var buildingID = sleepingBag.buildingID;
            if (buildingID == 0) {
                return null;
            }
            if (!DimensionalPocket.ServerCacheBuildingIDToPocket.ContainsKey(buildingID)) {
                return null;
            }
            bool hasRespawnInPocketPermission = HasRespawnInPocketPermission(player);
            //if both the permission is present, AND you CAN respawn inside without the box being deployed, no need to go further
            if (hasRespawnInPocketPermission && !Configuration.DimensionalPocketsRespawningInsideRequiresDeployment) {
                return null;
            }
            //check if the player had just respawned in a non-deployed pocket Dimension
            object returnObject = null;
            if (!hasRespawnInPocketPermission) {
                returnObject = false;
            }
            else {
                //check if the pocket is deployed
                CheckPositionResultDeep(sleepingBag.transform.position);
                if (PositionCheckResult.BottomPocketFound != null && !PositionCheckResult.PocketIsDeployed) {
                    returnObject = false;
                    ToastPlayer(player, MSG(MSG_CANT_RESPAWN_INSIDE_NON_DEPLOYED, player.UserIDString));
                }
            }
            return returnObject;
        }
        void OnEntitySpawned(BaseLock baseLock) {
            if (Instance == null) {
                return;
            }
            if (Configuration.DimensionalBoxesAllowLockingWithLocks) {
                return;
            }
            if (baseLock == null) {
                return;
            }
            var lockOwnerThing = baseLock.parentEntity.Get(true) as StorageContainer;
            if (lockOwnerThing == null) {
                return;
            }
            if (lockOwnerThing.PrefabName != PREFAB_WOOD_STORAGE_BOX) {
                return;
            }
            if (!IsEntityMarkedInternal(lockOwnerThing)) {
                return;
            }
            DimensionalBox box;
            if (!DimensionalBox.ServerCacheBox.TryGetValue(lockOwnerThing.net.ID.Value, out box)) {
                return;
            }
            //drop the lock as an item
            baseLock.Invoke(() => {
                if (box == null) {
                    baseLock.Kill();
                    return;
                }
                if (box.ThisStorageContainer == null) {
                    baseLock.Kill();
                    return;
                }
                var item = ItemManager.Create(baseLock.itemType, 1, baseLock.skinID);
                if (item != null) {
                    item.Drop(baseLock.transform.position, Vector3.zero, baseLock.transform.rotation);
                }
                if (baseLock.PrefabName.Contains("code")) {
                    Effect.server.Run(FX_CODELOCK, baseLock.transform.position, baseLock.transform.up);
                }
                baseLock.Kill();
            }
            , 0.01F);
        }
        object OnEntityKill(BuildingBlock buildingBlock) {
            if (Instance == null) {
                return null;
            }
            if (buildingBlock == null) {
                return null;
            }
            if (!IsEntityMarkedInternal(buildingBlock)) {
                return null;
            }
            DimensionalPocket pocket;
            if (!DimensionalPocket.ServerCacheShellBlockToPocket.TryGetValue(buildingBlock.net.ID.Value, out pocket)) {
                return null;
            }
            return pocket.OnShellBlockKilled(buildingBlock);
        }
        object CanBeTargeted(BasePlayer player, DecayEntity entity) {
            if (Instance == null) {
                return null;
            }
            if (player.HasPlayerFlag(FLAG_IMMUNE_AFTER_TELEPORT)) {
                return false;
            }
            return null;
        }
        object OnItemPickup(Item item, BasePlayer player) {
            if (Instance == null) {
                return null;
            }
            if (!Instance.Configuration.DimensionalBoxesItemCheckTCAuthInsideWhenHandlingItem) {
                return null;
            }
            if (item == null) {
                return null;
            }
            if (player == null) {
                return null;
            }
            if (!IsDimensionalBoxItem(item)) {
                return null;
            }
            if (item.instanceData == null) {
                return null;
            }
            var pocket = TryGetDimensionalPocketFromNonNullItemWithDataInt(item);
            if (pocket == null) {
                return null;
            }
            if (pocket.IsPlayerBuildingBlockedOnFirstTcInsideIfThereIsAnyButOnlyIfAtLeast1Auth(player)) {
                ToastPlayer(player, MSG(MSG_CANT_HANDLE_WITHOUT_TC_AUTH2, player.UserIDString));
                return true;
            }
            return null;
        }
        private void OnPlayerDeath(BasePlayer player, HitInfo info) => OnPlayerMissingCommon(player);
        private void OnPlayerDisconnected(BasePlayer player, string reason) => OnPlayerMissingCommon(player);
        //not actually a hook
        private void OnPlayerMissingCommon(BasePlayer player) {
            if (Instance == null) {
                return;
            }
            if (IsPlayerNPC(player)) {
                return;
            }
            DimensionalPlayer dimensionalPlayer;
            if (!DimensionalPlayer.ServerCachePlayer.TryGetValue(player.userID, out dimensionalPlayer)) {
                return;
            }
            UnityEngine.Object.DestroyImmediate(dimensionalPlayer);
        }
        void OnPlayerSleepEnded(BasePlayer player) => OnPlayerConnected(player);
        void OnPlayerConnected(BasePlayer player) {
            if (Instance == null) {
                return;
            }
            if (!Configuration.DimensionalPocketsTeleportingInsideRequiresDeployment) {
                return;
            }
            if (IsPlayerNPC(player)) {
                return;
            }
            DimensionalPlayer compo;
            if (DimensionalPlayer.ServerCachePlayer.ContainsKey(player.userID)) {
                compo = DimensionalPlayer.ServerCachePlayer[player.userID];
            }
            else {
                compo = player.gameObject.AddComponent<DimensionalPlayer>();
            }
            compo.OnPlayerMajorUpdate(player);
        }
        object CanMoveItem(Item item, PlayerInventory playerLoot, ItemContainerId targetContainer, int targetSlot, int amount) {
            //TODO: Test this
            //ALso: don't allow the player to drop this if not authed.
            if (Instance == null) {
                return null;
            }
            if (!Instance.Configuration.DimensionalBoxesItemCheckTCAuthInsideWhenHandlingItem) {
                return null;
            }
            if (item == null) {
                return null;
            }
            if (!IsDimensionalBoxItem(item)) {
                return null;
            }
            if (item.instanceData == null) {
                return null;
            }
            if (playerLoot == null) {
                return null;
            }
            var player = playerLoot.GetComponent<BasePlayer>();
            if (player == null) {
                return null;
            }
            var pocket = TryGetDimensionalPocketFromNonNullItemWithDataInt(item);
            if (pocket == null) {
                return null;
            }
            if (pocket.IsPlayerBuildingBlockedOnFirstTcInsideIfThereIsAnyButOnlyIfAtLeast1Auth(player)) {
                ToastPlayer(player, MSG(MSG_CANT_HANDLE_WITHOUT_TC_AUTH2, player.UserIDString));
                return true;
            }
            return null;
        }
        object CanCombineDroppedItem(DroppedItem droppedItem, DroppedItem droppedTargetItem) {
            if (Instance == null) {
                return null;
            }
            if (droppedItem == null) {
                return null;
            }
            if (droppedTargetItem == null) {
                return null;
            }
            if (droppedItem.item == null) {
                return null;
            }
            if (droppedTargetItem.item == null) {
                return null;
            }
            if (!(IsDimensionalBoxItem(droppedItem.item) || IsDimensionalBoxItem(droppedItem.item))) {
                return null;
            }
            return false;
        }
        void OnItemRemove(Item item) {
            if (Instance == null) {
                return;
            }
            if (item == null) {
                return;
            }
            if (!IsDimensionalBoxItem(item)) {
                return;
            }
            if (item.instanceData == null) {
                return;
            }
            var pocket = TryGetDimensionalPocketFromNonNullItemWithDataInt(item);
            if (pocket == null) {
                return;
            }
            MarkEntityAsSpecific(pocket.ThisPortal);
        }
        object OnPortalUse(BasePlayer player, BasePortal portal) {
            if (Instance == null) {
                return null;
            }
            if (player == null) {
                return null;
            }
            if (!IsEntityMarkedInternal(portal)) {
                return null;
            }
            DimensionalPocket pocket;
            if (!DimensionalPocket.ServerCachePortal.TryGetValue(portal.net.ID.Value, out pocket)) {
                return null;
            }
            if (!HasEnterExitPermission(player)) {
                ToastPlayer(player, MSG(MSG_NO_PERMISSION_ENTER_EXIT, player.UserIDString));
                return true;
            }
            if (Instance.Configuration.CheckEscapeBlockWhenExitingDimensions) {
                if (IsEscapeBlocked(player)) {
                    ToastPlayer(player, MSG(MSG_ESCAPE_BLOCKED_CANT_EXIT, player.UserIDString));
                    return true;
                }
            }
            pocket.PlayerUsePortal(player);
            //return non null
            return true;
        }
        object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (Instance == null) {
                return null;
            }
            if (info == null) {
                return null;
            }
            if (!IsEntityMarkedInternal(entity)) {
                return null;
            }
            //always let decay damage through
            if (info.damageTypes.GetMajorityDamageType() == Rust.DamageType.Decay) {
                return null;
            }
            if (!Configuration.DimensionalPocketsExteriorBlocksAllowNonDecayDamage) {
                if (DimensionalPocket.ServerCacheShellBlockToPocket.ContainsKey(entity.net.ID.Value)) {
                    return true;
                }
            }
            if (!IsEntityMarkedIndestructible(entity)) {
                return null;
            }
            //is this a box?...
            if (DimensionalBox.ServerCacheBox.ContainsKey(entity.net.ID.Value)) {
                if (!Configuration.DimensionalBoxesAllowDamage) {
                    return true;
                }
                else {
                    //adjust the damage
                    info.damageTypes.ScaleAll(1F / Mathf.Max(0.001F, Configuration.DimensionaBoxesDamageResistanceDivisor));
                    return null;
                }
            }
            return null;
        }
        void OnLootEntity(BasePlayer player, BuildingPrivlidge tc) {
            if (Instance == null) {
                return;
            }
            if (player == null) {
                return;
            }
            if (!HasConvertTCPermission(player)) {
                return;
            }
            if (tc.buildingID == 0) {
                return;
            }
            if (IsTCWaterBaseTC(tc)) {
                return;
            }
            //is it already converted?
            if (DimensionalPocket.ServerCacheBuildingIDToPocket.ContainsKey(tc.buildingID)) {
                return;
            }
            ConversionGuiManager.PlayerOpenTC(player, tc);
        }
        void OnLootEntityEnd(BasePlayer player, BuildingPrivlidge tc) {
            if (Instance == null) {
                return;
            }
            if (player == null) {
                return;
            }
            if (IsTCWaterBaseTC(tc)) {
                return;
            }
            ConversionGuiManager.PlayerHideAllUI(player);
        }
        object CanLootEntity(BasePlayer player, StorageContainer container) {
            if (Instance == null) {
                return null;
            }
            if (player == null) {
                return null;
            }
            if (container == null) {
                return null;
            }
            if (container.PrefabName != PREFAB_WOOD_STORAGE_BOX) {
                return null;
            }
            if (!IsEntityMarkedInternal(container)) {
                return null;
            }
            DimensionalBox box;
            if (!DimensionalBox.ServerCacheBox.TryGetValue(container.net.ID.Value, out box)) {
                return null;
            }
            if (!HasEnterExitPermission(player)) {
                ToastPlayer(player, MSG(MSG_NO_PERMISSION_ENTER_EXIT, player.UserIDString));
                return true;
            }
            if (Instance.Configuration.CheckEscapeBlockWhenEnteringDimensions) {
                if (IsEscapeBlocked(player)) {
                    ToastPlayer(player, MSG(MSG_CANT_ENTER_ESCAPE_BLOCKED, player.UserIDString));
                    return true;
                }
            }
            if (Instance.Configuration.DimensionalBoxesCheckBuildingBlockOutsideWhenEnteringDimension) {
                if (player.IsBuildingBlocked()) {
                    ToastPlayer(player, MSG(MSG_CANT_ENTER_BUILDING_BLOCKED, player.UserIDString));
                    return true;
                }
            }
            if (Instance.Configuration.DimensionalBoxesCheckTCAuthInsideWhenEnteringDimension) {
                if (box.PairedPocket.IsPlayerBuildingBlockedOnFirstTcInsideIfThereIsAnyButOnlyIfAtLeast1Auth(player)) {
                    ToastPlayer(player, MSG(MSG_CANT_ENTER_WITHOUT_TC_AUTH2, player.UserIDString));
                    return true;
                }
            }
            if (container.IsLocked()) {
                player.ShowToast(GameTip.Styles.Red_Normal, StorageContainer.LockedMessage);
                return true;
            }
            ;
            if (!container.CanOpenLootPanel(player, container.panelName)) {
                return true;
            }
            ;
            box.PlayerOpenedBox(player);
            //return non null
            return true;
        }
        object CanBuild(Planner planner, Construction prefab, Construction.Target target) {
            //TODO: Don't allow to deploy the dimension in itself!
            //ALSO: Don't allow to deploy the dimension if it already has a paired box - destroy this item to prevent this in the future.
            //
            if (Instance == null) {
                return null;
            }
            if (prefab.prefabID != PREFAB_ID_SMALL_WOODEN_BOX) {
                return null;
            }
            var player = planner.GetOwnerPlayer();
            if (player == null) {
                return null;
            }
            //ok, it's a small box. have you verified the item or what...?
            var item = planner.GetItem();
            //looking for existing and fresh
            bool isExisting = IsDimensionalBoxItem(item);
            bool isFresh = IsDimensionalBoxItem(item, true);
            if (!(isExisting || isFresh)) {
                return null;
            }
            //now player!
            if (!HasDeployPickupPermission(player)) {
                ToastPlayer(player, MSG(MSG_NO_PERM_DEPLOY_PICKUP, player.UserIDString));
                return true;
            }
            if (Instance.Configuration.CheckEscapeBlockWhenDeployingDimensions) {
                if (IsEscapeBlocked(player)) {
                    ToastPlayer(player, MSG(MSG_ESCAPE_BLOCKED_CANT_DEPLOY, player.UserIDString));
                    return true;
                }
            }
            var targetPosition = target.entity && target.entity.transform && target.socket ? target.GetWorldPosition() : target.position;
            DimensionalPocket itemDimension = null;
            bool itemDimensionNotNull = false;
            if (isExisting) {
                if (item.instanceData != null) {
                    if (item.instanceData.dataInt != 0) {
                        var pocket = TryGetDimensionalPocketFromNonNullItemWithDataInt(item);
                        if (pocket != null) {
                            itemDimension = pocket;
                            itemDimensionNotNull = true;
                        }
                    }
                }
            }
            CheckPositionResultDeep(targetPosition, itemDimension);
            //now check for any problems.
            //first, cannot deploy in itself.
            if (PositionCheckResult.BottomPocketFound != null) {
                if (Instance.Configuration.DimensionalPocketsMaxInceptionDepth == 0) {
                    ToastPlayer(player, MSG(MSG_CANT_DEPLOY_DIMENSIONS_INSIDE_DIMENSIONS, player.UserIDString));
                    return true;
                }
                //ok, we're trying to deploy a dimension inside a dimension.
                if (itemDimensionNotNull) {
                    //are you trying to deploy in yourself?!
                    //check if you short circuited
                    if (PositionCheckResult.ShortCircuitDetected) {
                        ToastPlayer(player, MSG(MSG_CANT_DEPLOY_SHORT_CIRCUIT, player.UserIDString));
                        return true;
                    }
                    if (itemDimension == PositionCheckResult.BottomPocketFound) {
                        ToastPlayer(player, MSG(MSG_CANT_DEPLOY_IN_ITSELF, player.UserIDString));
                        return true;
                        //return non null
                    }
                    //what about deploying in undeployed dimensions?!
                    //should that be a config value?
                }
                //for depth, new dimensions should be checked too!
                if (PositionCheckResult.NoMoreDepthAllowed) {
                    ToastPlayer(player, MSG(MSG_CANT_DEPLOY_TOO_DEEP, player.UserIDString, Instance.Configuration.DimensionalPocketsMaxInceptionDepth));
                    return true;
                }
            }
            return null;
        }
        void OnEntityBuilt(Planner planner, GameObject gameObject) {
            if (Instance == null) {
                return;
            }
            var maybeDimensionalBoxItem = planner.GetItem();
            if (maybeDimensionalBoxItem == null) {
                return;
            }
            var maybeStorage = gameObject.GetComponent<StorageContainer>();
            if (maybeStorage == null) {
                return;
            }
            //here, only non-fresh matter
            if (!IsDimensionalBoxItem(maybeDimensionalBoxItem)) {
                return;
            }
            MarkEntityAsIndestructible(maybeStorage);
            MarkEntityAsInternal(maybeStorage);
            var newDimensionalBox = maybeStorage.gameObject.AddComponent<DimensionalBox>();
            if (!newDimensionalBox.TryBuildFromItem(maybeDimensionalBoxItem)) {
                var player = planner.GetOwnerPlayer();
                if (player == null) {
                    return;
                }
                ToastPlayer(player, MSG(MSG_DIMENSION_DOESNT_EXIST, player.UserIDString));
                maybeStorage.Invoke(() => maybeStorage.Kill(BaseNetworkable.DestroyMode.Gib), 0.01F);
            }
        }
        object CanPickupEntity(BasePlayer player, StorageContainer entity) {
            if (Instance == null) {
                return null;
            }
            if (player == null) {
                return null;
            }
            if (!IsEntityMarkedInternal(entity)) {
                return null;
            }
            DimensionalBox box;
            if (!DimensionalBox.ServerCacheBox.TryGetValue(entity.net.ID.Value, out box)) {
                return null;
            }
            if (!HasDeployPickupPermission(player)) {
                ToastPlayer(player, MSG(MSG_NO_PERM_DEPLOY_PICKUP, player.UserIDString));
                return false;
            }
            if (Instance.Configuration.CheckEscapeBlockWhenPickingUpDimensions) {
                if (IsEscapeBlocked(player)) {
                    ToastPlayer(player, MSG(MSG_ESCAPE_BLOCKED_CANT_PICKUP, player.UserIDString));
                    return false;
                }
            }
            var res = box.CanPickupBox(player);
            return res;
        }
        void OnEntityPickedUp(StorageContainer container, Item createdItem, BasePlayer player) {
            if (Instance == null) {
                return;
            }
            if (container.PrefabName != PREFAB_WOOD_STORAGE_BOX) {
                return;
            }
            if (!IsEntityMarkedInternal(container)) {
                return;
            }
            DimensionalBox box;
            if (!DimensionalBox.ServerCacheBox.TryGetValue(container.net.ID.Value, out box)) {
                return;
            }
            box.OnPickedUp(createdItem, player);
        }
#endregion
#region DIMENSIONAL PLAYER
        public class DimensionalPlayer : InternalBehaviour {
            public static Hash<ulong, DimensionalPlayer> ServerCachePlayer;
            public BasePlayer Player;
            public ulong SteamID;
            public Vector3 LastCheckedPosition;
            public bool WasFlyingLastTimeChecked;
            public static void PrepareStatic() {
                ServerCachePlayer = new Hash<ulong, DimensionalPlayer>();
            }
            public static void UnloadStatic() {
                ServerCachePlayer = null;
            }
            public void OnPlayerMajorUpdate(BasePlayer player) {
                Player = player;
                SteamID = Player.userID;
                LastCheckedPosition = Player.transform.position;
                WasFlyingLastTimeChecked = Player.IsFlying;
                if (!ServerCachePlayer.ContainsKey(SteamID)) {
                    ServerCachePlayer.Add(SteamID, this);
                }
                PositionChangeUpdate(true);
                if (!Player.IsInvoking(PositionChangeUpdate)) {
                    Player.InvokeRandomized(PositionChangeUpdate, 0.5F, 0.5F, 0.1F);
                }
            }
            public void PositionChangeUpdate() => PositionChangeUpdate(false);
            public void PositionChangeUpdate(bool whenPreparing = false) {
                if (Player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
                    return;
                }
                //when preparing, force an update anyway
                if (!whenPreparing) {
                    if (Player.transform.position == LastCheckedPosition) {
                        return;
                    }
                    if (WasFlyingLastTimeChecked || Player.IsFlying) {
                        LastCheckedPosition = Player.transform.position;
                        WasFlyingLastTimeChecked = Player.IsFlying;
                        return;
                    }
                }
                //position changed to something different.
                //check if the new position is inside the range for pocket dimensions.
                //bool wasInDimensionLayerBefore = PositionWithinDimensionLayer(LastCheckedPosition);
                bool isInDimensionLayerNow = PositionWithinDimensionLayer(Player.transform.position);
                if (isInDimensionLayerNow) {
                    bool needTeleportBack = false;
                    string reasonForTeleportingBack = default(string);
                    //yes, this is in the range.
                    //check how much it changed.
                    var distanceTraversed = Vector3.Distance(LastCheckedPosition, Player.transform.position);
                    if (distanceTraversed > 40F) {
                        //that looks like a teleport to a dimension above.
                        //do a raycast down, 10 meters max.
                        //if you encounter absolutely nothing, you need to be teleported back.
                        //by "something" we mean a decay entity.
                        CheckPositionResultDeep(Player.transform.position);
                        if (PositionCheckResult.NothingAround) {
                            //absolutely nothing found. We need to teleport the player back.
                            needTeleportBack = true;
                            reasonForTeleportingBack = MSG(MSG_DIMENSION_DOESNT_EXIST, Player.UserIDString);
                        }
                        else {
                            if (PositionCheckResult.BottomPocketFound != null) {
                                if (!PositionCheckResult.PocketIsDeployed) {
                                    needTeleportBack = true;
                                    reasonForTeleportingBack = MSG(MSG_CANT_TELEPORT_INSIDE_NON_DEPLOYED, Player.UserIDString);
                                }
                            }
                        }
                    }
                    if (needTeleportBack) {
                        TeleportPlayerTo(Player, LastCheckedPosition);
                        ToastPlayer(Player, reasonForTeleportingBack);
                    }
                }
                LastCheckedPosition = Player.transform.position;
                WasFlyingLastTimeChecked = Player.IsFlying;
            }
            void OnDestroy() {
                if (Player != null) {
                    Player.CancelInvoke(PositionChangeUpdate);
                }
                ServerCachePlayer.Remove(SteamID);
            }
        }
#endregion
#region LANG
        public const string MSG_POCKET_DIMENSION_ITEM_NAME = nameof(MSG_POCKET_DIMENSION_ITEM_NAME);
        public const string MSG_CONVERT_COST_CURRENCY_NAME_SERVER_REWARDS = nameof(MSG_CONVERT_COST_CURRENCY_NAME_SERVER_REWARDS);
        public const string MSG_CONVERT_COST_CURRENCY_NAME_ECONOMICS = nameof(MSG_CONVERT_COST_CURRENCY_NAME_ECONOMICS);
        public const string MSG_CONVERT_COST_LABEL_TEXT_AND_FORMAT = nameof(MSG_CONVERT_COST_LABEL_TEXT_AND_FORMAT);
        public const string MSG_CONVERT_BUTTON_CONVERT = nameof(MSG_CONVERT_BUTTON_CONVERT);
        public const string MSG_CONVERT_TEST_FAILED = nameof(MSG_CONVERT_TEST_FAILED);
        public const string MSG_CONVERTED_SUCCESSFULLY = nameof(MSG_CONVERTED_SUCCESSFULLY);
        public const string MSG_CONVERT_COST_CANNOT_AFFORD = nameof(MSG_CONVERT_COST_CANNOT_AFFORD);
        public const string MSG_CONVERT_COST_FORMAT_SERVER_REWARDS = nameof(MSG_CONVERT_COST_FORMAT_SERVER_REWARDS);
        public const string MSG_CONVERT_COST_FORMAT_ECONOMICS = nameof(MSG_CONVERT_COST_FORMAT_ECONOMICS);
        public const string MSG_CONVERT_COST_FORMAT_CUSTOM_ITEM_AMOUNT = nameof(MSG_CONVERT_COST_FORMAT_CUSTOM_ITEM_AMOUNT);
        public const string MSG_CONVERT_COST_MISSING_PLUGIN = nameof(MSG_CONVERT_COST_MISSING_PLUGIN);
        public const string MSG_COMMAND_FORBIDDEN_INSIDE = nameof(MSG_COMMAND_FORBIDDEN_INSIDE);
        public const string MSG_NO_PERMISSION_ENTER_EXIT = nameof(MSG_NO_PERMISSION_ENTER_EXIT);
        public const string MSG_NO_PERM_DEPLOY_PICKUP = nameof(MSG_NO_PERM_DEPLOY_PICKUP);
        public const string MSG_NO_CONVERT_PERMISSION = nameof(MSG_NO_CONVERT_PERMISSION);
        public const string MSG_DIMENSION_DOESNT_EXIST = nameof(MSG_DIMENSION_DOESNT_EXIST);
        public const string MSG_CANT_RESPAWN_INSIDE_NON_DEPLOYED = nameof(MSG_CANT_RESPAWN_INSIDE_NON_DEPLOYED);
        public const string MSG_CANT_TELEPORT_INSIDE_NON_DEPLOYED = nameof(MSG_CANT_TELEPORT_INSIDE_NON_DEPLOYED);
        public const string MSG_CANT_DEPLOY_IN_ITSELF = nameof(MSG_CANT_DEPLOY_IN_ITSELF);
        public const string MSG_CANT_DEPLOY_SHORT_CIRCUIT = nameof(MSG_CANT_DEPLOY_SHORT_CIRCUIT);
        public const string MSG_CANT_DEPLOY_DIMENSIONS_INSIDE_DIMENSIONS = nameof(MSG_CANT_DEPLOY_DIMENSIONS_INSIDE_DIMENSIONS);
        public const string MSG_CANT_DEPLOY_TOO_DEEP = nameof(MSG_CANT_DEPLOY_TOO_DEEP);
        public const string MSG_CANT_PICK_UP_WITH_PLAYERS_INSIDE = nameof(MSG_CANT_PICK_UP_WITH_PLAYERS_INSIDE);
        public const string MSG_CANT_PICK_UP_WITHOUT_TC_AUTH2 = nameof(MSG_CANT_PICK_UP_WITHOUT_TC_AUTH2);
        public const string MSG_CANT_HANDLE_WITHOUT_TC_AUTH2 = nameof(MSG_CANT_HANDLE_WITHOUT_TC_AUTH2);
        public const string MSG_CANT_GET_OUT_STUCK = nameof(MSG_CANT_GET_OUT_STUCK);
        public const string MSG_CANT_ENTER_ESCAPE_BLOCKED = nameof(MSG_CANT_ENTER_ESCAPE_BLOCKED);
        public const string MSG_CANT_ENTER_BUILDING_BLOCKED = nameof(MSG_CANT_ENTER_BUILDING_BLOCKED);
        public const string MSG_CANT_ENTER_WITHOUT_TC_AUTH2 = nameof(MSG_CANT_ENTER_WITHOUT_TC_AUTH2);
        public const string MSG_ESCAPE_BLOCKED_CANT_EXIT = nameof(MSG_ESCAPE_BLOCKED_CANT_EXIT);
        public const string MSG_ESCAPE_BLOCKED_CANT_DEPLOY = nameof(MSG_ESCAPE_BLOCKED_CANT_DEPLOY);
        public const string MSG_ESCAPE_BLOCKED_CANT_PICKUP = nameof(MSG_ESCAPE_BLOCKED_CANT_PICKUP);
        public const string MSG_VIABILITY_OK = nameof(MSG_VIABILITY_OK);
        public const string MSG_VIABILITY_TOO_MANY_TCS = nameof(MSG_VIABILITY_TOO_MANY_TCS);
        public const string MSG_VIABILITY_NO_BUILDING_BLOCKS = nameof(MSG_VIABILITY_NO_BUILDING_BLOCKS);
        public const string MSG_VIABILITY_ONLY_SQUARE_FOUNDATIONS = nameof(MSG_VIABILITY_ONLY_SQUARE_FOUNDATIONS);
        public const string MSG_VIABILITY_MUST_HAVE_9_FOUNDATIONS = nameof(MSG_VIABILITY_MUST_HAVE_9_FOUNDATIONS);
        public const string MSG_VIABILITY_MUST_HAVE_AT_LEAST_9_FLOORS = nameof(MSG_VIABILITY_MUST_HAVE_AT_LEAST_9_FLOORS);
        public const string MSG_VIABILITY_MUST_HAVE_1_DOORWAY = nameof(MSG_VIABILITY_MUST_HAVE_1_DOORWAY);
        public const string MSG_VIABILITY_MUST_HAVE_AT_LEAST_35_WA
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху