Пример #1
0
    public void ServerPerformInteraction(PositionalHandApply interaction)
    {
        if (Validations.HasItemTrait(interaction.HandObject, CommonTraits.Instance.Wrench))
        {
            SoundManager.PlayNetworkedAtPos("Wrench", interaction.WorldPositionTarget, 1f);
            Spawn.ServerPrefab("Metal", interaction.WorldPositionTarget.RoundToInt(), transform.parent, count: 1,
                               scatterRadius: Spawn.DefaultScatterRadius, cancelIfImpassable: true);
            Despawn.ServerSingle(gameObject);

            return;
        }

        var progressFinishAction = new ProgressCompleteAction(() =>
        {
            Chat.AddExamineMsgFromServer(interaction.Performer,
                                         "You assemble a rack.");
            Spawn.ServerPrefab(rackPrefab, interaction.WorldPositionTarget.RoundToInt(),
                               interaction.Performer.transform.parent);
            var handObj = interaction.HandObject;
            Inventory.ServerDespawn(interaction.HandSlot);
        }
                                                              );

        var bar = UIManager.ServerStartProgress(ProgressAction.Construction, interaction.WorldPositionTarget.RoundToInt(),
                                                5f, progressFinishAction, interaction.Performer);

        if (bar != null)
        {
            Chat.AddExamineMsgFromServer(interaction.Performer, "You start constructing a rack...");
        }
    }
Пример #2
0
    //Server only
    public void ProcessDeconstructRequest(GameObject player, GameObject matrixRoot, TileType tileType,
                                          Vector3 cellPos, Vector3 worldCellPos)
    {
        //TODO: This should probably be refactored to use IF2 so validations can be used, we shouldn't need
        // a custom net message for deconstruction

        //Process Wall deconstruct request:
        if (tileType == TileType.Wall)
        {
            //Set up the action to be invoked when progress bar finishes:
            var progressFinishAction = new ProgressCompleteAction(
                () =>
            {
                SoundManager.PlayNetworkedAtPos("Weld", worldCellPos, 0.8f);
                CraftingManager.Deconstruction.TryTileDeconstruct(
                    matrixRoot.GetComponent <TileChangeManager>(), tileType, cellPos, worldCellPos);
            }
                );

            //Start the progress bar:
            var bar = UIManager.ServerStartProgress(ProgressAction.Construction, Vector3Int.RoundToInt(worldCellPos),
                                                    10f, progressFinishAction, player);
            if (bar != null)
            {
                SoundManager.PlayNetworkedAtPos("Weld", worldCellPos, Random.Range(0.9f, 1.1f));
            }
        }
    }
Пример #3
0
    public void ServerPerformInteraction(PositionalHandApply interaction)
    {
        if (Validations.IsTool(interaction.HandObject, ToolType.Wrench))
        {
            SoundManager.PlayNetworkedAtPos("Wrench", interaction.WorldPositionTarget, 1f);
            ObjectFactory.SpawnMetal(1, interaction.WorldPositionTarget.To2Int(), parent: transform.parent);
            PoolManager.PoolNetworkDestroy(gameObject);

            return;
        }

        var progressFinishAction = new ProgressCompleteAction(() =>
        {
            Chat.AddExamineMsgFromServer(interaction.Performer,
                                         "You assemble a rack.");
            PoolManager.PoolNetworkInstantiate(rackPrefab, interaction.WorldPositionTarget.RoundToInt(),
                                               interaction.Performer.transform.parent);
            var handObj = interaction.HandObject;
            var slot    = InventoryManager.GetSlotFromOriginatorHand(interaction.Performer,
                                                                     interaction.HandSlot.equipSlot);
            handObj.GetComponent <Pickupable>().DisappearObject(slot);
        }
                                                              );

        var bar = UIManager.ServerStartProgress(ProgressAction.Construction, interaction.WorldPositionTarget.RoundToInt(),
                                                5f, progressFinishAction, interaction.Performer);

        if (bar != null)
        {
            Chat.AddExamineMsgFromServer(interaction.Performer, "You start constructing a rack...");
        }
    }
Пример #4
0
    public void ServerPerformInteraction(PositionalHandApply interaction)
    {
        //server is performing server-side logic for the interaction
        //do the mopping
        var progressFinishAction = new ProgressCompleteAction(() => CleanTile(interaction.WorldPositionTarget));

        //Start the progress bar:
        UIManager.ServerStartProgress(ProgressAction.Mop, interaction.WorldPositionTarget.RoundToInt(),
                                      5f, progressFinishAction, interaction.Performer);
    }
Пример #5
0
    /// <summary>
    /// Performs common tool usage logic and also sends start / end action messages, and invokes a callback on success.
    /// </summary>
    /// <param name="performer">player using the tool</param>
    /// <param name="tool">tool being used</param>
    /// <param name="worldTilePos">tile position the action is being performed on</param>
    /// <param name="seconds">seconds taken to perform the action, 0 if it should be instant</param>
    /// <param name="performerStartActionMessage">message to show performer when action begins.</param>
    /// <param name="othersStartActionMessage">message to show others when action begins.</param>
    /// <param name="performerFinishActionMessage">message to show performer when action completes successfully.</param>
    /// <param name="othersFinishActionMessage">message to show others when action completes successfully.</param>
    /// <param name="onSuccessfulCompletion">called when action is completed</param>
    public static void ServerUseToolWithActionMessages(GameObject performer, GameObject tool, Vector2 worldTilePos,
                                                       float seconds, string performerStartActionMessage, string othersStartActionMessage, string performerFinishActionMessage,
                                                       string othersFinishActionMessage, Action onSuccessfulCompletion)
    {
        Chat.AddActionMsgToChat(performer, performerStartActionMessage,
                                othersStartActionMessage);
        var progressFinishAction = new ProgressCompleteAction(() =>
        {
            Chat.AddActionMsgToChat(performer, performerFinishActionMessage,
                                    othersFinishActionMessage);
            onSuccessfulCompletion.Invoke();
        });

        ServerUseTool(performer, tool, worldTilePos, seconds, progressFinishAction);
    }
Пример #6
0
    public void CmdRequestCPR(GameObject rescuer, GameObject cardiacArrestPlayer)
    {
        //TODO: Probably refactor this to IF2

        var cardiacArrestPlayerRegister = cardiacArrestPlayer.GetComponent <RegisterPlayer>();

        var progressFinishAction = new ProgressCompleteAction(() => DoCPR(rescuer, cardiacArrestPlayer));

        var bar = UIManager.ServerStartProgress(ProgressAction.CPR, cardiacArrestPlayerRegister.WorldPosition, 5f, progressFinishAction,
                                                rescuer);

        if (bar != null)
        {
            Chat.AddActionMsgToChat(rescuer, $"You begin performing CPR on {cardiacArrestPlayer.Player()?.Name}.",
                                    $"{rescuer.Player()?.Name} is trying to perform CPR on {cardiacArrestPlayer.Player()?.Name}.");
        }
    }
Пример #7
0
    public void ServerPerformInteraction(PositionalHandApply interaction)
    {
        //server is performing server-side logic for the interaction
        //do the mining
        var progressFinishAction = new ProgressCompleteAction(() => FinishMine(interaction));

        //Start the progress bar:
        //technically pickaxe is deconstruction, so it would interrupt any construction / deconstruction being done
        //on that tile
        var bar = UIManager.ServerStartProgress(ProgressAction.Construction, interaction.WorldPositionTarget.RoundToInt(),
                                                5f, progressFinishAction, interaction.Performer);

        if (bar != null)
        {
            SoundManager.PlayNetworkedAtPos("pickaxe#", interaction.WorldPositionTarget);
        }
    }
Пример #8
0
    public override IEnumerator Process()
    {
        yield return(WaitFor(PlayerToUncuff));

        GameObject actor          = SentByPlayer.GameObject;
        GameObject playerToUncuff = NetworkObject;

        var restraint = playerToUncuff.GetComponent <PlayerNetworkActions>().Inventory[EquipSlot.handcuffs]?.Item?.GetComponent <Restraint>();

        if (restraint)
        {
            var finishProgressAction = new ProgressCompleteAction(() =>
                                                                  playerToUncuff.GetComponent <PlayerMove>().RequestUncuff(actor));
            UIManager.ServerStartProgress(ProgressAction.Uncuff, actor.transform.position, restraint.RemoveTime,
                                          finishProgressAction, actor);
        }
    }
    public void CmdDisrobe(GameObject toDisrobe)
    {
        if (!Validations.CanApply(playerScript, toDisrobe, NetworkSide.Server))
        {
            return;
        }
        //only allowed if this player is an observer of the player to disrobe
        var itemStorage = toDisrobe.GetComponent <ItemStorage>();

        if (itemStorage == null)
        {
            return;
        }

        //are we an observer of the player to disrobe?
        if (!itemStorage.ServerIsObserver(gameObject))
        {
            return;
        }

        //disrobe each slot, taking .2s per each occupied slot
        //calculate time
        var occupiedSlots = itemStorage.GetItemSlots().Count(slot => slot.NamedSlot != NamedSlot.handcuffs && !slot.IsEmpty);

        if (occupiedSlots == 0)
        {
            return;
        }
        var timeTaken            = occupiedSlots * .4f;
        var finishProgressAction = new ProgressCompleteAction(() =>
        {
            foreach (var itemSlot in itemStorage.GetItemSlots())
            {
                //skip slots which have special uses
                if (itemSlot.NamedSlot == NamedSlot.handcuffs)
                {
                    continue;
                }
                Inventory.ServerDrop(itemSlot);
            }
        });

        UIManager.ServerStartProgress(ProgressAction.Disrobe, toDisrobe.transform.position, timeTaken,
                                      finishProgressAction, gameObject);
    }
    public void CmdRequestCPR(GameObject cardiacArrestPlayer)
    {
        //TODO: Probably refactor this to IF2
        if (!Validations.CanApply(playerScript, cardiacArrestPlayer, NetworkSide.Server))
        {
            return;
        }

        var cardiacArrestPlayerRegister = cardiacArrestPlayer.GetComponent <RegisterPlayer>();

        var progressFinishAction = new ProgressCompleteAction(() => DoCPR(playerScript.gameObject, cardiacArrestPlayer));

        var bar = UIManager.ServerStartProgress(ProgressAction.CPR, cardiacArrestPlayerRegister.WorldPosition, 5f, progressFinishAction,
                                                playerScript.gameObject);

        if (bar != null)
        {
            Chat.AddActionMsgToChat(playerScript.gameObject, $"You begin performing CPR on {cardiacArrestPlayer.Player()?.Name}.",
                                    $"{playerScript.gameObject.Player()?.Name} is trying to perform CPR on {cardiacArrestPlayer.Player()?.Name}.");
        }
    }
    public override IEnumerator Process()
    {
        yield return(WaitFor(PlayerToUncuff));

        GameObject actor          = SentByPlayer.GameObject;
        GameObject playerToUncuff = NetworkObject;

        var handcuffs = playerToUncuff.GetComponent <ItemStorage>().GetNamedItemSlot(NamedSlot.handcuffs).ItemObject;

        if (handcuffs != null)
        {
            var restraint = handcuffs.GetComponent <Restraint>();
            if (restraint)
            {
                var finishProgressAction = new ProgressCompleteAction(() =>
                                                                      playerToUncuff.GetComponent <PlayerMove>().RequestUncuff(actor));
                UIManager.ServerStartProgress(ProgressAction.Uncuff, actor.transform.position, restraint.RemoveTime,
                                              finishProgressAction, actor);
            }
        }
    }
Пример #12
0
    public void ServerPerformInteraction(HandApply interaction)
    {
        GameObject target    = interaction.TargetObject;
        GameObject performer = interaction.Performer;

        var progressFinishAction = new ProgressCompleteAction(
            () =>
        {
            if (performer.GetComponent <PlayerScript>()?.IsInReach(target, true) ?? false)
            {
                target.GetComponent <PlayerMove>().Cuff(interaction);
            }
        }
            );

        var bar = UIManager.ServerStartProgress(ProgressAction.Restrain, target.transform.position, applyTime, progressFinishAction, performer);

        if (bar != null)
        {
            SoundManager.PlayNetworkedAtPos(sound, target.transform.position);
        }
    }
Пример #13
0
    public void ServerPerformInteraction(HandApply interaction)
    {
        if (interaction.TargetObject != gameObject)
        {
            return;
        }

        if (Validations.HasComponent <Metal>(interaction.HandObject))
        {
            var progressFinishAction = new ProgressCompleteAction(() =>
                                                                  ConstructWall(interaction));
            UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer, 5f, progressFinishAction, interaction.Performer);
        }
        else if (Validations.IsTool(interaction.HandObject, ToolType.Wrench))
        {
            var progressFinishAction = new ProgressCompleteAction(Disassemble);
            var bar = UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer, 5f, progressFinishAction, interaction.Performer);
            if (bar != null)
            {
                SoundManager.PlayNetworkedAtPos("Wrench", transform.localPosition, 1f);
            }
        }
    }
Пример #14
0
    public void ServerPerformInteraction(PositionalHandApply interaction)
    {
        if (reagentContainer.CurrentCapacity < 1)
        {               //warning
            Chat.AddExamineMsg(interaction.Performer, "Your mop is dry!");
            return;
        }
        //server is performing server-side logic for the interaction
        //do the mopping
        var progressFinishAction = new ProgressCompleteAction(() =>
        {
            CleanTile(interaction.WorldPositionTarget);
            Chat.AddExamineMsg(interaction.Performer, "You finish mopping.");
        });

        //Start the progress bar:
        if (UIManager.ServerStartProgress(ProgressAction.Mop, interaction.WorldPositionTarget.RoundToInt(),
                                          useTime, progressFinishAction, interaction.Performer))
        {
            Chat.AddActionMsgToChat(interaction.Performer,
                                    $"You begin to clean the floor with {gameObject.ExpensiveName()}...",
                                    $"{interaction.Performer.name} begins to clean the floor with {gameObject.ExpensiveName()}.");
        }
    }
Пример #15
0
    private void startBuilding(HandActivate interaction)
    {
        var progressFinishAction = new ProgressCompleteAction(() => BuildGirder(interaction));

        UIManager.ServerStartProgress(ProgressAction.Construction, interaction.Performer.TileWorldPosition().To3Int(), 5f, progressFinishAction, interaction.Performer);
    }
Пример #16
0
    /// <summary>
    /// Performs common tool usage logic, such as playing the correct sound.
    /// If item is not a tool, simply performs the progress action normally.
    /// </summary>
    /// <param name="performer">player using the tool</param>
    /// <param name="tool">tool being used</param>
    /// <param name="worldTilePos">tile position the action is being performed on</param>
    /// <param name="seconds">seconds taken to perform the action, 0 if it should be instant</param>
    /// <param name="progressCompleteAction">completion callback (will also be called instantly if completion is instant)</param>
    /// <returns>progress bar spawned, null if progress did not start or this was instant</returns>
    public static ProgressBar ServerUseTool(GameObject performer, GameObject tool, Vector2 worldTilePos, float seconds, ProgressCompleteAction progressCompleteAction)
    {
        //check tool stats
        var toolStats = tool.GetComponent <Tool>();

        if (toolStats != null)
        {
            seconds /= toolStats.SpeedMultiplier;
        }

        if (seconds <= 0f)
        {
            ServerPlayToolSound(tool, worldTilePos);
            progressCompleteAction.OnEnd(ProgressEndReason.COMPLETED);
            return(null);
        }
        else
        {
            var bar = UIManager.ServerStartProgress(ProgressAction.Construction, worldTilePos, seconds, progressCompleteAction, performer);
            if (bar != null)
            {
                ServerPlayToolSound(tool, worldTilePos);
            }

            return(bar);
        }
    }
Пример #17
0
 /// <summary>
 /// Performs common tool usage logic, such as playing the correct sound.
 /// If item is not a tool, simply performs the progress action normally.
 /// </summary>
 /// <param name="handApply">hand apply causing the tool usage</param>
 /// <param name="seconds">seconds taken to perform the action, 0 for instant.</param>
 /// <param name="progressCompleteAction">completion callback</param>
 /// <returns>progress bar spawned, null if progress did not start</returns>
 public static ProgressBar ServerUseTool(HandApply handApply, float seconds            = 0,
                                         ProgressCompleteAction progressCompleteAction = null)
 {
     return(ServerUseTool(handApply.Performer, handApply.HandObject,
                          handApply.TargetObject.TileWorldPosition(), seconds, progressCompleteAction));
 }
Пример #18
0
 /// <summary>
 /// Performs common tool usage logic, such as playing the correct sound.
 /// If item is not a tool, simply performs the progress action normally.
 /// </summary>
 /// <param name="tileApply">tile apply causing the tool usage</param>
 /// <param name="seconds">seconds taken to perform the action, 0 for instant.</param>
 /// <param name="progressCompleteAction">completion callback</param>
 /// <returns>progress bar spawned, null if progress did not start</returns>
 public static ProgressBar ServerUseTool(TileApply tileApply, float seconds            = 0,
                                         ProgressCompleteAction progressCompleteAction = null)
 {
     return(ServerUseTool(tileApply.Performer, tileApply.HandObject,
                          tileApply.WorldPositionTarget, seconds, progressCompleteAction));
 }
Пример #19
0
    public override IEnumerator Process()
    {
        var clientStorage = SentByPlayer.Script.ItemStorage;
        var usedSlot      = clientStorage.GetActiveHandSlot();

        if (usedSlot == null || usedSlot.ItemObject == null)
        {
            yield break;
        }

        var hasConstructionMenu = usedSlot.ItemObject.GetComponent <BuildingMaterial>();

        if (hasConstructionMenu == null)
        {
            yield break;
        }

        var entry = hasConstructionMenu.BuildList.Entries.ToArray()[EntryIndex];

        if (!entry.CanBuildWith(hasConstructionMenu))
        {
            yield break;
        }

        //check if the space to construct on is passable
        if (!MatrixManager.IsPassableAt((Vector3Int)SentByPlayer.GameObject.TileWorldPosition(), true, includingPlayers: false))
        {
            Chat.AddExamineMsg(SentByPlayer.GameObject, "It won't fit here.");
            yield break;
        }

        //if we are building something impassable, check if there is anything on the space other than the performer.
        var atPosition =
            MatrixManager.GetAt <RegisterTile>((Vector3Int)SentByPlayer.GameObject.TileWorldPosition(), true);
        var builtObjectIsImpassable = !entry.Prefab.GetComponent <RegisterTile>().IsPassable(true);

        foreach (var thingAtPosition in atPosition)
        {
            if (entry.OnePerTile)
            {
                //can only build one of this on a given tile
                if (entry.Prefab.Equals(Spawn.DeterminePrefab(thingAtPosition.gameObject)))
                {
                    Chat.AddExamineMsg(SentByPlayer.GameObject, $"There's already one here.");
                    yield break;
                }
            }

            if (builtObjectIsImpassable)
            {
                //if the object we are building is itself impassable, we should check if anything blocks construciton.
                //otherwise it's fine to add it to the pile on the tile
                if (ServerValidations.IsConstructionBlocked(SentByPlayer.GameObject, null,
                                                            SentByPlayer.GameObject.TileWorldPosition()))
                {
                    yield break;
                }
            }
        }

        //build and consume
        var finishProgressAction = new ProgressCompleteAction(() =>
        {
            if (entry.ServerBuild(SpawnDestination.At(SentByPlayer.Script.registerTile), hasConstructionMenu))
            {
                Chat.AddActionMsgToChat(SentByPlayer.GameObject, $"You finish building the {entry.Name}.",
                                        $"{SentByPlayer.GameObject.ExpensiveName()} finishes building the {entry.Name}.");
            }
        });

        Chat.AddActionMsgToChat(SentByPlayer.GameObject, $"You begin building the {entry.Name}...",
                                $"{SentByPlayer.GameObject.ExpensiveName()} begins building the {entry.Name}...");
        ToolUtils.ServerUseTool(SentByPlayer.GameObject, usedSlot.ItemObject,
                                SentByPlayer.Script.registerTile.WorldPositionServer.To2Int(), entry.BuildTime,
                                finishProgressAction);
    }
Пример #20
0
    public void ServerPerformInteraction(HandApply interaction)
    {
        InventorySlot slot = InventoryManager.GetSlotFromOriginatorHand(interaction.Performer, interaction.HandSlot.equipSlot);

        if (RelatedInterface != null)
        {
            if (!RelatedInterface.InteractionUpdate(interaction, slot, this))
            {
                return;
            }
        }
        if (ContainedObjects[CurrentStage] != null)
        {
            foreach (var _Object in ContainedObjects[CurrentStage])
            {
                if (_Object.NumberNeeded > _Object.NumberPresent)
                {
                    if (_Object.GameObject != null)
                    {
                        if (slot.Item.GetComponent(_Object.IdentifyingComponent) != null)
                        {
                            if (_Object.TimeNeeded > 0)
                            {
                                var progressFinishAction = new ProgressCompleteAction(() => ExceptItem(slot, interaction));
                                UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer, _Object.TimeNeeded, progressFinishAction, interaction.Performer);
                            }
                            else
                            {
                                ConstructionStages[CurrentStage].PresentParts.Add(slot.Item);
                                InventoryManager.ClearInvSlot(slot);
                                _Object.NumberPresent++;
                            }
                        }
                    }
                    else if (_Object.CType != ConstructionElementType.Null)
                    {
                        var Item = slot.Item?.GetComponent <ConstructionComponent>();
                        if (Item != null)
                        {
                            if (Item.CType == _Object.CType && Item.level >= _Object.level)
                            {
                                if (_Object.TimeNeeded > 0)
                                {
                                    var progressFinishAction = new ProgressCompleteAction(() => ExceptItem(slot, interaction));
                                    UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer, _Object.TimeNeeded, progressFinishAction, interaction.Performer);
                                }
                                else
                                {
                                    ConstructionStages[CurrentStage].PresentParts.Add(slot.Item);
                                    InventoryManager.ClearInvSlot(slot);
                                    _Object.NumberPresent++;
                                }
                            }
                        }
                    }
                }
            }
        }

        var tool = slot.Item?.GetComponent <Tool>();

        if (tool == null)
        {
            return;
        }
        if (ConstructionStages[CurrentStage].ToolStage.ContainsKey(tool.ToolType))
        {
            var Jump = ConstructionStages[CurrentStage].ToolStage[tool.ToolType];
            if (Jump.ConstructionTime > 0)
            {
                var progressFinishAction = new ProgressCompleteAction(() => JumpLanding(tool));
                UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer, Jump.ConstructionTime / tool.SpeedMultiplier, progressFinishAction, interaction.Performer);
            }
            else
            {
                JumpLanding(tool);
            }
        }
    }
Пример #21
0
    private void SelfHeal(GameObject originator, BodyPartBehaviour targetBodyPart)
    {
        var progressFinishAction = new ProgressCompleteAction(() => ApplyHeal(targetBodyPart));

        UIManager.ServerStartProgress(ProgressAction.SelfHeal, originator.transform.position.RoundToInt(), 5f, progressFinishAction, originator);
    }
Пример #22
0
    public void ServerPerformInteraction(HandApply interaction)
    {
        var slot = interaction.HandSlot;

        if (RelatedInterface != null)
        {
            if (!RelatedInterface.InteractionUpdate(interaction, slot, this))
            {
                return;
            }
        }
        if (ContainedObjects[CurrentStage] != null)
        {
            foreach (var _Object in ContainedObjects[CurrentStage])
            {
                if (_Object.NumberNeeded > _Object.NumberPresent)
                {
                    if (_Object.GameObject != null)
                    {
                        if (slot.Item.GetComponent(_Object.IdentifyingComponent) != null)
                        {
                            if (_Object.TimeNeeded > 0)
                            {
                                var progressFinishAction = new ProgressCompleteAction(() => ExceptItem(slot, interaction));
                                UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer, _Object.TimeNeeded, progressFinishAction, interaction.Performer);
                            }
                            else
                            {
                                ConstructionStages[CurrentStage].PresentParts.Add(slot.ItemObject);
                                //TODO: In need of refactor throughout this component to not use Inventory.Vanish, instead should have an ItemStorage of its own most likely
                                Inventory.ServerVanish(slot);
                                _Object.NumberPresent++;
                            }
                        }
                    }
                    else if (_Object.CType != ConstructionElementType.Null)
                    {
                        var Item = slot.ItemObject?.GetComponent <ConstructionComponent>();
                        if (Item != null)
                        {
                            if (Item.CType == _Object.CType && Item.level >= _Object.level)
                            {
                                if (_Object.TimeNeeded > 0)
                                {
                                    var progressFinishAction = new ProgressCompleteAction(() => ExceptItem(slot, interaction));
                                    UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer, _Object.TimeNeeded, progressFinishAction, interaction.Performer);
                                }
                                else
                                {
                                    ConstructionStages[CurrentStage].PresentParts.Add(slot.ItemObject);
                                    Inventory.ServerVanish(slot);
                                    _Object.NumberPresent++;
                                }
                            }
                        }
                    }
                }
            }
        }

        var attrs = slot.Item?.GetComponent <ItemAttributes>();
        var tool  = slot.Item?.GetComponent <Tool>();

        if (attrs == null || tool == null)
        {
            return;
        }

        foreach (var trait in attrs.GetTraits())
        {
            if (ConstructionStages[CurrentStage].TraitStage.ContainsKey(trait))
            {
                var Jump = ConstructionStages[CurrentStage].TraitStage[trait];
                if (Jump.ConstructionTime > 0)
                {
                    var progressFinishAction = new ProgressCompleteAction(() => JumpLanding(tool, attrs));
                    UIManager.ServerStartProgress(ProgressAction.Construction, registerObject.WorldPositionServer,
                                                  Jump.ConstructionTime / tool.SpeedMultiplier, progressFinishAction, interaction.Performer);
                }
                else
                {
                    JumpLanding(tool, attrs);
                }
            }
        }
    }