public static bool SharedIsTargetAlreadyScheduledForAnyActiveDrone( ICharacter character, Vector2Ushort worldPosition, bool logError) { foreach (var objectDrone in character.SharedGetCurrentlyControlledDrones()) { var droneTargetPosition = objectDrone.GetPublicState <DronePublicState>() .TargetObjectPosition; if (droneTargetPosition != worldPosition) { continue; } // the drone is already sent there if (logError) { if (IsServer) { Logger.Info("Drone already sent there: " + worldPosition, character); } else { CannotInteractMessageDisplay.ClientOnCannotInteract(ClientCurrentCharacterHelper.Character, Notification_DroneAlreadySent, isOutOfRange: false); } } return(true); } return(false); }
public static bool ClientTryStartDrone( IItem itemDrone, Vector2Ushort worldPosition, bool showErrorNotification) { var character = ClientCurrentCharacterHelper.Character; if (SharedIsMaxDronesToControlNumberExceeded(character, showErrorNotification) || SharedIsTargetAlreadyScheduledForAnyActiveDrone(character, worldPosition, showErrorNotification)) { return(false); } var targetObject = SharedGetCompatibleTarget(character, worldPosition, out var hasIncompatibleTarget, out var isPveActionForbidden); if (targetObject is null) { // nothing to mine there if (showErrorNotification) { if (isPveActionForbidden) { PveSystem.ClientShowNotificationActionForbidden(); } CannotInteractMessageDisplay.ClientOnCannotInteract( character, hasIncompatibleTarget ? Notification_CannotMineThat : Notification_NothingToMineThere, isOutOfRange: false); } return(false); } if (!SharedIsValidStartLocation(character, worldPosition, out var hasObstacles)) { if (showErrorNotification) { CannotInteractMessageDisplay.ClientOnCannotInteract( character, hasObstacles ? CoreStrings.Notification_ObstaclesOnTheWay : CoreStrings.Notification_TooFar, isOutOfRange: true); } return(false); } ClientDroneStartQueue.Add(itemDrone, worldPosition); return(true); }
public override void SharedUpdate(double deltaTime) { // don't invoke the base SharedUpdate implementation as we don't advance the timer here if (!ReferenceEquals(this.ItemFishingRod, this.CharacterPublicState.SelectedItem)) { // player changed the selected item this.SetCompleted(isCancelled: true); this.AbortAction(); return; } if (FishingSystem.SharedIsTooFar(this.Character, this.FishingTargetPosition)) { if (Api.IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(this.Character, CoreStrings.Notification_TooFar, isOutOfRange: true); } this.Cancel(); return; } if (this.SharedFishingSession != null && this.SharedFishingSession.IsDestroyed) { this.Complete(); } }
public static void ClientOnCannotInteract( IWorldObject worldObject, string message, bool isOutOfRange = false) { CannotInteractMessageDisplay.ClientOnCannotInteract(worldObject, message, isOutOfRange); }
public static void ClientOnCannotInteractNotOwner(IWorldObject worldObject, bool isFactionAccess) { var message = isFactionAccess ? WorldObjectAccessModeSystem.NotificationDontHaveAccess : DialogCannotSetOwners_MessageNotOwner; CannotInteractMessageDisplay.ClientOnCannotInteract(worldObject, message, isOutOfRange: false); }
public static void ClientOnCannotInteractNotOwner(IWorldObject worldObject) { CannotInteractMessageDisplay.ClientOnCannotInteract(worldObject, DialogCannotSetOwners_MessageNotOwner, isOutOfRange: false); }
public static bool SharedCheckCanInteract( ICharacter character, IDynamicWorldObject vehicle, bool writeToLog) { if (vehicle is null || vehicle.IsDestroyed) { return(false); } // it's possible to repair any vehicle within a certain distance to the character var canInteract = character.Position.DistanceSquaredTo(vehicle.Position) <= MaxDistanceForRepairAction * MaxDistanceForRepairAction; if (!canInteract) { if (writeToLog) { Logger.Warning( $"Character cannot interact with {vehicle} for repair - too far", character); if (IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(vehicle, CoreStrings.Notification_TooFar, isOutOfRange: true); } } return(false); } var physicsSpace = character.PhysicsBody.PhysicsSpace; var characterCenter = character.Position + character.PhysicsBody.CenterOffset; if (ObstacleTestHelper.SharedHasObstaclesInTheWay(characterCenter, physicsSpace, vehicle, sendDebugEvents: writeToLog)) { if (writeToLog) { Logger.Warning( $"Character cannot interact with {vehicle} for repair - obstacles in the way", character); if (IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(vehicle, CoreStrings.Notification_ObstaclesOnTheWay, isOutOfRange: true); } } return(false); } using var tempCharactersNearby = Api.Shared.GetTempList <ICharacter>(); if (IsClient) { Client.Characters.GetKnownPlayerCharacters(tempCharactersNearby); } else { Server.World.GetScopedByPlayers(vehicle, tempCharactersNearby); } foreach (var otherPlayerCharacter in tempCharactersNearby.AsList()) { if (ReferenceEquals(character, otherPlayerCharacter)) { continue; } if (PlayerCharacter.GetPublicState(otherPlayerCharacter).CurrentPublicActionState is VehicleRepairActionState.PublicState repairActionState && ReferenceEquals(repairActionState.TargetWorldObject, vehicle)) { // already repairing by another player if (!writeToLog) { return(false); } Logger.Important($"Cannot start repairing {vehicle} - already repairing by another player", character); if (IsClient) { NotificationSystem.ClientShowNotification( CoreStrings.Notification_ErrorCannotInteract, CoreStrings.Notification_ErrorObjectUsedByAnotherPlayer, NotificationColor.Bad, icon: ((IProtoVehicle)vehicle.ProtoGameObject).Icon); } return(false); } } return(true); }
protected override bool ClientItemUseFinish(ClientItemData data) { var character = ClientCurrentCharacterHelper.Character; var characterTilePosition = character.TilePosition; var mouseTilePosition = Client.Input.MousePointedTilePosition; var dronesNumberToLaunch = Api.Client.Input.IsKeyHeld(InputKey.Shift, evenIfHandled: true) ? this.MaxDronesToControl : 1; using var tempExceptDrones = Api.Shared.GetTempList <IItem>(); using var tempExceptTargets = Api.Shared.GetTempList <Vector2Ushort>(); for (var index = 0; index < dronesNumberToLaunch; index++) { var showErrorNotification = index == 0; var itemDrone = CharacterDroneControlSystem.ClientSelectNextDrone(tempExceptDrones.AsList()); if (itemDrone is null) { if (CharacterDroneControlSystem.SharedIsMaxDronesToControlNumberExceeded( character, clientShowErrorNotification: showErrorNotification)) { break; } if (showErrorNotification) { CannotInteractMessageDisplay.ClientOnCannotInteract( character, CharacterDroneControlSystem.Notification_ErrorNoDrones_Title, isOutOfRange: false); } break; } tempExceptDrones.Add(itemDrone); Vector2Ushort targetPosition; if (index == 0) { targetPosition = mouseTilePosition; var targetObject = CharacterDroneControlSystem .SharedGetCompatibleTarget(character, mouseTilePosition, out var hasIncompatibleTarget, out var isPveActionForbidden); if (targetObject is null) { if (showErrorNotification) { if (isPveActionForbidden) { PveSystem.ClientShowNotificationActionForbidden(); } CannotInteractMessageDisplay.ClientOnCannotInteract( character, hasIncompatibleTarget ? CharacterDroneControlSystem.Notification_CannotMineThat : CharacterDroneControlSystem.Notification_NothingToMineThere, isOutOfRange: false); } return(false); } if (!WorldObjectClaimSystem.SharedIsAllowInteraction(character, targetObject, showClientNotification: showErrorNotification)) { return(false); } if (CharacterDroneControlSystem.SharedIsTargetAlreadyScheduledForAnyActiveDrone( character, mouseTilePosition, logError: false)) { // already scheduled a drone mining there...try find another target of the same type targetPosition = TryGetNextTargetPosition(); if (targetPosition == default) { // no further targets CannotInteractMessageDisplay.ClientOnCannotInteract( character, CharacterDroneControlSystem.Notification_DroneAlreadySent, isOutOfRange: false); return(false); } } } else { targetPosition = TryGetNextTargetPosition(); if (targetPosition == default) { // no further targets break; } } if (!CharacterDroneControlSystem.ClientTryStartDrone(itemDrone, targetPosition, showErrorNotification: showErrorNotification)) { break; } tempExceptTargets.Add(targetPosition); } // always return false as we don't want to play any device sounds return(false); Vector2Ushort TryGetNextTargetPosition() { var targetObjectProto = CharacterDroneControlSystem .SharedGetCompatibleTarget(character, mouseTilePosition, out _, out _)? .ProtoWorldObject; if (targetObjectProto is null) { return(default);
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)); } } }
public static bool CheckCanInteractForConstruction( ICharacter character, IStaticWorldObject worldObject, bool writeToLog, bool checkRaidblock) { var characterPosition = character.Position; var canInteract = false; var staticWorldObjectProto = ProtoObjectConstructionSite.SharedGetConstructionProto(worldObject) ?? worldObject.ProtoStaticWorldObject; var startTilePosition = worldObject.TilePosition; foreach (var tileOffset in staticWorldObjectProto.Layout.TileOffsets) { var tilePosition = startTilePosition + tileOffset; if (characterPosition.DistanceSquaredTo( new Vector2D(tilePosition.X + 0.5, tilePosition.Y + 0.5)) <= MaxDistanceForBuildRepairAction * MaxDistanceForBuildRepairAction) { canInteract = true; break; } } if (!canInteract) { canInteract = CreativeModeSystem.SharedIsInCreativeMode(character); } if (!canInteract) { if (writeToLog) { Logger.Warning( $"Character cannot interact with {worldObject} for (de)construction - too far.", character); if (IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(worldObject, CoreStrings.Notification_TooFar, isOutOfRange: true); } } return(false); } if (checkRaidblock && LandClaimSystem.SharedIsUnderRaidBlock(character, worldObject)) { // the building is in an area under the raid if (writeToLog) { LandClaimSystem.SharedSendNotificationActionForbiddenUnderRaidblock(character); } return(false); } return(true); }
private void ClientRemote_OnCannotInteractNoAccess(IStaticWorldObject worldObject) { CannotInteractMessageDisplay.ClientOnCannotInteract(worldObject, NotificationDontHaveAccess, isOutOfRange: false); }
protected override void SharedValidateRequest(FishingActionRequest request) { var character = request.Character; var fishingTargetPosition = request.FishingTargetPosition; var itemRod = request.Item; if (itemRod is null || itemRod != character.SharedGetPlayerSelectedHotbarItem() || !(itemRod.ProtoItem is IProtoItemToolFishing)) { throw new Exception("The fishing rod is not selected"); } var fishingRodPublicState = itemRod.GetPublicState <ItemFishingRodPublicState>(); if (fishingRodPublicState.CurrentProtoBait is null || SharedFindBaitItem(character, fishingRodPublicState.CurrentProtoBait) is null) { // no bait available throw new Exception("There is no bait available of the required type"); } var world = IsServer ? (IWorldService)Server.World : (IWorldService)Client.World; var tile = world.GetTile(fishingTargetPosition.ToVector2Ushort()); if (!(tile.ProtoTile is IProtoTileWater protoTileWater) || !protoTileWater.IsFishingAllowed) { if (IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(character, Notification_CannotFishHere, isOutOfRange: false); } throw new Exception("Cannot fish here"); } // check obstacle objects (such as bridges) using var testResults = world.GetPhysicsSpace() .TestPoint(fishingTargetPosition, CollisionGroups.Default, sendDebugEvent: false); foreach (var testResult in testResults.AsList()) { if (testResult.PhysicsBody.AssociatedWorldObject is null) { continue; } // an obstacle found if (IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(character, Notification_CannotFishHere, isOutOfRange: false); } throw new Exception("Cannot fish here"); } if (SharedIsTooFar(character, fishingTargetPosition)) { if (IsClient) { CannotInteractMessageDisplay.ClientOnCannotInteract(character, CoreStrings.Notification_TooFar, isOutOfRange: true); } throw new Exception("Too far"); } }