예제 #1
0
    /// <summary>
    /// Instantiates prefab then add it to inventory
    /// </summary>
    /// <param name="addedObject"></param>
    /// <param name="toSlot"></param>
    /// <param name="replacementStrategy">what to do if toSlot is already occupied</param>
    /// <returns>true if successful</returns>
    public static bool ServerSpawnPrefab(GameObject addedObject, ItemSlot toSlot, ReplacementStrategy replacementStrategy = ReplacementStrategy.Cancel, bool IgnoreRestraints = false)
    {
        var spawn = Spawn.ServerPrefab(addedObject);

        return(ServerPerform(InventoryMove.Add(spawn.GameObject.GetComponent <Pickupable>(), toSlot, replacementStrategy, IgnoreRestraints)));
    }
예제 #2
0
    /// <summary>
    /// Server-side only. General purpose method for performing an inventory move. Performs the move indicated by toPerform.
    /// </summary>
    /// <param name="toPerform"></param>
    /// <returns>true if successful</returns>
    public static bool ServerPerform(InventoryMove toPerform)
    {
        if (toPerform == null)
        {
            Logger.LogError("Inventory move null, likely it failed due to previous error.", Category.Inventory);
            return(false);
        }
        var pickupable = toPerform.MovedObject;

        if (pickupable == null)
        {
            Logger.LogTrace("Inventory move attempted with null object. Move will not be performed", Category.Inventory);
            return(false);
        }

        if (toPerform.FromSlot != null && toPerform.FromSlot.Invalid)
        {
            Logger.LogErrorFormat("Inventory move attempted with invalid slot {0}. This slot reference should've" +
                                  " been cleaned up when the round restarted yet somehow didn't.", Category.Inventory,
                                  toPerform.FromSlot);
            return(false);
        }
        if (toPerform.ToSlot != null && toPerform.ToSlot.Invalid)
        {
            Logger.LogErrorFormat("Inventory move attempted with invalid slot {0}. This slot reference should've" +
                                  " been cleaned up when the round restarted yet somehow didn't.", Category.Inventory,
                                  toPerform.ToSlot);
            return(false);
        }

        //figure out which kind of move to do
        if (toPerform.InventoryMoveType == InventoryMoveType.Add)
        {
            if (!ServerPerformAdd(toPerform, pickupable))
            {
                return(false);
            }
        }
        else if (toPerform.InventoryMoveType == InventoryMoveType.Remove)
        {
            if (!ServerPerformRemove(toPerform, pickupable))
            {
                return(false);
            }
        }
        else if (toPerform.InventoryMoveType == InventoryMoveType.Transfer)
        {
            if (!ServerPerformTransfer(toPerform, pickupable))
            {
                return(false);
            }
        }
        else
        {
            Logger.LogTraceFormat("Unrecognized move type {0}. Please add logic to this method to support this move type.",
                                  Category.Inventory, toPerform.InventoryMoveType);
        }

        PlayInventorySound(toPerform.FromSlot, toPerform.MovedObject.gameObject.Item());

        return(true);
    }
예제 #3
0
 /// <summary>
 /// NOTE: This should RARELY be used, and this method may even be removed later!
 /// It's only here as a last resort / stopgap in case you can't figure out
 /// a better alternative. If you need to store an object for your component, use an ItemStorage
 /// on the object your component is on and transfer into it. It's bad to have items just hanging out at hidden pos.
 ///
 /// Inventory move in which the object in the slot is removed from inventory but neither dropped in the world,
 /// despawned, or made visible. Instead it is kept invisible at hiddenpos.
 /// </summary>
 /// <param name="fromSlot"></param>
 /// <returns>true if successful</returns>
 public static bool ServerVanish(ItemSlot fromSlot)
 {
     return(ServerPerform(InventoryMove.Vanish(fromSlot)));
 }
예제 #4
0
 /// <summary>
 /// Inventory move in which the object in the slot is thrown into the world from the location of its root storage
 /// </summary>
 /// <param name="fromSlot"></param>
 /// <param name="worldTargetVector">world space vector pointing from origin to targeted position to throw</param>
 /// <param name="spinMode"></param>
 /// <param name="aim">body part to target</param>
 /// <returns>true if successful</returns>
 public static bool ServerThrow(ItemSlot fromSlot, Vector2 worldTargetVector, SpinMode spinMode = SpinMode.CounterClockwise, BodyPartType aim = BodyPartType.Chest)
 {
     return(ServerPerform(InventoryMove.Throw(fromSlot, worldTargetVector, spinMode, aim)));
 }
예제 #5
0
 /// <summary>
 /// Inventory move in which the object in the slot is despawned directly from inventory and doesn't reappear
 /// in the world.
 /// </summary>
 /// <param name="fromSlot"></param>
 /// <returns>true if successful</returns>
 public static bool ServerDespawn(ItemSlot fromSlot)
 {
     return(ServerPerform(InventoryMove.Despawn(fromSlot)));
 }
예제 #6
0
 /// <summary>
 /// Inventory move in which the object in the slot is dropped into the world at the location of its root storage
 /// </summary>
 /// <param name="fromSlot"></param>
 /// <param name="worldTargetVector">world space vector pointing from origin to targeted position to throw, leave null
 /// to drop at holder's position</param>
 /// <returns>true if successful</returns>
 public static bool ServerDrop(ItemSlot fromSlot, Vector2?worldTargetVector = null)
 {
     return(ServerPerform(InventoryMove.Drop(fromSlot, worldTargetVector)));
 }
예제 #7
0
    private static bool ServerPerformAdd(InventoryMove toPerform, Pickupable pickupable)
    {
        //item is not currently in inventory, it should be moved into inventory system into
        //the indicated slot.

        if (pickupable.ItemSlot != null)
        {
            Logger.LogTraceFormat("Attempted to add {0} to inventory but item is already in slot {1}." +
                                  " Move will not be performed.", Category.Inventory, pickupable.name, pickupable.ItemSlot);
            return(false);
        }

        var toSlot = toPerform.ToSlot;

        if (toSlot == null)
        {
            Logger.LogTraceFormat("Attempted to add {0} to inventory but target slot was null." +
                                  " Move will not be performed.", Category.Inventory, pickupable.name);
            return(false);
        }

        if (toSlot.Item != null)
        {
            var stackableTarget = toSlot.Item.GetComponent <Stackable>();
            if (stackableTarget != null && stackableTarget.CanAccommodate(pickupable.gameObject))
            {
                toSlot.Item.GetComponent <Stackable>().ServerCombine(pickupable.GetComponent <Stackable>());
                return(true);
            }
            else
            {
                switch (toPerform.ReplacementStrategy)
                {
                case ReplacementStrategy.DespawnOther:
                    Logger.LogTraceFormat("Attempted to add {0} to inventory but target slot {1} already had something in it." +
                                          " Item in slot will be despawned first.", Category.Inventory, pickupable.name, toSlot);
                    ServerDespawn(toSlot);
                    break;

                case ReplacementStrategy.DropOther:
                    Logger.LogTraceFormat("Attempted to add {0} to inventory but target slot {1} already had something in it." +
                                          " Item in slot will be dropped first.", Category.Inventory, pickupable.name, toSlot);
                    ServerDrop(toSlot);
                    break;

                case ReplacementStrategy.Cancel:
                default:
                    Logger.LogTraceFormat("Attempted to add {0} to inventory but target slot {1} already had something in it." +
                                          " Move will not be performed.", Category.Inventory, pickupable.name, toSlot);
                    return(false);
                }
            }
        }

        if (!Validations.CanFit(toSlot, pickupable, NetworkSide.Server, true))
        {
            Logger.LogTraceFormat("Attempted to add {0} to slot {1} but slot cannot fit this item." +
                                  " transfer will not be performed.", Category.Inventory, pickupable.name, toSlot);
            return(false);
        }

        //go poof, it's in inventory now.
        pickupable.GetComponent <CustomNetTransform>().DisappearFromWorldServer(true);

        //no longer inside any PushPull
        pickupable.GetComponent <ObjectBehaviour>().parentContainer = null;
        pickupable.GetComponent <RegisterTile>().UpdatePositionServer();

        //update pickupable's item and slot's item
        pickupable._SetItemSlot(toSlot);
        toSlot._ServerSetItem(pickupable);

        foreach (var onMove in pickupable.GetComponents <IServerInventoryMove>())
        {
            onMove.OnInventoryMoveServer(toPerform);
        }

        return(true);
    }
예제 #8
0
 /// <summary>
 /// Inventory move in which the object was not previously in the inventory system (not in any ItemSlot)
 /// and now is.
 /// </summary>
 /// <param name="addedObject"></param>
 /// <param name="toSlot"></param>
 /// <param name="replacementStrategy">what to do if toSlot is already occupied</param>
 /// <returns>true if successful</returns>
 public static bool ServerAdd(GameObject addedObject, ItemSlot toSlot, ReplacementStrategy replacementStrategy = ReplacementStrategy.Cancel)
 {
     return(ServerPerform(InventoryMove.Add(addedObject, toSlot, replacementStrategy)));
 }
예제 #9
0
    private static bool ServerPerformRemove(InventoryMove toPerform, Pickupable pickupable)
    {
        if (pickupable.ItemSlot == null)
        {
            Logger.LogTraceFormat("Attempted to remove {0} from inventory but item is not in a slot." +
                                  " remove will not be performed.", Category.Inventory, pickupable.name);
            return(false);
        }

        var fromSlot = toPerform.FromSlot;

        if (fromSlot == null)
        {
            Logger.LogTraceFormat("Attempted to remove {0} from inventory but from slot was null." +
                                  " Move will not be performed.", Category.Inventory, pickupable.name);
            return(false);
        }

        if (fromSlot.Item == null)
        {
            Logger.LogTraceFormat("Attempted to remove {0} from inventory but from slot {1} had no item in it." +
                                  " Move will not be performed.", Category.Inventory, pickupable.name, fromSlot);
            return(false);
        }

        //update pickupable's item and slot's item
        pickupable._SetItemSlot(null);
        fromSlot._ServerRemoveItem();

        //decide how it should be removed
        var removeType      = toPerform.RemoveType;
        var holder          = fromSlot.GetRootStorage();
        var holderPushPull  = holder.GetComponent <PushPull>();
        var parentContainer = holderPushPull == null ? null : holderPushPull.parentContainer;

        if (parentContainer != null && removeType == InventoryRemoveType.Throw)
        {
            Logger.LogTraceFormat("throwing from slot {0} while in container {1}. Will drop instead.", Category.Inventory,
                                  fromSlot,
                                  parentContainer.name);
            removeType = InventoryRemoveType.Drop;
        }


        if (removeType == InventoryRemoveType.Despawn)
        {
            //destroy (safe to skip invnetory despawn check because we already performed necessary inventory logic)
            Despawn.ServerSingle(pickupable.gameObject, true);
        }
        else if (removeType == InventoryRemoveType.Drop)
        {
            //drop where it is
            //determine where it will appear
            if (parentContainer != null)
            {
                //TODO: Not a big fan of this bespoke logic for dealing with dropping in closet control. Try to refactor this
                Logger.LogTraceFormat("Dropping from slot {0} while in container {1}", Category.Inventory,
                                      fromSlot,
                                      parentContainer.name);
                var closetControl = parentContainer.GetComponent <ClosetControl>();
                if (closetControl == null)
                {
                    Logger.LogWarningFormat("Dropping from slot {0} while in container {1}, but container type was not recognized. " +
                                            "Currently only ClosetControl is supported. Please add code to handle this case.", Category.Inventory,
                                            fromSlot,
                                            holderPushPull.parentContainer.name);
                    return(false);
                }
                //vanish it and set its parent container
                ServerVanish(fromSlot);
                var objBehavior = pickupable.GetComponent <ObjectBehaviour>();
                if (objBehavior == null)
                {
                    Logger.LogTraceFormat("Dropping object {0} while in container {1}, but dropped object had" +
                                          " no object behavior. Cannot drop.", Category.Inventory,
                                          pickupable,
                                          holderPushPull.parentContainer.name);
                    return(false);
                }
                closetControl.ServerAddInternalItem(objBehavior);

                return(true);
            }

            var     holderPlayer   = holder.GetComponent <PlayerSync>();
            var     cnt            = pickupable.GetComponent <CustomNetTransform>();
            var     holderPosition = holder.gameObject.AssumedWorldPosServer();
            Vector3 targetWorldPos = holderPosition + (Vector3)toPerform.WorldTargetVector.GetValueOrDefault(Vector2.zero);
            if (holderPlayer != null)
            {
                //dropping from player
                //Inertia drop works only if player has external impulse (space floating etc.)
                cnt.InertiaDrop(targetWorldPos, holderPlayer.SpeedServer,
                                holderPlayer.ServerImpulse);
            }
            else
            {
                //dropping from not-held storage
                cnt.AppearAtPositionServer(targetWorldPos);
            }
        }
        else if (removeType == InventoryRemoveType.Throw)
        {
            //throw / eject
            //determine where it will be thrown from
            var cnt = pickupable.GetComponent <CustomNetTransform>();
            var assumedWorldPosServer = holder.gameObject.AssumedWorldPosServer();
            var throwInfo             = new ThrowInfo
            {
                ThrownBy        = holder.gameObject,
                Aim             = toPerform.ThrowAim.GetValueOrDefault(BodyPartType.Chest),
                OriginWorldPos  = assumedWorldPosServer,
                WorldTrajectory = toPerform.WorldTargetVector.GetValueOrDefault(Vector2.zero),
                SpinMode        = toPerform.ThrowSpinMode.GetValueOrDefault(SpinMode.Clockwise)
            };
            //dropping from player
            //Inertia drop works only if player has external impulse (space floating etc.)
            cnt.Throw(throwInfo);

            //Counter-impulse for players in space
            holderPushPull.Pushable.NewtonianMove((-throwInfo.WorldTrajectory).NormalizeTo2Int(), speed: (int)cnt.Size + 1);
        }
        //NOTE: vanish doesn't require any extra logic. The item is already at hiddenpos and has
        //already been removed from the inventory system.

        foreach (var onMove in pickupable.GetComponents <IServerInventoryMove>())
        {
            onMove.OnInventoryMoveServer(toPerform);
        }

        return(true);
    }
예제 #10
0
    private static bool ServerPerformTransfer(InventoryMove toPerform, Pickupable pickupable)
    {
        //transfer from one slot to another
        var toSlot   = toPerform.ToSlot;
        var fromSlot = toPerform.FromSlot;

        if (toSlot == null)
        {
            Logger.LogTraceFormat("Attempted to transfer {0} to another slot but target slot was null." +
                                  " Move will not be performed.", Category.Inventory, pickupable.name);
            return(false);
        }

        if (toSlot.Item != null)
        {
            // Check if the items can be stacked
            var stackableTarget = toSlot.Item.GetComponent <Stackable>();
            if (stackableTarget != null && stackableTarget.CanAccommodate(pickupable.gameObject))
            {
                toSlot.Item.GetComponent <Stackable>().ServerCombine(pickupable.GetComponent <Stackable>());
                return(true);
            }

            switch (toPerform.ReplacementStrategy)
            {
            case ReplacementStrategy.DespawnOther:
                Logger.LogTraceFormat("Attempted to transfer from slot {0} to slot {1} which already had something in it." +
                                      " Item in slot will be despawned first.", Category.Inventory, fromSlot, toSlot);
                ServerDespawn(toSlot);
                break;

            case ReplacementStrategy.DropOther:
                Logger.LogTraceFormat("Attempted to transfer from slot {0} to slot {1} which already had something in it." +
                                      " Item in slot will be dropped first.", Category.Inventory, fromSlot, toSlot);
                ServerDrop(toSlot);
                break;

            case ReplacementStrategy.Cancel:
            default:
                Logger.LogTraceFormat("Attempted to transfer from slot {0} to slot {1} which already had something in it." +
                                      " Transfer will not be performed.", Category.Inventory, fromSlot, toSlot);
                return(false);
            }
        }

        if (pickupable.ItemSlot == null)
        {
            Logger.LogTraceFormat("Attempted to transfer {0} to target slot but item is not in a slot." +
                                  " transfer will not be performed.", Category.Inventory, pickupable.name);
            return(false);
        }


        if (fromSlot == null)
        {
            Logger.LogTraceFormat("Attempted to transfer {0} to target slot but from slot was null." +
                                  " transfer will not be performed.", Category.Inventory, pickupable.name);
            return(false);
        }

        if (!Validations.CanFit(toSlot, pickupable, NetworkSide.Server, true))
        {
            Logger.LogTraceFormat("Attempted to transfer {0} to slot {1} but slot cannot fit this item." +
                                  " transfer will not be performed.", Category.Inventory, pickupable.name, toSlot);
            return(false);
        }

        pickupable._SetItemSlot(null);
        fromSlot._ServerRemoveItem();

        pickupable._SetItemSlot(toSlot);
        toSlot._ServerSetItem(pickupable);

        foreach (var onMove in pickupable.GetComponents <IServerInventoryMove>())
        {
            onMove.OnInventoryMoveServer(toPerform);
        }

        return(true);
    }
예제 #11
0
 /// <summary>
 /// Inventory move in which the object in one slot is transferred directly to another
 /// </summary>
 /// <param name="fromSlot"></param>
 /// <param name="toSlot"></param>
 /// <param name="replacementStrategy">what to do if toSlot is already occupied</param>
 /// <returns>true if successful</returns>
 public static bool ServerTransfer(ItemSlot fromSlot, ItemSlot toSlot, ReplacementStrategy replacementStrategy = ReplacementStrategy.Cancel)
 {
     return(ServerPerform(InventoryMove.Transfer(fromSlot, toSlot, replacementStrategy)));
 }