public static void ClientToggleConstructionMenu()
        {
            if (ClientCloseConstructionMenu())
            {
                // just closed the construction menu
                return;
            }

            if (ClientCurrentCharacterHelper.PublicState.CurrentVehicle is not null)
            {
                Logger.Important("Construction menu is not accessible while in a vehicle");
                return;
            }

            WindowConstructionMenu.Open(
                onStructureProtoSelected:
                selectedProtoStructure =>
            {
                ClientEnsureConstructionToolIsSelected();
                currentSelectedProtoConstruction = selectedProtoStructure;

                componentObjectPlacementHelper = Client.Scene
                                                 .CreateSceneObject("ConstructionHelper")
                                                 .AddComponent <ClientComponentObjectPlacementHelper>();

                // repeat placement for held button only for walls, floor and farms
                var isRepeatCallbackIfHeld = selectedProtoStructure.IsRepeatPlacement;

                componentObjectPlacementHelper
                .Setup(selectedProtoStructure,
                       isCancelable: true,
                       isRepeatCallbackIfHeld: isRepeatCallbackIfHeld,
                       isDrawConstructionGrid: true,
                       isBlockingInput: true,
                       validateCanPlaceCallback: ClientValidateCanBuild,
                       placeSelectedCallback: ClientConstructionPlaceSelectedCallback,
                       delayRemainsSeconds: 0.4);
            },
                onClosed: OnStructureSelectWindowOpenedOrClosed);

            OnStructureSelectWindowOpenedOrClosed();
        }
        public static void ClientToggleConstructionMenu()
        {
            if (ClientCloseConstructionMenu())
            {
                // just closed the construction menu
                return;
            }

            WindowConstructionMenu.Open(
                onStructureProtoSelected:
                selectedProtoStructure =>
            {
                ClientEnsureConstructionToolIsSelected();
                currentSelectedProtoConstruction = selectedProtoStructure;

                componentObjectPlacementHelper = Client.Scene
                                                 .CreateSceneObject(
                    "ConstructionHelper",
                    Vector2D.Zero)
                                                 .AddComponent <
                    ClientComponentObjectPlacementHelper>();

                // repeat placement for held button only for walls, floor and farms
                var isRepeatCallbackIfHeld = selectedProtoStructure is IProtoObjectWall ||
                                             selectedProtoStructure is IProtoObjectFloor ||
                                             selectedProtoStructure is IProtoObjectFarm;

                componentObjectPlacementHelper
                .Setup(selectedProtoStructure,
                       isCancelable: true,
                       isRepeatCallbackIfHeld: isRepeatCallbackIfHeld,
                       isDrawConstructionGrid: true,
                       isBlockingInput: true,
                       validateCanPlaceCallback: ClientValidateCanBuild,
                       placeSelectedCallback: ClientConstructionPlaceSelectedCallback,
                       delayRemainsSeconds: 0.4);
            },
                onClosed: OnStructureSelectWindowOpenedOrClosed);

            OnStructureSelectWindowOpenedOrClosed();
        }
        public static void Setup(IItem item, bool isSelected)
        {
            if (!isSelected)
            {
                item = null;
            }

            if (currentSelectedSeedItem == item)
            {
                return;
            }

            currentSelectedSeedItem  = item;
            currentSelectedProtoSeed = currentSelectedSeedItem?.ProtoItem as IProtoItemSeed;
            if (currentSelectedProtoSeed == null)
            {
                // seed is not selected anymore
                blueprintComponent?.SceneObject.Destroy();
                blueprintComponent = null;
                return;
            }

            // seed is selected - create blueprint component
            if (blueprintComponent == null)
            {
                blueprintComponent = Client.Scene.CreateSceneObject("Seed placer helper")
                                     .AddComponent <ClientComponentObjectPlacementHelper>();
            }

            blueprintComponent.Setup(
                protoStaticWorldObject: currentSelectedProtoSeed.ObjectPlantProto,
                isCancelable: false,
                isRepeatCallbackIfHeld: true,
                isDrawConstructionGrid: true,
                isBlockingInput: false,
                validateCanPlaceCallback: OnValidate,
                placeSelectedCallback: OnPlaceSelected,
                maxDistance: MaxSeedPlacementDistance);
        }
 public static void ClientDisableConstructionPlacement()
 {
     componentObjectPlacementHelper?.SceneObject.Destroy();
     componentObjectPlacementHelper = null;
 }
Example #5
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,
                                                   requireFactionPermission: true,
                                                   out var hasNoFactionPermission,
                                                   out _))
            {
                // the building location or destination is in an area that is not owned by the player
                SharedShowCannotRelocateNotification(
                    character,
                    protoStructure,
                    hasNoFactionPermission);
                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 string errorMessage,
                out bool canPlace,
                out bool isTooFar)
            {
                if (tilePosition == objectStructure.TilePosition)
                {
                    canPlace     = true;
                    isTooFar     = false;
                    errorMessage = null;
                    return;
                }

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

                if (!SharedValidateCanCharacterRelocateStructure(character,
                                                                 objectStructure,
                                                                 tilePosition,
                                                                 out errorMessage,
                                                                 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);
                    }

                    errorMessage = CoreStrings.Notification_ObstaclesOnTheWay;
                    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));
                }
            }
        }