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();
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #5
0
        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();
        }