コード例 #1
0
        private static bool SharedCheckTileRequirementsForRelocation(
            ICharacter character,
            IStaticWorldObject objectStructure,
            Vector2Ushort toPosition,
            out string errorMessage,
            bool logErrors)
        {
            if (!(objectStructure.ProtoGameObject is IProtoObjectStructure protoStructure))
            {
                errorMessage = null;
                return(false);
            }

            var world = Api.IsServer
                            ? (IWorldService)Server.World
                            : (IWorldService)Client.World;

            var tileRequirements      = protoStructure.TileRequirements;
            var occupiedTilePositions = new HashSet <Vector2Ushort>(objectStructure.OccupiedTilePositions);

            foreach (var tileOffset in protoStructure.Layout.TileOffsets)
            {
                var tilePosition = new Vector2Ushort((ushort)(toPosition.X + tileOffset.X),
                                                     (ushort)(toPosition.Y + tileOffset.Y));
                if (occupiedTilePositions.Contains(tilePosition))
                {
                    // no need to check that tile as the object player want to move is already there
                    continue;
                }

                var tile = world.GetTile(tilePosition,
                                         logOutOfBounds: false);

                if (tile.IsOutOfBounds)
                {
                    errorMessage = "Out of bounds";
                }
                else
                {
                    var context = new ConstructionTileRequirements.Context(tile,
                                                                           character,
                                                                           protoStructure,
                                                                           tileOffset,
                                                                           startTilePosition: toPosition,
                                                                           objectToRelocate: objectStructure);
                    if (tileRequirements.Check(context, out errorMessage))
                    {
                        // valid tile
                        continue;
                    }
                }

                // check failed
                if (!logErrors)
                {
                    return(false);
                }

                if (Api.IsServer)
                {
                    Api.Logger.Warning(
                        $"Cannot move {protoStructure} at {toPosition} - check failed:"
                        + Environment.NewLine
                        + errorMessage);
                }

                ConstructionSystem.SharedShowCannotPlaceNotification(
                    character,
                    errorMessage,
                    protoStructure);

                return(false);
            }

            errorMessage = null;
            return(true);
        }
コード例 #2
0
        public static void ClientStartRelocation(IStaticWorldObject objectStructure)
        {
            var protoStructure = objectStructure.ProtoStaticWorldObject;
            var character      = Client.Characters.CurrentPlayerCharacter;

            if (IsInObjectPlacementMode ||
                ConstructionPlacementSystem.IsInObjectPlacementMode)
            {
                // already relocating/placing something
                return;
            }

            if (!SharedIsRelocatable(objectStructure))
            {
                return;
            }

            if (!CreativeModeSystem.SharedIsInCreativeMode(character) &&
                !LandClaimSystem.SharedIsOwnedLand(objectStructure.TilePosition, character, out _))
            {
                // the building location or destination is in an area that is not owned by the player
                ConstructionSystem.SharedShowCannotPlaceNotification(
                    character,
                    LandClaimSystem.ErrorNotLandOwner_Message,
                    protoStructure);
                return;
            }

            var isPvEorWithinInteractionArea = PveSystem.SharedIsPve(false) ||
                                               protoStructure.SharedIsInsideCharacterInteractionArea(
                Api.Client.Characters.CurrentPlayerCharacter,
                objectStructure,
                writeToLog: false);

            if (!isPvEorWithinInteractionArea)
            {
                CannotInteractMessageDisplay.ClientOnCannotInteract(
                    character,
                    CoreStrings.Notification_TooFar,
                    isOutOfRange: true);
                return;
            }

            if (LandClaimSystem.SharedIsUnderRaidBlock(character, objectStructure))
            {
                // the building is in an area under the raid
                ConstructionSystem.SharedShowCannotBuildNotification(
                    character,
                    LandClaimSystem.ErrorRaidBlockActionRestricted_Message,
                    protoStructure);
                return;
            }

            if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(objectStructure))
            {
                // the building is in an area under shield protection
                LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection(
                    character);
                return;
            }

            ClientDisableConstructionRelocation();

            var sceneObject = Client.Scene.CreateSceneObject("StructureRelocationHelper");

            componentObjectPlacementHelper = sceneObject.AddComponent <ClientComponentObjectPlacementHelper>();
            componentRelocationHelper      = sceneObject.AddComponent <ClientComponentObjectRelocationHelper>();

            componentObjectPlacementHelper
            .Setup(protoStructure,
                   isCancelable: true,
                   isRepeatCallbackIfHeld: false,
                   isDrawConstructionGrid: true,
                   isBlockingInput: true,
                   validateCanPlaceCallback: ClientValidateCanRelocate,
                   placeSelectedCallback: ClientConstructionPlaceSelectedCallback,
                   delayRemainsSeconds: 0.1);
            componentObjectPlacementHelper.HideBlueprintOnOverlapWithTheSameObject = false;

            componentRelocationHelper.Setup(objectStructure);

            void ClientValidateCanRelocate(
                Vector2Ushort tilePosition,
                bool logErrors,
                out bool canPlace,
                out bool isTooFar)
            {
                if (tilePosition == objectStructure.TilePosition)
                {
                    canPlace = true;
                    isTooFar = false;
                    return;
                }

                if (!SharedCheckTileRequirementsForRelocation(character,
                                                              objectStructure,
                                                              tilePosition,
                                                              logErrors: logErrors))
                {
                    // time requirements are not valid
                    canPlace = false;
                    isTooFar = false;
                    return;
                }

                if (!SharedValidateCanCharacterRelocateStructure(character,
                                                                 objectStructure,
                                                                 tilePosition,
                                                                 logErrors: logErrors))
                {
                    canPlace = true;
                    isTooFar = true;
                    return;
                }

                if (SharedHasObstacle(
                        character,
                        objectStructure,
                        tilePosition.ToVector2D() + protoStructure.Layout.Center))
                {
                    if (logErrors)
                    {
                        CannotInteractMessageDisplay.ClientOnCannotInteract(
                            character,
                            CoreStrings.Notification_ObstaclesOnTheWay,
                            isOutOfRange: true);
                    }

                    canPlace = true;
                    isTooFar = true;
                    return;
                }

                canPlace = true;
                isTooFar = false;
            }

            void ClientConstructionPlaceSelectedCallback(Vector2Ushort tilePosition)
            {
                if (SharedHasObstacle(
                        character,
                        objectStructure,
                        tilePosition.ToVector2D() + protoStructure.Layout.Center))
                {
                    CannotInteractMessageDisplay.ClientOnCannotInteract(
                        character,
                        CoreStrings.Notification_ObstaclesOnTheWay,
                        isOutOfRange: true);
                    return;
                }

                ClientTimersSystem.AddAction(0.1, ClientDisableConstructionRelocation);
                if (tilePosition != objectStructure.TilePosition)
                {
                    Instance.CallServer(_ => _.ServerRemote_RelocateStructure(objectStructure, tilePosition));
                }
            }
        }
コード例 #3
0
        public static bool SharedValidateCanCharacterRelocateStructure(
            ICharacter character,
            IStaticWorldObject objectStructure,
            Vector2Ushort toPosition,
            out string errorMessage,
            bool logErrors)
        {
            if (!SharedIsRelocatable(objectStructure))
            {
                errorMessage = null;
                return(false);
            }

            if (!SharedCheckTileRequirementsForRelocation(character,
                                                          objectStructure,
                                                          toPosition,
                                                          out errorMessage,
                                                          logErrors))
            {
                return(false);
            }

            if (!(objectStructure.ProtoGameObject is IProtoObjectStructure protoStructure))
            {
                return(false);
            }

            var maxRelocationDistance = PveSystem.SharedIsPve(true)
                                            ? MaxRelocationDistancePvE
                                            : MaxRelocationDistancePvP;

            if (objectStructure.TilePosition.TileSqrDistanceTo(toPosition)
                > maxRelocationDistance * maxRelocationDistance)
            {
                if (logErrors)
                {
                    ConstructionSystem.SharedShowCannotPlaceNotification(
                        character,
                        CoreStrings.Notification_TooFar,
                        protoStructure);
                }

                errorMessage = CoreStrings.Notification_TooFar;
                return(false);
            }

            var itemInHands = character.SharedGetPlayerSelectedHotbarItem();

            if (!(itemInHands.ProtoGameObject is IProtoItemToolToolbox))
            {
                return(false);
            }

            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                errorMessage = null;
                return(true);
            }

            if (!LandClaimSystem.SharedIsOwnedLand(objectStructure.TilePosition,
                                                   character,
                                                   requireFactionPermission: true,
                                                   out var hasNoFactionPermission,
                                                   ownedArea: out _) ||
                !IsOwnedLand(toPosition, out hasNoFactionPermission))
            {
                errorMessage = string.Format(CoreStrings.Faction_Permission_Required_Format,
                                             CoreStrings.Faction_Permission_LandClaimManagement_Title);

                // the building location or destination is in an area that is not owned by the player
                if (logErrors)
                {
                    SharedShowCannotRelocateNotification(
                        character,
                        protoStructure,
                        hasNoFactionPermission);
                }

                return(false);
            }

            if (LandClaimSystem.SharedIsUnderRaidBlock(character, objectStructure))
            {
                // the building is in an area under the raid
                errorMessage = LandClaimSystem.ErrorRaidBlockActionRestricted_Message;
                if (logErrors)
                {
                    ConstructionSystem.SharedShowCannotPlaceNotification(
                        character,
                        LandClaimSystem.ErrorRaidBlockActionRestricted_Message,
                        protoStructure);
                }

                return(false);
            }

            if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(objectStructure))
            {
                // the building is in an area under shield protection
                errorMessage = CoreStrings.ShieldProtection_ActionRestrictedBaseUnderShieldProtection;
                if (logErrors)
                {
                    LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection(
                        character);
                }

                return(false);
            }

            errorMessage = null;
            return(true);

            bool IsOwnedLand(
                Vector2Ushort startTilePosition,
                out bool hasNoFactionPermission)
            {
                var worldObjectLayoutTileOffsets = objectStructure.ProtoStaticWorldObject.Layout.TileOffsets;

                foreach (var tileOffset in worldObjectLayoutTileOffsets)
                {
                    if (!LandClaimSystem.SharedIsOwnedLand(startTilePosition.AddAndClamp(tileOffset),
                                                           character,
                                                           requireFactionPermission: true,
                                                           out hasNoFactionPermission,
                                                           out _))
                    {
                        return(false);
                    }
                }

                hasNoFactionPermission = false;
                return(true);
            }
        }
コード例 #4
0
        public static bool SharedValidateCanCharacterRelocateStructure(
            ICharacter character,
            IStaticWorldObject objectStructure,
            Vector2Ushort toPosition,
            bool logErrors)
        {
            if (!SharedIsRelocatable(objectStructure))
            {
                return(false);
            }

            if (!SharedCheckTileRequirementsForRelocation(character,
                                                          objectStructure,
                                                          toPosition,
                                                          logErrors))
            {
                return(false);
            }

            if (!(objectStructure.ProtoGameObject is IProtoObjectStructure protoStructure))
            {
                return(false);
            }

            if (objectStructure.TilePosition.TileSqrDistanceTo(toPosition)
                > MaxRelocationDistance * MaxRelocationDistance)
            {
                if (logErrors)
                {
                    ConstructionSystem.SharedShowCannotPlaceNotification(
                        character,
                        CoreStrings.Notification_TooFar,
                        protoStructure);
                }

                return(false);
            }

            var itemInHands = character.SharedGetPlayerSelectedHotbarItem();

            if (!(itemInHands.ProtoGameObject is IProtoItemToolToolbox))
            {
                return(false);
            }

            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return(true);
            }

            if (!LandClaimSystem.SharedIsOwnedLand(objectStructure.TilePosition, character, out _) ||
                !IsOwnedLand(toPosition))
            {
                // the building location or destination is in an area that is not owned by the player
                if (logErrors)
                {
                    ConstructionSystem.SharedShowCannotPlaceNotification(
                        character,
                        LandClaimSystem.ErrorNotLandOwner_Message,
                        protoStructure);
                }

                return(false);
            }

            if (LandClaimSystem.SharedIsUnderRaidBlock(character, objectStructure))
            {
                // the building is in an area under the raid
                if (logErrors)
                {
                    ConstructionSystem.SharedShowCannotPlaceNotification(
                        character,
                        LandClaimSystem.ErrorRaidBlockActionRestricted_Message,
                        protoStructure);
                }

                return(false);
            }

            if (LandClaimShieldProtectionSystem.SharedIsUnderShieldProtection(objectStructure))
            {
                // the building is in an area under shield protection
                if (logErrors)
                {
                    LandClaimShieldProtectionSystem.SharedSendNotificationActionForbiddenUnderShieldProtection(
                        character);
                }

                return(false);
            }

            return(true);

            bool IsOwnedLand(Vector2Ushort startTilePosition)
            {
                var worldObjectLayoutTileOffsets = objectStructure.ProtoStaticWorldObject.Layout.TileOffsets;

                foreach (var tileOffset in worldObjectLayoutTileOffsets)
                {
                    if (!LandClaimSystem.SharedIsOwnedLand(startTilePosition.AddAndClamp(tileOffset), character, out _))
                    {
                        return(false);
                    }
                }

                return(true);
            }
        }