/// <summary> /// Stop everything. /// </summary> public override void Stop() { if (interactionQueue?.Count > 0) { interactionQueue.Clear(); InteractionCheckerSystem.CancelCurrentInteraction(CurrentCharacter); } }
/// <summary> /// Stop everything. /// </summary> public override void Stop() { if (interactionQueue?.Count > 0) { interactionQueue.Clear(); InteractionCheckerSystem.CancelCurrentInteraction(CurrentCharacter); } readyForInteraction = true; lastActionState = null; }
protected override void CheckInteractionQueue() { if (openedLootContainer != null) { if (!openedLootContainer.SharedCanInteract(CurrentCharacter, interactionQueue[0], false)) { openedLootContainer = null; } else if (interactionQueue[0].ClientHasPrivateState) { // Take all items from container. var q = lastActionState.TargetWorldObject.GetPrivateState <LootContainerPrivateState>(); CurrentCharacter.ProtoCharacter.ClientTryTakeAllItems(CurrentCharacter, q.ItemsContainer, true); InteractionCheckerSystem.CancelCurrentInteraction(CurrentCharacter); openedLootContainer = null; } else { return; } } if (!readyForInteraction) { return; } // Remove from queue while it have object and they in our whitelist if: // - object is destroyed // - if object is container that we already have looted // - if object not IProtoObjectGatherable // - if we can not interact with object right now // - if we can not gather anything from object while (interactionQueue.Count != 0 && EnabledEntityList.Contains(interactionQueue[0].ProtoGameObject) && (interactionQueue[0].IsDestroyed || (lastActionState?.TargetWorldObject == interactionQueue[0] && lastActionState.IsCompleted && !lastActionState.IsCancelled && !lastActionState.IsCancelledByServer) || !(interactionQueue[0].ProtoGameObject is IProtoObjectGatherable protoGatherable) || !protoGatherable.SharedCanInteract(CurrentCharacter, interactionQueue[0], false) || !protoGatherable.SharedIsCanGather(interactionQueue[0]))) { interactionQueue.RemoveAt(0); } if (interactionQueue.Count == 0) { return; } var request = new WorldActionRequest(CurrentCharacter, interactionQueue[0]); GatheringSystem.Instance.SharedStartAction(request); }
private bool ServerRemote_OnClientInteractStart(IWorldObject 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.SharedRegister( character, worldObject, finishAction: isAbort => { if (worldObject.IsDestroyed) { return; } this.ServerFinishInteractionInternal(character, worldObject); if (isAbort) { // notify client this.CallClient(character, _ => this.ClientRemote_FinishInteraction(worldObject)); } }); Logger.Info($"Started object interaction with {worldObject} for {character}"); return(true); }
protected override void CheckInteractionQueue() { if (openedLootContainer != null) { if (InteractionCheckerSystem.SharedHasInteraction(CurrentCharacter, openedLootContainer, true)) { // We get container private state, now take all items from container. var q = openedLootContainer.GetPrivateState <LootContainerPrivateState>(); var result = CurrentCharacter.ProtoCharacter.ClientTryTakeAllItems(CurrentCharacter, q.ItemsContainer, true); if (result.MovedItems.Count > 0) { NotificationSystem.ClientShowItemsNotification( itemsChangedCount: result.MovedItems .GroupBy(p => p.Key.ProtoItem) .ToDictionary(p => p.Key, p => p.Sum(v => v.Value))); } InteractionCheckerSystem.CancelCurrentInteraction(CurrentCharacter); } else if (openedLootContainer.ProtoWorldObject .SharedCanInteract(CurrentCharacter, openedLootContainer, false)) { // Waiting for container private state from server. return; } openedLootContainer = null; readyForInteraction = true; } if (!readyForInteraction) { return; } // Remove from queue while it have object and they in our whitelist if: // - object is destroyed // - if object is container that we already have looted // - if object not IProtoObjectGatherable // - if we can not interact with object right now // - if we can not gather anything from object while (interactionQueue.Count != 0 && EnabledEntityList.Contains(interactionQueue[0].ProtoGameObject) && (interactionQueue[0].IsDestroyed || (lastActionState != null && lastActionState.TargetWorldObject == interactionQueue[0] && lastActionState.IsCompleted && !lastActionState.IsCancelled && !lastActionState.IsCancelledByServer) || !(interactionQueue[0].ProtoGameObject is IProtoObjectGatherable protoGatherable) || !protoGatherable.SharedCanInteract(CurrentCharacter, interactionQueue[0], false) || !protoGatherable.SharedIsCanGather(interactionQueue[0]))) { interactionQueue.RemoveAt(0); } if (interactionQueue.Count == 0) { return; } var request = new WorldActionRequest(CurrentCharacter, interactionQueue[0]); GatheringSystem.Instance.SharedStartAction(request); }
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); }