示例#1
0
        private void ClientRemote_OnContainerOpened(IStaticWorldObject worldObject)
        {
            var privateState = GetPrivateState(worldObject);
            var itemsContainer = privateState.ItemsContainer;

            var soundClose = Client.UI.GetApplicationResource<SoundUI>("SoundWindowContainerClose");
            var menuWindow = WindowContainerExchange.Show(
                itemsContainer,
                soundClose: soundClose,
                isAutoClose: true);

            var character = Client.Characters.CurrentPlayerCharacter;
            InteractionCheckerSystem.SharedRegister(
                character,
                worldObject,
                finishAction: _ => menuWindow.CloseWindow());

            ClientInteractionUISystem.Register(
                worldObject,
                menuWindow,
                onMenuClosedByClient:
                () =>
                {
                    InteractionCheckerSystem.SharedUnregister(character, worldObject, isAbort: false);
                    if (!worldObject.IsDestroyed)
                    {
                        this.CallServer(_ => _.ServerRemote_OnClientInteractFinish(worldObject));
                    }
                });

            Logger.Important("Started object interaction with " + worldObject);

            ClientCurrentInteractionMenu.RegisterMenuWindow(menuWindow);
            ClientCurrentInteractionMenu.Open();
        }
示例#2
0
        protected override void ClientInteractStart(ClientObjectData data)
        {
            var worldObject = data.GameObject;
            var character   = Client.Characters.CurrentPlayerCharacter;

            var menuWindow = WindowCraftingStation.Open(this);

            ClientCurrentInteractionMenu.RegisterMenuWindow(menuWindow);

            InteractionCheckerSystem.SharedRegister(
                character,
                worldObject,
                finishAction: _ => menuWindow.CloseWindow());

            ClientInteractionUISystem.Register(
                worldObject,
                menuWindow,
                onMenuClosedByClient:
                () => InteractionCheckerSystem.SharedUnregister(
                    character,
                    worldObject,
                    isAbort: false));

            ClientCurrentInteractionMenu.Open();
        }
示例#3
0
        private void ServerRemote_OnClientInteractFinish(IStaticWorldObject worldObject)
        {
            var character = ServerRemoteContext.Character;
            if (!InteractionCheckerSystem.SharedUnregister(character, worldObject, isAbort: false))
            {
                return;
            }

            Logger.Important($"Client {character} informed that the object interaction with {worldObject} is finished");
        }
示例#4
0
        private void SharedAbortActionInternal(ICharacter character, TActionRequest request)
        {
            var characterPrivateState = PlayerCharacter.GetPrivateState(character);
            var state = characterPrivateState.CurrentActionState;

            if (!(state is TActionState actionState))
            {
                // no action or action of another state type
                return;
            }

            if (!request.Equals(actionState.Request))
            {
                // different request active
                return;
            }

            if (!state.IsCompleted)
            {
                // reset action state
                actionState.Cancel();
                // return now - because this method was just called again by SetCurrentActionState
                return;
            }

            // ensure the action state is reset
            characterPrivateState.SetCurrentActionState(null);

            Logger.Info("Action cancelled: " + state, character);

            if (state.TargetWorldObject is not null)
            {
                InteractionCheckerSystem.SharedUnregister(character, state.TargetWorldObject, isAbort: false);
            }

            if (IsClient &&
                !state.IsCancelledByServer)
            {
                Logger.Info("Sending action abort request: " + request);
                Instance.CallServer(_ => _.ServerRemote_AbortAction(request));
            }
            else if (IsServer &&
                     !ServerRemoteContext.IsRemoteCall)
            {
                Instance.CallClient(character, _ => _.ClientRemote_AbortAction(request));
                // TODO: notify other players as well
            }
        }
示例#5
0
        public void SharedOnActionCompleted(TActionState state)
        {
            var character = state.Character;
            var request   = state.Request;

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

            if (state.TargetWorldObject is not null)
            {
                InteractionCheckerSystem.SharedUnregister(character, state.TargetWorldObject, isAbort: false);
            }

            var canComplete = true;

            try
            {
                // ensure the request is still valid
                this.SharedValidateRequest(request);
            }
            catch (Exception ex)
            {
                canComplete = false;
                Logger.Warning("Exception during completed action processing: "
                               + ex.Message
                               + Environment.NewLine
                               + request);
            }

            if (canComplete)
            {
                try
                {
                    this.SharedOnActionCompletedInternal(state, character);
                }
                catch (Exception ex)
                {
                    Logger.Exception(ex, "Exception during completed action processing");
                }
            }

            PlayerCharacter.GetPrivateState(character)
            .SetCurrentActionState(null);
        }
示例#6
0
        private async void ClientInteractStartAsync(IWorldObject worldObject)
        {
            if (this.isAwaitingServerInteraction)
            {
                return;
            }

            var character = Client.Characters.CurrentPlayerCharacter;

            if (InteractionCheckerSystem.SharedGetCurrentInteraction(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 objectWindow = SharedGetProto(worldObject).ClientOpenUI(worldObject);

            if (objectWindow is null)
            {
                Logger.Info("Cannot open menu for object interaction with " + worldObject);
                this.CallServer(_ => _.ServerRemote_OnClientInteractFinish(worldObject));
                return;
            }

            Api.SafeInvoke(() => ClientMenuCreated?.Invoke(worldObject, objectWindow));
            if (!(objectWindow is IMenu))
            {
                ClientCurrentInteractionMenu.RegisterMenuWindow(objectWindow);
            }
            else
            {
                ClientCurrentInteractionMenu.TryCloseCurrentMenu();
            }

            InteractionCheckerSystem.SharedRegister(
                character,
                worldObject,
                finishAction: _ => objectWindow.CloseWindow());

            ClientInteractionUISystem.Register(
                worldObject,
                objectWindow,
                onMenuClosedByClient:
                () =>
            {
                InteractionCheckerSystem.SharedUnregister(character, worldObject, isAbort: false);
                if (!worldObject.IsDestroyed)
                {
                    ++lastRequestId;
                    this.CallServer(_ => _.ServerRemote_OnClientInteractFinish(worldObject));
                }
            });

            Logger.Info("Started object interaction with " + worldObject);
            if (objectWindow is IMenu objectMenu)
            {
                if (!objectMenu.IsOpened)
                {
                    objectMenu.Toggle();
                }
            }
            else
            {
                ClientCurrentInteractionMenu.Open();
            }
        }
示例#7
0
 public static void ServerTryAbortInteraction(ICharacter character, IWorldObject worldObject)
 {
     InteractionCheckerSystem.SharedUnregister(character, worldObject, isAbort: true);
 }