protected BaseUserControlWithWindow ClientOpenUI(ClientObjectData data) { var worldObject = data.GameObject; var publicState = data.SyncPublicState; if (worldObject.ClientHasPrivateState && !Client.Input.IsKeyHeld(InputKey.Alt)) { // open admin window return(WindowTradingStationAdmin.Open( new ViewModelWindowTradingStationAdmin(worldObject, data.SyncPrivateState, publicState))); } // open user window (if has any lots) if (publicState.Lots.Any(l => l.State != TradingStationLotState.Disabled)) { return(WindowTradingStationUser.Open( new ViewModelWindowTradingStationUser(worldObject, publicState))); } CannotInteractMessageDisplay.ShowOn(worldObject, publicState.Mode == TradingStationMode.StationSelling ? NotificationNothingForSale : NotificationNoTradingLots); return(null); }
protected override async void ClientInteractStart(ClientObjectData data) { var bedObject = data.GameObject; var (isSuccess, name) = await this.CallServer(_ => _.ServerRemote_GetBedOwnerName(bedObject)); if (!isSuccess) { ClientOnCannotInteract(bedObject, CoreStrings.Notification_TooFar, isOutOfRange: true); return; } var isFree = string.IsNullOrEmpty(name); if (isFree) { DialogWindow.ShowDialog( DialogClaimBed_Title, DialogClaimBed_Message, okText: CoreStrings.Yes, okAction: () => this.ClientMakeCurrentBed(bedObject), hideCancelButton: false); return; } var message = name == Client.Characters.CurrentPlayerCharacter.Name ? MessageBedBelongsToCurrentPlayer : string.Format(MessageFormatBedBelongsToAnotherPlayer, name); CannotInteractMessageDisplay.ShowOn(bedObject, message); this.SoundPresetObject.PlaySound(ObjectSound.InteractSuccess); }
protected override void SharedValidateRequest(WorldActionRequest request) { var worldObject = request.WorldObject; if (!(worldObject?.ProtoWorldObject is IProtoObjectGatherable)) { throw new Exception("The world object must be gatherable"); } if (!worldObject.ProtoWorldObject.SharedCanInteract(request.Character, worldObject, true)) { throw new Exception("Cannot interact with " + worldObject); } if (!(worldObject.ProtoGameObject is IProtoObjectGatherable protoGatherable)) { throw new Exception("Not a gatherable resource: " + worldObject); } if (!protoGatherable.SharedIsCanGather((IStaticWorldObject)worldObject)) { Logger.Warning("Cannot gather now: " + worldObject, request.Character); if (Api.IsClient) { CannotInteractMessageDisplay.ShowOn(worldObject, NotificationNothingToHarvestYet); worldObject.ProtoWorldObject.SharedGetObjectSoundPreset() .PlaySound(ObjectSound.InteractFail); } throw new Exception("Cannot gather now: " + worldObject); } }
public virtual void ClientOnCannotInteract( TWorldObject worldObject, string message, bool isOutOfRange = false) { CannotInteractMessageDisplay.ShowOn(worldObject, message); var soundKey = isOutOfRange ? ObjectSound.InteractOutOfRange : ObjectSound.InteractFail; worldObject.ProtoWorldObject.SharedGetObjectSoundPreset() .PlaySound(soundKey); }
public static bool SharedCheckCanInteract( ICharacter character, IWorldObject worldObject, bool writeToLog) { if (worldObject == null || worldObject.IsDestroyed) { return(false); } // Can deconstruct only if the character can contact directly // with the object click area (if object has the click area) // or with the object collider (if object don't has the click area). var isObjectHasClickArea = worldObject.PhysicsBody .Shapes .Any(s => s.CollisionGroup == CollisionGroups.ClickArea); var result = worldObject.ProtoWorldObject.SharedIsInsideCharacterInteractionArea( character, worldObject, writeToLog: false, requiredCollisionGroup: isObjectHasClickArea ? CollisionGroups.ClickArea : CollisionGroups .DefaultWithCollisionToInteractionArea); if (result) { return(true); } if (writeToLog) { Logger.Warning( $"Cannot deconstruct - {character} cannot interact with the {worldObject} - there is no direct (physics) line of sight between them (the object click area or static/dynamic colliders must be inside the character interaction area)"); if (IsClient) { CannotInteractMessageDisplay.ShowOn(worldObject, CoreStrings.Notification_TooFar); worldObject.ProtoWorldObject.SharedGetObjectSoundPreset() .PlaySound(ObjectSound.InteractOutOfRange); } } return(false); }
protected override GatheringActionState SharedTryCreateState(WorldActionRequest request) { var worldObject = request.WorldObject; var character = request.Character; var staticWorldObject = (IStaticWorldObject)worldObject; if (!(worldObject.ProtoGameObject is IProtoObjectGatherable protoGatherable)) { throw new Exception("Not a gatherable resource: " + worldObject); } if (!protoGatherable.SharedIsCanGather(staticWorldObject)) { Logger.Warning("Cannot gather now: " + worldObject, character); if (Api.IsClient) { CannotInteractMessageDisplay.ShowOn(worldObject, NotificationNothingToHarvestYet); worldObject.ProtoWorldObject.SharedGetObjectSoundPreset() .PlaySound(ObjectSound.InteractFail); } return(null); } var durationSeconds = protoGatherable.DurationGatheringSeconds; var multiplier = protoGatherable.GetGatheringSpeedMultiplier(staticWorldObject, character); durationSeconds /= multiplier; if (CreativeModeSystem.SharedIsInCreativeMode(character)) { durationSeconds = 0.1; } return(new GatheringActionState( character, staticWorldObject, durationSeconds)); }
protected override void SharedValidateRequest(WorldActionRequest request) { var worldObject = (IStaticWorldObject)request.WorldObject; if (!(worldObject?.ProtoWorldObject is IProtoObjectGatherable protoGatherable)) { throw new Exception("The world object must be gatherable"); } if (!worldObject.ProtoWorldObject.SharedCanInteract(request.Character, worldObject, true)) { throw new Exception("Cannot interact with " + worldObject); } if (!WorldObjectClaimSystem.SharedIsAllowInteraction(request.Character, worldObject, showClientNotification: true)) { throw new Exception("Locked for another player: " + worldObject); } if (protoGatherable.SharedIsCanGather(worldObject)) { return; } Logger.Warning("Cannot gather now: " + worldObject, request.Character); if (Api.IsClient) { CannotInteractMessageDisplay.ShowOn(worldObject, NotificationNothingToHarvestYet); worldObject.ProtoWorldObject.SharedGetObjectSoundPreset() .PlaySound(ObjectSound.InteractFail); } throw new Exception("Cannot gather now: " + worldObject); }
public static bool SharedCheckCanInteract( ICharacter character, IWorldObject worldObject, bool writeToLog) { if (worldObject == null || worldObject.IsDestroyed) { return(false); } // Can build/repair only if the character can contact directly // with the object click area (if object has the click area) // or with the object collider (if object don't has the click area). var isObjectHasClickArea = worldObject.PhysicsBody.Shapes.Any(s => s.CollisionGroup == CollisionGroups.ClickArea); var result = worldObject.ProtoWorldObject.SharedIsInsideCharacterInteractionArea( character, worldObject, writeToLog: false, requiredCollisionGroup: isObjectHasClickArea ? CollisionGroups.ClickArea : CollisionGroups .DefaultWithCollisionToInteractionArea); if (!result) { if (writeToLog) { Logger.Warning( $"Cannot build/repair - {character} cannot interact with the {worldObject} - there is no direct (physics) line of sight between them (the object click area or static/dynamic colliders must be inside the character interaction area)"); if (IsClient) { CannotInteractMessageDisplay.ShowOn(worldObject, CoreStrings.Notification_TooFar); worldObject.ProtoWorldObject.SharedGetObjectSoundPreset() .PlaySound(ObjectSound.InteractOutOfRange); } } return(false); } if (worldObject is IStaticWorldObject staticWorldObject) { // ensure the building is not in an area under the raid var world = IsClient ? (IWorldService)Client.World : Server.World; var protoStaticWorldObject = staticWorldObject.ProtoStaticWorldObject; var validatorNoRaid = LandClaimSystem.ValidatorNoRaid; foreach (var tileOffset in protoStaticWorldObject.Layout.TileOffsets) { var occupiedTile = world.GetTile( worldObject.TilePosition.X + tileOffset.X, worldObject.TilePosition.Y + tileOffset.Y, logOutOfBounds: false); if (!occupiedTile.IsValidTile) { continue; } if (validatorNoRaid.Function( new ConstructionTileRequirements.Context( occupiedTile, character, protoStaticWorldObject, tileOffset))) { continue; } // raid is under way - cannot build/repair SharedShowCannotBuildNotification( character, validatorNoRaid.ErrorMessage, protoStaticWorldObject); return(false); } } return(true); }