/// <summary>
 /// Stop everything.
 /// </summary>
 public override void Stop()
 {
     if (interactionQueue?.Count > 0)
     {
         interactionQueue.Clear();
         InteractionCheckerSystem.SharedAbortCurrentInteraction(CurrentCharacter);
     }
 }
예제 #2
0
 /// <summary>
 /// Stop everything.
 /// </summary>
 public override void Stop()
 {
     if (interactionQueue?.Count > 0)
     {
         interactionQueue.Clear();
         InteractionCheckerSystem.SharedAbortCurrentInteraction(CurrentCharacter);
     }
     readyForInteraction = true;
     lastActionState     = null;
     openedLootContainer = null;
 }
예제 #3
0
        private bool ServerRemote_OnClientInteractStart(IWorldObject worldObject)
        {
            var character = ServerRemoteContext.Character;

            if (worldObject is null ||
                !worldObject.ProtoWorldObject.SharedCanInteract(character, worldObject, writeToLog: true))
            {
                // player is too far from the world object or world object is destroyed
                return(false);
            }

            InteractionCheckerSystem.SharedAbortCurrentInteraction(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);
        }
예제 #4
0
        public bool SharedStartAction(TActionRequest request)
        {
            if (request is 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 is null)
            {
                Logger.Info(
                    "Action cannot be started: " + request,
                    character);
                return(false);
            }

            state.Request = request;
            InteractionCheckerSystem.SharedAbortCurrentInteraction(character);
            characterPrivateState.SetCurrentActionState(state);

            Logger.Info("Action started: " + request, character);

            if (IsClient)
            {
                this.ClientOnStartActionCompleted(request, state);
            }

            if (state.TargetWorldObject is not null)
            {
                InteractionCheckerSystem.SharedRegister(
                    character,
                    state.TargetWorldObject,
                    finishAction: isAbort =>
                {
                    if (!isAbort)
                    {
                        return;
                    }

                    Logger.Warning(
                        $"InteractionCheckerSystem interaction check failed - cancelling \"{this.ShortId}\" action: {state}",
                        character);
                    this.SharedAbortActionInternal(character, state.Request);
                });
            }

            return(true);
        }
예제 #5
0
        protected override void CheckInteractionQueue()
        {
            if (openedLootContainer != null)
            {
                if (InteractionCheckerSystem.SharedIsInteracting(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.SharedAbortCurrentInteraction(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 ||
                    !TestObject(interactionQueue[0]) ||
                    (lastActionState != null &&
                     lastActionState.TargetWorldObject == interactionQueue[0] &&
                     lastActionState.IsCompleted &&
                     !lastActionState.IsCancelled &&
                     !lastActionState.IsCancelledByServer)))
            {
                interactionQueue.RemoveAt(0);
            }

            if (interactionQueue.Count == 0)
            {
                return;
            }

            var request = new WorldActionRequest(CurrentCharacter, interactionQueue[0]);

            GatheringSystem.Instance.SharedStartAction(request);
        }