protected override void ClientInteractStart(ClientObjectData data) { var worldObject = data.GameObject; var character = Client.Characters.CurrentPlayerCharacter; var menuWindow = WindowCraftingStation.Open(this); ClientCurrentInteractionMenu.RegisterMenuWindow(menuWindow); InteractionCheckerSystem.Register( character, worldObject, finishAction: _ => menuWindow.CloseWindow()); ClientInteractionUISystem.Register( worldObject, menuWindow, onMenuClosedByClient: () => InteractionCheckerSystem.Unregister( character, worldObject, isAbort: false)); ClientCurrentInteractionMenu.Open(); }
private bool ServerRemote_OnClientInteractStart(IStaticWorldObject worldObject) { var character = ServerRemoteContext.Character; if (worldObject == null || !worldObject.ProtoWorldObject.SharedCanInteract(character, worldObject, writeToLog: true)) { // player is too far from the world object or world object is destroyed return(false); } InteractionCheckerSystem.CancelCurrentInteraction(character); var proto = SharedGetProto(worldObject); proto.ServerOnClientInteract(character, worldObject); if (proto.IsAutoEnterPrivateScopeOnInteraction) { // enter private scope - containers will be sent to the player character Server.World.EnterPrivateScope(character, worldObject); } // register private scope exit on interaction cancel InteractionCheckerSystem.Register( character, worldObject, finishAction: isAbort => { if (worldObject.IsDestroyed) { return; } this.ServerFinishInteractionInternal(character, worldObject); if (isAbort) { // notify client this.CallClient(character, _ => this.ClientRemote_FinishInteraction(worldObject)); } }); Logger.Important($"Started object interaction with {worldObject} for {character}"); return(true); }
public bool SharedStartAction(TActionRequest request) { if (request == null) { return(false); } var character = request.Character; var characterPrivateState = PlayerCharacter.GetPrivateState(character); if (characterPrivateState.CurrentActionState is TActionState existingState && this.SharedIsSameAction(existingState, request)) { // the same action is already in process Logger.Info( $"Action cannot be started: {request} - already performing the same action", character); return(false); } try { this.SharedValidateRequest(request); } catch (Exception ex) { Logger.Info( $"Action cannot be started: {request} the request is not valid: {Environment.NewLine}{ex.Message}", character); return(false); } var state = this.SharedTryCreateState(request); if (state == null) { Logger.Info( "Action cannot be started: " + request, character); return(false); } state.Request = request; InteractionCheckerSystem.CancelCurrentInteraction(character); characterPrivateState.SetCurrentActionState(state); Logger.Info("Action started: " + request, character); if (IsClient) { this.ClientOnStartActionCompleted(request, state); } if (state.TargetWorldObject != null) { InteractionCheckerSystem.Register( character, state.TargetWorldObject, finishAction: isAbort => { if (!isAbort) { return; } Logger.Warning( $"InteractionCheckerSystem interaction check failed - cancelling \"{this.Name}\" action: {state}", character); this.SharedAbortActionInternal(character, state.Request); }); } return(true); }
public bool ServerGather(IStaticWorldObject worldObject, ICharacter character) { var privateState = GetPrivateState(worldObject); if (privateState.IsDropListSpawned) { // this loot container was already search - drop list was already spawned return(true); } // spawn items accordingly to the droplist privateState.IsDropListSpawned = true; var lootDroplist = this.ServerGetLootDroplist(worldObject); var dropItemContext = new DropItemContext(character, worldObject); CreateItemResult dropItemResult; var attemptRemains = 100; var itemsContainer = privateState.ItemsContainer; do { dropItemResult = lootDroplist.TryDropToContainer(itemsContainer, dropItemContext); } // ensure that at least something is spawned... // perhaps that's not a good idea, but we have an attempts limit while (dropItemResult.TotalCreatedCount == 0 && --attemptRemains > 0); Server.Items.SetSlotsCount(itemsContainer, (byte)itemsContainer.OccupiedSlotsCount); character.ServerAddSkillExperience <SkillSearching>(SkillSearching.ExperienceAddWhenSearching); Server.World.EnterPrivateScope(character, worldObject); // register private scope exit on interaction cancel InteractionCheckerSystem.Register( character, worldObject, finishAction: isAbort => { if (worldObject.IsDestroyed) { return; } Server.World.ExitPrivateScope(character, worldObject); if (isAbort) { // notify client this.CallClient(character, _ => _.ClientRemote_FinishInteraction(worldObject)); } if (this.IsAutoDestroyWhenLooted) { // container was closed - destroy it Server.World.DestroyObject(worldObject); } }); Logger.Important($"Started object interaction with {worldObject} for {character}"); this.CallClient(character, _ => _.ClientRemote_OnContainerOpened(worldObject)); return(true); }
private async void ClientInteractStartAsync(IStaticWorldObject worldObject) { if (this.isAwaitingServerInteraction) { return; } var character = Client.Characters.CurrentPlayerCharacter; if (InteractionCheckerSystem.GetCurrentInteraction(character) == worldObject) { // already interacting with this object return; } this.isAwaitingServerInteraction = true; try { var requestId = ++lastRequestId; var isOpened = await this.CallServer(_ => _.ServerRemote_OnClientInteractStart(worldObject)); if (!isOpened || requestId != lastRequestId) { return; } } finally { this.isAwaitingServerInteraction = false; } var menuWindow = SharedGetProto(worldObject).ClientOpenUI(worldObject); if (menuWindow == null) { Logger.Important("Cannot open menu for object interaction with " + worldObject); this.CallServer(_ => _.ServerRemote_OnClientInteractFinish(worldObject)); return; } ClientCurrentInteractionMenu.RegisterMenuWindow(menuWindow); InteractionCheckerSystem.Register( character, worldObject, finishAction: _ => menuWindow.CloseWindow()); ClientInteractionUISystem.Register( worldObject, menuWindow, onMenuClosedByClient: () => { InteractionCheckerSystem.Unregister(character, worldObject, isAbort: false); if (!worldObject.IsDestroyed) { ++lastRequestId; this.CallServer(_ => _.ServerRemote_OnClientInteractFinish(worldObject)); } }); Logger.Important("Started object interaction with " + worldObject); ClientCurrentInteractionMenu.Open(); }