public void EjectContainer() { foreach (var slot in itemStorage.GetItemSlots()) { Inventory.ServerDrop(itemSlot); } return; }
protected override void Gib() { EffectsFactory.BloodSplat(transform.position, BloodSplatSize.large, bloodColor); //drop clothes, gib... but don't destroy actual player, a piece should remain //drop everything foreach (var slot in itemStorage.GetItemSlots()) { Inventory.ServerDrop(slot); } if (!playerMove.PlayerScript.IsGhost) { //dirty way to follow gibs. change this when implementing proper gibbing, perhaps make it follow brain var gibsToFollow = MatrixManager.GetAt <RawMeat>(transform.position.CutToInt(), true); if (gibsToFollow.Count > 0) { var gibs = gibsToFollow[0]; FollowCameraMessage.Send(gameObject, gibs.gameObject); var gibsIntegrity = gibs.GetComponent <Integrity>(); if (gibsIntegrity != null) { //Stop cam following gibs if they are destroyed gibsIntegrity.OnWillDestroyServer.AddListener(x => FollowCameraMessage.Send(gameObject, null)); } } } playerMove.PlayerScript.pushPull.VisibleState = false; }
private void OnStorageChanged() { // recalculate occupied slots count and send to client var allSlots = storage.GetItemSlots(); objectsInsideCount = allSlots.Count((s) => s.IsOccupied); }
/// <summary> /// Dry everything inside it. /// </summary> private void CheckDried(float dryTime) { foreach (var slot in storage.GetItemSlots()) { if (slot.IsEmpty == true) { break; } // If, somehow, something undryable is in the drying rack (should be impossible), spit it out. var dryable = slot.ItemObject.GetComponent <Dryable>(); if (dryable == null) { Inventory.ServerDrop(slot); continue; } if (dryable.AddDryingTime(dryTime) == true) { // Swap item for its dried version, if applicable. if (dryable.DriedProduct == null) { return; } Spawn.ServerPrefab(dryable.DriedProduct, WorldPosition); _ = Despawn.ServerSingle(dryable.gameObject); } } }
/// <summary> /// Can be called client and server side to free up the cached /// slots in this storage. Should be called when storage is going to be destroyed or /// will be no longer known by the client. On server side, also destroys all the items in the slot. /// </summary> /// <param name="storageToFree"></param> public static void Free(ItemStorage storageToFree) { if (CustomNetworkManager.Instance != null && CustomNetworkManager.Instance._isServer) { //destroy all items in the slots foreach (var slot in storageToFree.GetItemSlots()) { if (slot.Item != null) { Inventory.ServerDespawn(slot); } } } if (storageToFree.GetComponentInParent <NetworkIdentity>()) { var instanceID = storageToFree.GetComponentInParent <NetworkIdentity>().GetInstanceID(); slots.TryGetValue(instanceID, out var dict); if (dict != null) { dict.Clear(); slots.Remove(instanceID); } } }
private bool CheckStorage(ItemStorage itemStorage) { foreach (var slot in itemStorage.GetItemSlots()) { if (CheckSlot(slot)) { return(true); } } return(false); }
protected override void Gib() { Death(); EffectsFactory.BloodSplat(RegisterTile.WorldPositionServer, BloodSplatSize.large, BloodSplatType.red); //drop clothes, gib... but don't destroy actual player, a piece should remain //drop everything foreach (var slot in itemStorage.GetItemSlots()) { Inventory.ServerDrop(slot); } PlayerMove.PlayerScript.pushPull.VisibleState = false; playerNetworkActions.ServerSpawnPlayerGhost(); }
/// <summary> /// Returns the slot in storage which is the best fit for the item. /// The BestSlots list will be scanned through in order. Returns the /// first slot in the BestSlots list for which toCheck has the /// indicated trait (ignored if trait is left blank) and can be put into the slot. If none of the BestSlots /// will fit this item, returns the first slot in storage which can hold the item. /// Returns null if the item cannot fit in any slots in storage. /// </summary> /// <param name="toCheck"></param> /// <param name="storage"></param> /// <param name="mustHaveUISlot">if true (default), will only return slots /// which are linked to a UI slot</param> /// <returns></returns> public ItemSlot GetBestSlot(Pickupable toCheck, ItemStorage storage, bool mustHaveUISlot = true) { if (toCheck == null || storage == null) { Logger.LogTrace("Cannot get best slot, toCheck or storage was null", Category.Inventory); return(null); } var side = CustomNetworkManager.IsServer ? NetworkSide.Server : NetworkSide.Client; var itemAttrs = toCheck.GetComponent <ItemAttributesV2>(); if (itemAttrs == null) { Logger.LogTraceFormat("Item {0} has no ItemAttributes, thus it will be put in the" + " first available slot.", Category.Inventory, toCheck); } else { //find the best slot var best = BestSlots.FirstOrDefault(tsm => (!mustHaveUISlot || storage.GetNamedItemSlot(tsm.Slot)?.LocalUISlot != null) && Validations.CanFit(storage.GetNamedItemSlot(tsm.Slot), toCheck, side) && (tsm.Trait == null || itemAttrs.HasTrait(tsm.Trait))); if (best != null) { return(storage.GetNamedItemSlot(best.Slot)); } } Logger.LogTraceFormat("Item {0} did not fit in any BestSlots, thus will" + " be placed in first available slot.", Category.Inventory, toCheck); // Get all slots var allSlots = storage.GetItemSlots(); // Filter blaclisted named slots var allowedSlots = allSlots.Where((slot) => !slot.NamedSlot.HasValue || (slot.NamedSlot.HasValue && !BlackListSlots.Contains(slot.NamedSlot.Value))).ToArray(); // Select first avaliable return(allowedSlots.FirstOrDefault(slot => (!mustHaveUISlot || slot.LocalUISlot != null) && Validations.CanFit(slot, toCheck, side))); }
//This is all client only interaction: public bool Interact(HandActivate interaction) { if (canQuickEmpty) { // Drop all items that are inside this storage var slots = itemStorage.GetItemSlots(); if (slots == null) { if (!CustomNetworkManager.Instance._isServer) { Chat.AddExamineMsgToClient("It's already empty!"); } return(false); } if (PlayerManager.PlayerScript == null) { return(false); } PlayerManager.PlayerScript.playerNetworkActions.CmdDropAllItems(itemStorage.GetIndexedItemSlot(0).ItemStorageNetID); if (!CustomNetworkManager.Instance._isServer) { Chat.AddExamineMsgToClient($"You start dumping out the {gameObject.ExpensiveName()}."); } return(true); } //open / close the backpack on activate if (UIManager.StorageHandler.CurrentOpenStorage != itemStorage) { UIManager.StorageHandler.OpenStorageUI(itemStorage); } else { UIManager.StorageHandler.CloseStorageUI(); } return(true); }
private void Start() { // get ItemStorage on a same object storage = GetComponent <ItemStorage>(); if (!storage) { Logger.LogError($"FancyItemStorage on {gameObject.name} can't find ItemStorage component!", Category.Containers); return; } // get all slots and subscribe if any slot changed var allSlots = storage.GetItemSlots(); foreach (var slot in allSlots) { slot.OnSlotContentsChangeServer.AddListener(OnStorageChanged); } // calculate occupied slots count objectsInsideCount = allSlots.Count((s) => s.IsOccupied); }
/// <summary> /// is the function to denote that it will be pooled or destroyed immediately after this function is finished, Used for cleaning up anything that needs to be cleaned up before this happens /// </summary> public void OnDespawnServer(DespawnInfo info) { if (MeltedDown) { foreach (var Rod in ReactorRods) { if (Rod != null) { switch (Rod.GetRodType()) { case RodType.Fuel: Spawn.ServerPrefab(UraniumOre, registerObject.WorldPositionServer); break; case RodType.Control: Spawn.ServerPrefab(MetalOre, registerObject.WorldPositionServer); break; } } } } else { foreach (var Rod in RodStorage.GetItemSlots()) { Inventory.ServerDespawn(Rod); } Spawn.ServerPrefab(ConstructMaterial, registerObject.WorldPositionServer, count: droppedMaterialAmount); } MeltedDown = false; PoppedPipes = false; PresentNeutrons = 0; Array.Clear(ReactorRods, 0, ReactorRods.Length); ReactorFuelRods.Clear(); ReactorEngineStarters.Clear(); UpdateManager.Remove(CallbackType.PERIODIC_UPDATE, CycleUpdate); }
/// <summary> /// Server: /// Allow items to be stored by clicking on bags with item in hand /// and clicking items with bag in hand if CanClickPickup is enabled /// </summary> public void ServerPerformInteraction(PositionalHandApply interaction) { if (allowedToInteract == false) { return; } // See which item needs to be stored if (Validations.IsTarget(gameObject, interaction)) { // Add hand item to this storage Inventory.ServerTransfer(interaction.HandSlot, itemStorage.GetBestSlotFor(interaction.HandObject)); } // See if this item can click pickup else if (canClickPickup) { bool pickedUpSomething = false; Pickupable pickup; switch (pickupMode) { case PickupMode.Single: // Don't pick up items which aren't set as CanPickup pickup = interaction.TargetObject.GetComponent <Pickupable>(); if (pickup == null || pickup.CanPickup == false) { Chat.AddExamineMsgFromServer(interaction.Performer, "There's nothing to pickup!"); return; } // Store the clicked item var slot = itemStorage.GetBestSlotFor(interaction.TargetObject); if (slot == null) { Chat.AddExamineMsgFromServer(interaction.Performer, $"The {interaction.TargetObject.ExpensiveName()} doesn't fit!"); return; } Inventory.ServerAdd(interaction.TargetObject, slot); break; case PickupMode.Same: if (interaction.TargetObject == null || interaction.TargetObject.Item() == null) { Chat.AddExamineMsgFromServer(interaction.Performer, "There's nothing to pickup!"); return; } // Get all items of the same type on the tile and try to store them var itemsOnTileSame = MatrixManager.GetAt <ItemAttributesV2>(interaction.WorldPositionTarget.To2Int().To3Int(), true); if (itemsOnTileSame.Count == 0) { Chat.AddExamineMsgFromServer(interaction.Performer, "There's nothing to pickup!"); return; } foreach (var item in itemsOnTileSame) { // Don't pick up items which aren't set as CanPickup pickup = item.gameObject.GetComponent <Pickupable>(); if (pickup == null || pickup.CanPickup == false) { continue; } // Only try to add it if it matches the target object's traits if (item.HasAllTraits(interaction.TargetObject.Item().GetTraits())) { // Try to add each item to the storage // Can't break this loop when it fails because some items might not fit and // there might be stacks with space still if (Inventory.ServerAdd(item.gameObject, itemStorage.GetBestSlotFor(item.gameObject))) { pickedUpSomething = true; } } } Chat.AddExamineMsgFromServer(interaction.Performer, $"You put everything you could in the {gameObject.ExpensiveName()}."); break; case PickupMode.All: // Get all items on the tile and try to store them var itemsOnTileAll = MatrixManager.GetAt <ItemAttributesV2>(interaction.WorldPositionTarget.To2Int().To3Int(), true); if (itemsOnTileAll.Count == 0) { Chat.AddExamineMsgFromServer(interaction.Performer, "There's nothing to pickup!"); return; } foreach (var item in itemsOnTileAll) { // Don't pick up items which aren't set as CanPickup pickup = item.gameObject.GetComponent <Pickupable>(); if (pickup == null || pickup.CanPickup == false) { continue; } // Try to add each item to the storage // Can't break this loop when it fails because some items might not fit and // there might be stacks with space still if (Inventory.ServerAdd(item.gameObject, itemStorage.GetBestSlotFor(item.gameObject))) { pickedUpSomething = true; } } if (pickedUpSomething) { Chat.AddExamineMsgFromServer(interaction.Performer, $"You put everything you could in the {gameObject.ExpensiveName()}."); } else { Chat.AddExamineMsgFromServer(interaction.Performer, "There's nothing to pickup!"); } break; case PickupMode.DropClick: if (canQuickEmpty) { // Drop all items that are inside this storage var slots = itemStorage.GetItemSlots(); if (slots == null) { Chat.AddExamineMsgFromServer(interaction.Performer, "It's already empty!"); return; } if (PlayerManager.PlayerScript == null) { return; } if (Validations.IsInReachDistanceByPositions(PlayerManager.PlayerScript.registerTile.WorldPosition, interaction.WorldPositionTarget) == false) { return; } if (MatrixManager.IsPassableAtAllMatricesOneTile(interaction.WorldPositionTarget.RoundToInt(), CustomNetworkManager.Instance._isServer) == false) { return; } PlayerManager.PlayerScript.playerNetworkActions.CmdDropAllItems(itemStorage.GetIndexedItemSlot(0) .ItemStorageNetID, interaction.WorldPositionTarget); Chat.AddExamineMsgFromServer(interaction.Performer, $"You start dumping out the {gameObject.ExpensiveName()}."); } break; } } }