private static void ClientValidateCanBuild( Vector2Ushort tilePosition, bool logErrors, out string errorMessage, out bool canPlace, out bool isTooFar) { var protoStructure = currentSelectedProtoConstruction; if (Client.World.GetTile(tilePosition) .StaticObjects .Any(so => so.ProtoStaticWorldObject == protoStructure || ProtoObjectConstructionSite.SharedIsConstructionOf(so, protoStructure))) { // this building is already built here canPlace = false; isTooFar = false; errorMessage = null; return; } var character = Client.Characters.CurrentPlayerCharacter; if (!protoStructure.CheckTileRequirements( tilePosition, character, errorCodeOrMessage: out var errorCodeOrMessage, logErrors: logErrors)) { // time requirements are not valid canPlace = false; isTooFar = false; errorMessage = ConstructionSystem.SharedConvertCodeOrErrorMessageToString(errorCodeOrMessage); return; } errorMessage = null; var configBuild = protoStructure.ConfigBuild; if (configBuild.CheckStageCanBeBuilt(character)) { canPlace = true; isTooFar = SharedIsTooFarToPlace(protoStructure, tilePosition, character, logErrors); return; } // not enough items to build the stage // close construction menu ClientCloseConstructionMenu(); canPlace = false; isTooFar = false; }
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 var errorCodeOrMessage, logErrors: logErrors)) { // time requirements are not valid canPlace = false; isTooFar = false; errorMessage = ConstructionSystem.SharedConvertCodeOrErrorMessageToString(errorCodeOrMessage); return; } if (!SharedValidateCanCharacterRelocateStructure(character, objectStructure, tilePosition, out errorCodeOrMessage, logErrors: logErrors)) { canPlace = true; isTooFar = true; errorMessage = ConstructionSystem.SharedConvertCodeOrErrorMessageToString(errorCodeOrMessage); 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; errorMessage = null; } 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)); } } }