Inventory slot enumerator rejig (#21788)
This commit is contained in:
@@ -202,17 +202,15 @@ public sealed class ClientClothingSystem : ClothingSystem
|
|||||||
revealedLayers.Clear();
|
revealedLayers.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitClothing(EntityUid uid, InventoryComponent? component = null, SpriteComponent? sprite = null)
|
public void InitClothing(EntityUid uid, InventoryComponent component)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref sprite, ref component) || !_inventorySystem.TryGetSlots(uid, out var slots, component))
|
if (!TryComp(uid, out SpriteComponent? sprite))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var slot in slots)
|
var enumerator = _inventorySystem.GetSlotEnumerator((uid, component));
|
||||||
|
while (enumerator.NextItem(out var item, out var slot))
|
||||||
{
|
{
|
||||||
if (!_inventorySystem.TryGetSlotContainer(uid, slot.Name, out var containerSlot, out _, component) ||
|
RenderEquipment(uid, item, slot.Name, component, sprite);
|
||||||
!containerSlot.ContainedEntity.HasValue) continue;
|
|
||||||
|
|
||||||
RenderEquipment(uid, containerSlot.ContainedEntity.Value, slot.Name, component, sprite);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using Content.Client.Clothing;
|
using Content.Client.Clothing;
|
||||||
using Content.Client.Examine;
|
using Content.Client.Examine;
|
||||||
using Content.Client.UserInterface.Controls;
|
|
||||||
using Content.Client.Verbs.UI;
|
using Content.Client.Verbs.UI;
|
||||||
using Content.Shared.Clothing.Components;
|
using Content.Shared.Clothing.Components;
|
||||||
using Content.Shared.Hands.Components;
|
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
@@ -15,14 +13,12 @@ using Robust.Client.UserInterface;
|
|||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Input.Binding;
|
using Robust.Shared.Input.Binding;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Client.Inventory
|
namespace Content.Client.Inventory
|
||||||
{
|
{
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class ClientInventorySystem : InventorySystem
|
public sealed class ClientInventorySystem : InventorySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IUserInterfaceManager _ui = default!;
|
[Dependency] private readonly IUserInterfaceManager _ui = default!;
|
||||||
|
|
||||||
@@ -89,7 +85,7 @@ namespace Content.Client.Inventory
|
|||||||
private void OnDidUnequip(InventorySlotsComponent component, DidUnequipEvent args)
|
private void OnDidUnequip(InventorySlotsComponent component, DidUnequipEvent args)
|
||||||
{
|
{
|
||||||
UpdateSlot(args.Equipee, component, args.Slot);
|
UpdateSlot(args.Equipee, component, args.Slot);
|
||||||
if (args.Equipee != _playerManager.LocalPlayer?.ControlledEntity)
|
if (args.Equipee != _playerManager.LocalEntity)
|
||||||
return;
|
return;
|
||||||
var update = new SlotSpriteUpdate(null, args.SlotGroup, args.Slot, false);
|
var update = new SlotSpriteUpdate(null, args.SlotGroup, args.Slot, false);
|
||||||
OnSpriteUpdate?.Invoke(update);
|
OnSpriteUpdate?.Invoke(update);
|
||||||
@@ -98,7 +94,7 @@ namespace Content.Client.Inventory
|
|||||||
private void OnDidEquip(InventorySlotsComponent component, DidEquipEvent args)
|
private void OnDidEquip(InventorySlotsComponent component, DidEquipEvent args)
|
||||||
{
|
{
|
||||||
UpdateSlot(args.Equipee, component, args.Slot);
|
UpdateSlot(args.Equipee, component, args.Slot);
|
||||||
if (args.Equipee != _playerManager.LocalPlayer?.ControlledEntity)
|
if (args.Equipee != _playerManager.LocalEntity)
|
||||||
return;
|
return;
|
||||||
var update = new SlotSpriteUpdate(args.Equipment, args.SlotGroup, args.Slot,
|
var update = new SlotSpriteUpdate(args.Equipment, args.SlotGroup, args.Slot,
|
||||||
HasComp<StorageComponent>(args.Equipment));
|
HasComp<StorageComponent>(args.Equipment));
|
||||||
@@ -107,9 +103,7 @@ namespace Content.Client.Inventory
|
|||||||
|
|
||||||
private void OnShutdown(EntityUid uid, InventoryComponent component, ComponentShutdown args)
|
private void OnShutdown(EntityUid uid, InventoryComponent component, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
if (uid != _playerManager.LocalPlayer?.ControlledEntity)
|
if (uid == _playerManager.LocalEntity)
|
||||||
return;
|
|
||||||
|
|
||||||
OnUnlinkInventory?.Invoke();
|
OnUnlinkInventory?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,13 +145,10 @@ namespace Content.Client.Inventory
|
|||||||
base.OnInit(uid, component, args);
|
base.OnInit(uid, component, args);
|
||||||
_clothingVisualsSystem.InitClothing(uid, component);
|
_clothingVisualsSystem.InitClothing(uid, component);
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex(component.TemplateId, out InventoryTemplatePrototype? invTemplate) ||
|
if (!TryComp(uid, out InventorySlotsComponent? inventorySlots))
|
||||||
!TryComp(uid, out InventorySlotsComponent? inventorySlots))
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var slot in invTemplate.Slots)
|
foreach (var slot in component.Slots)
|
||||||
{
|
{
|
||||||
TryAddSlotDef(uid, inventorySlots, slot);
|
TryAddSlotDef(uid, inventorySlots, slot);
|
||||||
}
|
}
|
||||||
@@ -165,7 +156,7 @@ namespace Content.Client.Inventory
|
|||||||
|
|
||||||
public void ReloadInventory(InventorySlotsComponent? component = null)
|
public void ReloadInventory(InventorySlotsComponent? component = null)
|
||||||
{
|
{
|
||||||
var player = _playerManager.LocalPlayer?.ControlledEntity;
|
var player = _playerManager.LocalEntity;
|
||||||
if (player == null || !Resolve(player.Value, ref component, false))
|
if (player == null || !Resolve(player.Value, ref component, false))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -179,7 +170,7 @@ namespace Content.Client.Inventory
|
|||||||
{
|
{
|
||||||
var oldData = component.SlotData[slotName];
|
var oldData = component.SlotData[slotName];
|
||||||
var newData = component.SlotData[slotName] = new SlotData(oldData, state);
|
var newData = component.SlotData[slotName] = new SlotData(oldData, state);
|
||||||
if (owner == _playerManager.LocalPlayer?.ControlledEntity)
|
if (owner == _playerManager.LocalEntity)
|
||||||
EntitySlotUpdate?.Invoke(newData);
|
EntitySlotUpdate?.Invoke(newData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +189,7 @@ namespace Content.Client.Inventory
|
|||||||
|
|
||||||
var newData = component.SlotData[slotName] =
|
var newData = component.SlotData[slotName] =
|
||||||
new SlotData(component.SlotData[slotName], newHighlight, newBlocked);
|
new SlotData(component.SlotData[slotName], newHighlight, newBlocked);
|
||||||
if (owner == _playerManager.LocalPlayer?.ControlledEntity)
|
if (owner == _playerManager.LocalEntity)
|
||||||
EntitySlotUpdate?.Invoke(newData);
|
EntitySlotUpdate?.Invoke(newData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,48 +199,11 @@ namespace Content.Client.Inventory
|
|||||||
if (!component.SlotData.TryAdd(newSlotDef.Name, newSlotData))
|
if (!component.SlotData.TryAdd(newSlotDef.Name, newSlotData))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (owner == _playerManager.LocalPlayer?.ControlledEntity)
|
if (owner == _playerManager.LocalEntity)
|
||||||
OnSlotAdded?.Invoke(newSlotData);
|
OnSlotAdded?.Invoke(newSlotData);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveSlotDef(EntityUid owner, InventorySlotsComponent component, SlotData slotData)
|
|
||||||
{
|
|
||||||
if (component.SlotData.Remove(slotData.SlotName))
|
|
||||||
{
|
|
||||||
if (owner == _playerManager.LocalPlayer?.ControlledEntity)
|
|
||||||
OnSlotRemoved?.Invoke(slotData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveSlotDef(EntityUid owner, InventorySlotsComponent component, string slotName)
|
|
||||||
{
|
|
||||||
if (!component.SlotData.TryGetValue(slotName, out var slotData))
|
|
||||||
return;
|
|
||||||
|
|
||||||
component.SlotData.Remove(slotName);
|
|
||||||
|
|
||||||
if (owner == _playerManager.LocalPlayer?.ControlledEntity)
|
|
||||||
OnSlotRemoved?.Invoke(slotData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO hud refactor This should also live in a UI Controller
|
|
||||||
private void HoverInSlotButton(EntityUid uid, string slot, SlotControl control,
|
|
||||||
InventoryComponent? inventoryComponent = null, HandsComponent? hands = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref inventoryComponent))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!Resolve(uid, ref hands, false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (hands.ActiveHandEntity is not EntityUid heldEntity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!TryGetSlotContainer(uid, slot, out var containerSlot, out var slotDef, inventoryComponent))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UIInventoryActivate(string slot)
|
public void UIInventoryActivate(string slot)
|
||||||
{
|
{
|
||||||
EntityManager.RaisePredictiveEvent(new UseSlotNetworkMessage(slot));
|
EntityManager.RaisePredictiveEvent(new UseSlotNetworkMessage(slot));
|
||||||
|
|||||||
@@ -90,11 +90,11 @@ namespace Content.Client.Inventory
|
|||||||
|
|
||||||
_strippingMenu.ClearButtons();
|
_strippingMenu.ClearButtons();
|
||||||
|
|
||||||
if (EntMan.TryGetComponent<InventoryComponent>(Owner, out var inv) && _protoMan.TryIndex<InventoryTemplatePrototype>(inv.TemplateId, out var template))
|
if (EntMan.TryGetComponent<InventoryComponent>(Owner, out var inv))
|
||||||
{
|
{
|
||||||
foreach (var slot in template.Slots)
|
foreach (var slot in inv.Slots)
|
||||||
{
|
{
|
||||||
AddInventoryButton(Owner, slot.Name, template, inv);
|
AddInventoryButton(Owner, slot.Name, inv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ namespace Content.Client.Inventory
|
|||||||
_ui.GetUIController<VerbMenuUIController>().OpenVerbMenu(slot.Entity.Value);
|
_ui.GetUIController<VerbMenuUIController>().OpenVerbMenu(slot.Entity.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddInventoryButton(EntityUid invUid, string slotId, InventoryTemplatePrototype _, InventoryComponent inv)
|
private void AddInventoryButton(EntityUid invUid, string slotId, InventoryComponent inv)
|
||||||
{
|
{
|
||||||
if (!_inv.TryGetSlotContainer(invUid, slotId, out var container, out var slotDef, inv))
|
if (!_inv.TryGetSlotContainer(invUid, slotId, out var container, out var slotDef, inv))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -92,9 +92,9 @@ namespace Content.Server.Administration.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var invSystem = entityManager.System<InventorySystem>();
|
var invSystem = entityManager.System<InventorySystem>();
|
||||||
if (invSystem.TryGetSlots(target, out var slotDefinitions, inventoryComponent))
|
if (invSystem.TryGetSlots(target, out var slots))
|
||||||
{
|
{
|
||||||
foreach (var slot in slotDefinitions)
|
foreach (var slot in slots)
|
||||||
{
|
{
|
||||||
invSystem.TryUnequip(target, slot.Name, true, true, false, inventoryComponent);
|
invSystem.TryUnequip(target, slot.Name, true, true, false, inventoryComponent);
|
||||||
var gearStr = startingGear.GetGear(slot.Name, profile);
|
var gearStr = startingGear.GetGear(slot.Name, profile);
|
||||||
|
|||||||
@@ -368,15 +368,12 @@ namespace Content.Server.Administration.Systems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryComp(entity.Value, out InventoryComponent? inventory) &&
|
if (_inventory.TryGetContainerSlotEnumerator(entity.Value, out var enumerator))
|
||||||
_inventory.TryGetSlots(entity.Value, out var slots, inventory))
|
|
||||||
{
|
{
|
||||||
foreach (var slot in slots)
|
while (enumerator.NextItem(out var item, out var slot))
|
||||||
{
|
{
|
||||||
if (_inventory.TryUnequip(entity.Value, entity.Value, slot.Name, out var item, true, true))
|
if (_inventory.TryUnequip(entity.Value, entity.Value, slot.Name, true, true))
|
||||||
{
|
_physics.ApplyAngularImpulse(item, ThrowingSystem.ThrowAngularImpulse);
|
||||||
_physics.ApplyAngularImpulse(item.Value, ThrowingSystem.ThrowAngularImpulse);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -285,27 +285,7 @@ public sealed partial class AdminVerbSystem
|
|||||||
Text = "Refill Internals Oxygen",
|
Text = "Refill Internals Oxygen",
|
||||||
Category = VerbCategory.Tricks,
|
Category = VerbCategory.Tricks,
|
||||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
|
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
|
||||||
Act = () =>
|
Act = () => RefillEquippedTanks(args.User, Gas.Oxygen),
|
||||||
{
|
|
||||||
foreach (var slot in _inventorySystem.GetSlots(args.Target))
|
|
||||||
{
|
|
||||||
if (!_inventorySystem.TryGetSlotEntity(args.Target, slot.Name, out var entity))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!TryComp(entity, out tank))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RefillGasTank(entity.Value, Gas.Oxygen, tank);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var held in _handsSystem.EnumerateHeld(args.Target))
|
|
||||||
{
|
|
||||||
if (!TryComp(held, out tank))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RefillGasTank(held, Gas.Oxygen, tank);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Impact = LogImpact.Extreme,
|
Impact = LogImpact.Extreme,
|
||||||
Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
|
Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
|
||||||
Priority = (int) TricksVerbPriorities.RefillOxygen,
|
Priority = (int) TricksVerbPriorities.RefillOxygen,
|
||||||
@@ -317,27 +297,7 @@ public sealed partial class AdminVerbSystem
|
|||||||
Text = "Refill Internals Nitrogen",
|
Text = "Refill Internals Nitrogen",
|
||||||
Category = VerbCategory.Tricks,
|
Category = VerbCategory.Tricks,
|
||||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
|
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
|
||||||
Act = () =>
|
Act = () =>RefillEquippedTanks(args.User, Gas.Nitrogen),
|
||||||
{
|
|
||||||
foreach (var slot in _inventorySystem.GetSlots(args.Target))
|
|
||||||
{
|
|
||||||
if (!_inventorySystem.TryGetSlotEntity(args.Target, slot.Name, out var entity))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!TryComp(entity, out tank))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RefillGasTank(entity.Value, Gas.Nitrogen, tank);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var held in _handsSystem.EnumerateHeld(args.Target))
|
|
||||||
{
|
|
||||||
if (!TryComp(held, out tank))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RefillGasTank(held, Gas.Nitrogen, tank);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Impact = LogImpact.Extreme,
|
Impact = LogImpact.Extreme,
|
||||||
Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
|
Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
|
||||||
Priority = (int) TricksVerbPriorities.RefillNitrogen,
|
Priority = (int) TricksVerbPriorities.RefillNitrogen,
|
||||||
@@ -349,27 +309,7 @@ public sealed partial class AdminVerbSystem
|
|||||||
Text = "Refill Internals Plasma",
|
Text = "Refill Internals Plasma",
|
||||||
Category = VerbCategory.Tricks,
|
Category = VerbCategory.Tricks,
|
||||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
|
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
|
||||||
Act = () =>
|
Act = () => RefillEquippedTanks(args.User, Gas.Plasma),
|
||||||
{
|
|
||||||
foreach (var slot in _inventorySystem.GetSlots(args.Target))
|
|
||||||
{
|
|
||||||
if (!_inventorySystem.TryGetSlotEntity(args.Target, slot.Name, out var entity))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!TryComp(entity, out tank))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RefillGasTank(entity.Value, Gas.Plasma, tank);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var held in _handsSystem.EnumerateHeld(args.Target))
|
|
||||||
{
|
|
||||||
if (!TryComp(held, out tank))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RefillGasTank(held, Gas.Plasma, tank);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Impact = LogImpact.Extreme,
|
Impact = LogImpact.Extreme,
|
||||||
Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
|
Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
|
||||||
Priority = (int) TricksVerbPriorities.RefillPlasma,
|
Priority = (int) TricksVerbPriorities.RefillPlasma,
|
||||||
@@ -792,9 +732,17 @@ public sealed partial class AdminVerbSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefillGasTank(EntityUid tank, Gas gasType, GasTankComponent? tankComponent)
|
private void RefillEquippedTanks(EntityUid target, Gas plasma)
|
||||||
{
|
{
|
||||||
if (!Resolve(tank, ref tankComponent))
|
foreach (var held in _inventorySystem.GetHandOrInventoryEntities(target))
|
||||||
|
{
|
||||||
|
RefillGasTank(held, Gas.Plasma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefillGasTank(EntityUid tank, Gas gasType, GasTankComponent? tankComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(tank, ref tankComponent, false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var mixSize = tankComponent.Air.Volume;
|
var mixSize = tankComponent.Air.Volume;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Server.Popups;
|
|||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Hands.Components;
|
||||||
using Content.Shared.Internals;
|
using Content.Shared.Internals;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
@@ -26,6 +27,8 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
|
public const SlotFlags InventorySlots = SlotFlags.POCKET | SlotFlags.BELT;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -81,7 +84,7 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tank = FindBestGasTank(uid, internals);
|
var tank = FindBestGasTank(uid);
|
||||||
|
|
||||||
if (tank == null)
|
if (tank == null)
|
||||||
{
|
{
|
||||||
@@ -224,59 +227,35 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity<GasTankComponent>? FindBestGasTank(EntityUid internalsOwner, InternalsComponent component)
|
public Entity<GasTankComponent>? FindBestGasTank(Entity<HandsComponent?, InventoryComponent?, ContainerManagerComponent?> user)
|
||||||
{
|
{
|
||||||
// Prioritise
|
// Prioritise
|
||||||
// 1. back equipped tanks
|
// 1. back equipped tanks
|
||||||
// 2. exo-slot tanks
|
// 2. exo-slot tanks
|
||||||
// 3. in-hand tanks
|
// 3. in-hand tanks
|
||||||
// 4. pocket/belt tanks
|
// 4. pocket/belt tanks
|
||||||
InventoryComponent? inventory = null;
|
|
||||||
ContainerManagerComponent? containerManager = null;
|
|
||||||
|
|
||||||
if (_inventory.TryGetSlotEntity(internalsOwner, "back", out var backEntity, inventory, containerManager) &&
|
if (!Resolve(user.Owner, ref user.Comp1, ref user.Comp2, ref user.Comp3))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (_inventory.TryGetSlotEntity(user.Owner, "back", out var backEntity, user.Comp2, user.Comp3) &&
|
||||||
TryComp<GasTankComponent>(backEntity, out var backGasTank) &&
|
TryComp<GasTankComponent>(backEntity, out var backGasTank) &&
|
||||||
_gasTank.CanConnectToInternals(backGasTank))
|
_gasTank.CanConnectToInternals(backGasTank))
|
||||||
{
|
{
|
||||||
return (backEntity.Value, backGasTank);
|
return (backEntity.Value, backGasTank);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_inventory.TryGetSlotEntity(internalsOwner, "suitstorage", out var entity, inventory, containerManager) &&
|
if (_inventory.TryGetSlotEntity(user.Owner, "suitstorage", out var entity, user.Comp2, user.Comp3) &&
|
||||||
TryComp<GasTankComponent>(entity, out var gasTank) &&
|
TryComp<GasTankComponent>(entity, out var gasTank) &&
|
||||||
_gasTank.CanConnectToInternals(gasTank))
|
_gasTank.CanConnectToInternals(gasTank))
|
||||||
{
|
{
|
||||||
return (entity.Value, gasTank);
|
return (entity.Value, gasTank);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tanks = new List<Entity<GasTankComponent>>();
|
foreach (var item in _inventory.GetHandOrInventoryEntities((user.Owner, user.Comp1, user.Comp2)))
|
||||||
|
|
||||||
foreach (var hand in _hands.EnumerateHands(internalsOwner))
|
|
||||||
{
|
{
|
||||||
if (TryComp(hand.HeldEntity, out gasTank) && _gasTank.CanConnectToInternals(gasTank))
|
if (TryComp(item, out gasTank) && _gasTank.CanConnectToInternals(gasTank))
|
||||||
tanks.Add((hand.HeldEntity.Value, gasTank));
|
return (item, gasTank);
|
||||||
}
|
|
||||||
|
|
||||||
if (tanks.Count > 0)
|
|
||||||
{
|
|
||||||
tanks.Sort((x, y) => y.Comp.Air.TotalMoles.CompareTo(x.Comp.Air.TotalMoles));
|
|
||||||
return tanks[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Resolve(internalsOwner, ref inventory, false))
|
|
||||||
{
|
|
||||||
var enumerator = new InventorySystem.ContainerSlotEnumerator(internalsOwner, inventory.TemplateId, _protoManager, _inventory, SlotFlags.POCKET | SlotFlags.BELT);
|
|
||||||
|
|
||||||
while (enumerator.MoveNext(out var container))
|
|
||||||
{
|
|
||||||
if (TryComp(container.ContainedEntity, out gasTank) && _gasTank.CanConnectToInternals(gasTank))
|
|
||||||
tanks.Add((container.ContainedEntity.Value, gasTank));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tanks.Count > 0)
|
|
||||||
{
|
|
||||||
tanks.Sort((x, y) => y.Comp.Air.TotalMoles.CompareTo(x.Comp.Air.TotalMoles));
|
|
||||||
return tanks[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -35,16 +35,14 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.BlockSlots != 0x0 && TryComp<InventoryComponent>(target, out var inventory))
|
if (component.BlockSlots != 0x0)
|
||||||
{
|
{
|
||||||
var containerEnumerator = new InventorySystem.ContainerSlotEnumerator(target, inventory.TemplateId, _protoManager, _inventorySystem, component.BlockSlots);
|
var containerEnumerator = _inventorySystem.GetSlotEnumerator(target, component.BlockSlots);
|
||||||
|
|
||||||
while (containerEnumerator.MoveNext(out var container))
|
// TODO add a helper method for this?
|
||||||
{
|
if (containerEnumerator.MoveNext(out _))
|
||||||
if (!container.ContainedEntity.HasValue) continue;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var solRemoved = solution.SplitSolution(component.TransferAmount);
|
var solRemoved = solution.SplitSolution(component.TransferAmount);
|
||||||
var solRemovedVol = solRemoved.Volume;
|
var solRemovedVol = solRemoved.Volume;
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ namespace Content.Server.Inventory
|
|||||||
|
|
||||||
private void OnExploded(Entity<InventoryComponent> ent, ref BeforeExplodeEvent args)
|
private void OnExploded(Entity<InventoryComponent> ent, ref BeforeExplodeEvent args)
|
||||||
{
|
{
|
||||||
if (!TryGetContainerSlotEnumerator(ent, out var slots, ent.Comp))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// explode each item in their inventory too
|
// explode each item in their inventory too
|
||||||
|
var slots = new InventorySlotEnumerator(ent);
|
||||||
while (slots.MoveNext(out var slot))
|
while (slots.MoveNext(out var slot))
|
||||||
{
|
{
|
||||||
if (slot.ContainedEntity != null)
|
if (slot.ContainedEntity != null)
|
||||||
@@ -55,33 +53,16 @@ namespace Content.Server.Inventory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TransferEntityInventories(EntityUid uid, EntityUid target)
|
public void TransferEntityInventories(Entity<InventoryComponent?> source, Entity<InventoryComponent?> target)
|
||||||
{
|
{
|
||||||
if (!TryGetContainerSlotEnumerator(uid, out var enumerator))
|
if (!Resolve(source.Owner, ref source.Comp) || !Resolve(target.Owner, ref target.Comp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Dictionary<string, EntityUid> inventoryEntities = new();
|
var enumerator = new InventorySlotEnumerator(source.Comp);
|
||||||
var slots = GetSlots(uid);
|
while (enumerator.NextItem(out var item, out var slot))
|
||||||
while (enumerator.MoveNext(out var containerSlot))
|
|
||||||
{
|
{
|
||||||
//records all the entities stored in each of the target's slots
|
if (TryUnequip(source, slot.Name, true, true, inventory: source.Comp))
|
||||||
foreach (var slot in slots)
|
TryEquip(target, item, slot.Name , true, true, inventory: target.Comp);
|
||||||
{
|
|
||||||
if (TryGetSlotContainer(target, slot.Name, out var conslot, out _) &&
|
|
||||||
conslot.ID == containerSlot.ID &&
|
|
||||||
containerSlot.ContainedEntity is { } containedEntity)
|
|
||||||
{
|
|
||||||
inventoryEntities.Add(slot.Name, containedEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//drops everything in the target's inventory on the ground
|
|
||||||
TryUnequip(uid, containerSlot.ID, true, true);
|
|
||||||
}
|
|
||||||
// This takes the objects we removed and stored earlier
|
|
||||||
// and actually equips all of it to the new entity
|
|
||||||
foreach (var (slot, item) in inventoryEntities)
|
|
||||||
{
|
|
||||||
TryEquip(target, item, slot , true, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ public sealed class StressTestMovementSystem : EntitySystem
|
|||||||
|
|
||||||
while (query.MoveNext(out var uid, out var stressTest, out var transform))
|
while (query.MoveNext(out var uid, out var stressTest, out var transform))
|
||||||
{
|
{
|
||||||
|
if (!transform.ParentUid.IsValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
stressTest.Progress += frameTime;
|
stressTest.Progress += frameTime;
|
||||||
|
|
||||||
if (stressTest.Progress > 1)
|
if (stressTest.Progress > 1)
|
||||||
|
|||||||
@@ -40,6 +40,16 @@ namespace Content.Server.Zombies
|
|||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
|
||||||
|
public const SlotFlags ProtectiveSlots =
|
||||||
|
SlotFlags.FEET |
|
||||||
|
SlotFlags.HEAD |
|
||||||
|
SlotFlags.EYES |
|
||||||
|
SlotFlags.GLOVES |
|
||||||
|
SlotFlags.MASK |
|
||||||
|
SlotFlags.NECK |
|
||||||
|
SlotFlags.INNERCLOTHING |
|
||||||
|
SlotFlags.OUTERCLOTHING;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -164,33 +174,27 @@ namespace Content.Server.Zombies
|
|||||||
|
|
||||||
private float GetZombieInfectionChance(EntityUid uid, ZombieComponent component)
|
private float GetZombieInfectionChance(EntityUid uid, ZombieComponent component)
|
||||||
{
|
{
|
||||||
var baseChance = component.MaxZombieInfectionChance;
|
var max = component.MaxZombieInfectionChance;
|
||||||
|
|
||||||
if (!TryComp<InventoryComponent>(uid, out var inventoryComponent))
|
if (!_inventory.TryGetContainerSlotEnumerator(uid, out var enumerator, ProtectiveSlots))
|
||||||
return baseChance;
|
return max;
|
||||||
|
|
||||||
var enumerator =
|
|
||||||
new InventorySystem.ContainerSlotEnumerator(uid, inventoryComponent.TemplateId, _protoManager, _inv,
|
|
||||||
SlotFlags.FEET |
|
|
||||||
SlotFlags.HEAD |
|
|
||||||
SlotFlags.EYES |
|
|
||||||
SlotFlags.GLOVES |
|
|
||||||
SlotFlags.MASK |
|
|
||||||
SlotFlags.NECK |
|
|
||||||
SlotFlags.INNERCLOTHING |
|
|
||||||
SlotFlags.OUTERCLOTHING);
|
|
||||||
|
|
||||||
var items = 0f;
|
var items = 0f;
|
||||||
var total = 0f;
|
var total = 0f;
|
||||||
while (enumerator.MoveNext(out var con))
|
while (enumerator.MoveNext(out var con))
|
||||||
{
|
{
|
||||||
total++;
|
total++;
|
||||||
|
|
||||||
if (con.ContainedEntity != null)
|
if (con.ContainedEntity != null)
|
||||||
items++;
|
items++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var max = component.MaxZombieInfectionChance;
|
if (total == 0)
|
||||||
|
return max;
|
||||||
|
|
||||||
|
// Everyone knows that when it comes to zombies, socks & sandals provide just as much protection as an
|
||||||
|
// armored vest. Maybe these should be weighted per-item. I.e. some kind of coverage/protection component.
|
||||||
|
// Or at the very least different weights per slot.
|
||||||
|
|
||||||
var min = component.MinZombieInfectionChance;
|
var min = component.MinZombieInfectionChance;
|
||||||
//gets a value between the max and min based on how many items the entity is wearing
|
//gets a value between the max and min based on how many items the entity is wearing
|
||||||
var chance = (max-min) * ((total - items)/total) + min;
|
var chance = (max-min) * ((total - items)/total) + min;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Shared.Inventory;
|
namespace Content.Shared.Inventory;
|
||||||
@@ -11,4 +12,7 @@ public sealed partial class InventoryComponent : Component
|
|||||||
public string TemplateId { get; private set; } = "human";
|
public string TemplateId { get; private set; } = "human";
|
||||||
|
|
||||||
[DataField("speciesId")] public string? SpeciesId { get; set; }
|
[DataField("speciesId")] public string? SpeciesId { get; set; }
|
||||||
|
|
||||||
|
public SlotDefinition[] Slots = Array.Empty<SlotDefinition>();
|
||||||
|
public ContainerSlot[] Containers = Array.Empty<ContainerSlot>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using Robust.Shared.Network;
|
|||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.Inventory;
|
namespace Content.Shared.Inventory;
|
||||||
|
|
||||||
@@ -47,12 +48,10 @@ public abstract partial class InventorySystem
|
|||||||
|
|
||||||
protected void QuickEquip(EntityUid uid, ClothingComponent component, UseInHandEvent args)
|
protected void QuickEquip(EntityUid uid, ClothingComponent component, UseInHandEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp(args.User, out InventoryComponent? inv)
|
if (!TryComp(args.User, out InventoryComponent? inv) || !HasComp<HandsComponent>(args.User))
|
||||||
|| !TryComp(args.User, out HandsComponent? hands)
|
|
||||||
|| !_prototypeManager.TryIndex<InventoryTemplatePrototype>(inv.TemplateId, out var prototype))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var slotDef in prototype.Slots)
|
foreach (var slotDef in inv.Slots)
|
||||||
{
|
{
|
||||||
if (!CanEquip(args.User, uid, slotDef.Name, out _, slotDef, inv))
|
if (!CanEquip(args.User, uid, slotDef.Name, out _, slotDef, inv))
|
||||||
continue;
|
continue;
|
||||||
@@ -255,6 +254,7 @@ public abstract partial class InventorySystem
|
|||||||
if (slotDefinition == null && !TryGetSlot(target, slot, out slotDefinition, inventory: inventory))
|
if (slotDefinition == null && !TryGetSlot(target, slot, out slotDefinition, inventory: inventory))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
DebugTools.Assert(slotDefinition.Name == slot);
|
||||||
if (slotDefinition.DependsOn != null && !TryGetSlotEntity(target, slotDefinition.DependsOn, out _, inventory))
|
if (slotDefinition.DependsOn != null && !TryGetSlotEntity(target, slotDefinition.DependsOn, out _, inventory))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -347,7 +347,8 @@ public abstract partial class InventorySystem
|
|||||||
|
|
||||||
removedItem = slotContainer.ContainedEntity;
|
removedItem = slotContainer.ContainedEntity;
|
||||||
|
|
||||||
if (!removedItem.HasValue) return false;
|
if (!removedItem.HasValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!force && !CanUnequip(actor, target, slot, out var reason, slotContainer, slotDefinition, inventory))
|
if (!force && !CanUnequip(actor, target, slot, out var reason, slotContainer, slotDefinition, inventory))
|
||||||
{
|
{
|
||||||
@@ -360,7 +361,7 @@ public abstract partial class InventorySystem
|
|||||||
if (!force && !_containerSystem.CanRemove(removedItem.Value, slotContainer))
|
if (!force && !_containerSystem.CanRemove(removedItem.Value, slotContainer))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var slotDef in GetSlots(target, inventory))
|
foreach (var slotDef in inventory.Slots)
|
||||||
{
|
{
|
||||||
if (slotDef != slotDefinition && slotDef.DependsOn == slotDefinition.Name)
|
if (slotDef != slotDefinition && slotDef.DependsOn == slotDefinition.Name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ public partial class InventorySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Yields all entities in hands or inventory slots with the specific flags.
|
/// Yields all entities in hands or inventory slots with the specific flags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<EntityUid> GetHandOrInventoryEntities(EntityUid user, SlotFlags flags = SlotFlags.All)
|
public IEnumerable<EntityUid> GetHandOrInventoryEntities(Entity<HandsComponent?, InventoryComponent?> user, SlotFlags flags = SlotFlags.All)
|
||||||
{
|
{
|
||||||
if (TryComp<HandsComponent>(user, out var handsComp))
|
if (Resolve(user.Owner, ref user.Comp1, false))
|
||||||
{
|
{
|
||||||
foreach (var hand in handsComp.Hands.Values)
|
foreach (var hand in user.Comp1.Hands.Values)
|
||||||
{
|
{
|
||||||
if (hand.HeldEntity == null)
|
if (hand.HeldEntity == null)
|
||||||
continue;
|
continue;
|
||||||
@@ -23,27 +23,22 @@ public partial class InventorySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryComp<InventoryComponent>(user, out var inventoryComp))
|
if (!Resolve(user.Owner, ref user.Comp2, false))
|
||||||
{
|
yield break;
|
||||||
var slotEnumerator = new ContainerSlotEnumerator(user, inventoryComp.TemplateId,
|
|
||||||
_prototypeManager, this, flags);
|
|
||||||
|
|
||||||
while (slotEnumerator.MoveNext(out var slot))
|
var slotEnumerator = new InventorySlotEnumerator(user.Comp2, flags);
|
||||||
|
while (slotEnumerator.NextItem(out var item))
|
||||||
{
|
{
|
||||||
if (slot.ContainedEntity == null)
|
yield return item;
|
||||||
continue;
|
|
||||||
|
|
||||||
yield return slot.ContainedEntity.Value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the definition of the inventory slot that the given entity is currently in..
|
/// Returns the definition of the inventory slot that the given entity is currently in..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryGetContainingSlot(EntityUid uid, [NotNullWhen(true)] out SlotDefinition? slot)
|
public bool TryGetContainingSlot(Entity<TransformComponent?, MetaDataComponent?> entity, [NotNullWhen(true)] out SlotDefinition? slot)
|
||||||
{
|
{
|
||||||
if (!_containerSystem.TryGetContainingContainer(uid, out var container))
|
if (!_containerSystem.TryGetContainingContainer(entity.Owner, out var container, entity.Comp2, entity.Comp1))
|
||||||
{
|
{
|
||||||
slot = null;
|
slot = null;
|
||||||
return false;
|
return false;
|
||||||
@@ -55,9 +50,10 @@ public partial class InventorySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if the given entity is equipped to an inventory slot with the given inventory slot flags.
|
/// Returns true if the given entity is equipped to an inventory slot with the given inventory slot flags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool InSlotWithFlags(EntityUid uid, SlotFlags flags)
|
public bool InSlotWithFlags(Entity<TransformComponent?, MetaDataComponent?> entity, SlotFlags flags)
|
||||||
{
|
{
|
||||||
return TryGetContainingSlot(uid, out var slot) && ((slot.SlotFlags & flags) == flags);
|
return TryGetContainingSlot(entity, out var slot)
|
||||||
|
&& (slot.SlotFlags & flags) == flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SpawnItemInSlot(EntityUid uid, string slot, string prototype, bool silent = false, bool force = false, InventoryComponent? inventory = null)
|
public bool SpawnItemInSlot(EntityUid uid, string slot, string prototype, bool silent = false, bool force = false, InventoryComponent? inventory = null)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ using Content.Shared.Slippery;
|
|||||||
using Content.Shared.Strip.Components;
|
using Content.Shared.Strip.Components;
|
||||||
using Content.Shared.Temperature;
|
using Content.Shared.Temperature;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Containers;
|
|
||||||
|
|
||||||
namespace Content.Shared.Inventory;
|
namespace Content.Shared.Inventory;
|
||||||
|
|
||||||
@@ -59,17 +58,15 @@ public partial class InventorySystem
|
|||||||
|
|
||||||
public void RelayEvent<T>(Entity<InventoryComponent> inventory, ref T args) where T : IInventoryRelayEvent
|
public void RelayEvent<T>(Entity<InventoryComponent> inventory, ref T args) where T : IInventoryRelayEvent
|
||||||
{
|
{
|
||||||
var containerEnumerator = new ContainerSlotEnumerator(inventory, inventory.Comp.TemplateId, _prototypeManager, this, args.TargetSlots);
|
if (args.TargetSlots == SlotFlags.NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
// this copies the by-ref event if it is a struct
|
// this copies the by-ref event if it is a struct
|
||||||
var ev = new InventoryRelayedEvent<T>(args);
|
var ev = new InventoryRelayedEvent<T>(args);
|
||||||
|
var enumerator = new InventorySlotEnumerator(inventory, args.TargetSlots);
|
||||||
while (containerEnumerator.MoveNext(out var container))
|
while (enumerator.NextItem(out var item))
|
||||||
{
|
{
|
||||||
if (!container.ContainedEntity.HasValue)
|
RaiseLocalEvent(item, ev);
|
||||||
continue;
|
|
||||||
|
|
||||||
RaiseLocalEvent(container.ContainedEntity.Value, ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// and now we copy it back
|
// and now we copy it back
|
||||||
@@ -81,40 +78,23 @@ public partial class InventorySystem
|
|||||||
if (args.TargetSlots == SlotFlags.NONE)
|
if (args.TargetSlots == SlotFlags.NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var containerEnumerator = new ContainerSlotEnumerator(inventory, inventory.Comp.TemplateId, _prototypeManager, this, args.TargetSlots);
|
|
||||||
var ev = new InventoryRelayedEvent<T>(args);
|
var ev = new InventoryRelayedEvent<T>(args);
|
||||||
while (containerEnumerator.MoveNext(out var container))
|
var enumerator = new InventorySlotEnumerator(inventory, args.TargetSlots);
|
||||||
|
while (enumerator.NextItem(out var item))
|
||||||
{
|
{
|
||||||
if (!container.ContainedEntity.HasValue)
|
RaiseLocalEvent(item, ev);
|
||||||
continue;
|
|
||||||
|
|
||||||
RaiseLocalEvent(container.ContainedEntity.Value, ev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGetEquipmentVerbs(EntityUid uid, InventoryComponent component, GetVerbsEvent<EquipmentVerb> args)
|
private void OnGetEquipmentVerbs(EntityUid uid, InventoryComponent component, GetVerbsEvent<EquipmentVerb> args)
|
||||||
{
|
{
|
||||||
// Automatically relay stripping related verbs to all equipped clothing.
|
// Automatically relay stripping related verbs to all equipped clothing.
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex(component.TemplateId, out InventoryTemplatePrototype? proto))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!TryComp(uid, out ContainerManagerComponent? containers))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var ev = new InventoryRelayedEvent<GetVerbsEvent<EquipmentVerb>>(args);
|
var ev = new InventoryRelayedEvent<GetVerbsEvent<EquipmentVerb>>(args);
|
||||||
foreach (var slotDef in proto.Slots)
|
var enumerator = new InventorySlotEnumerator(component);
|
||||||
|
while (enumerator.NextItem(out var item, out var slotDef))
|
||||||
{
|
{
|
||||||
if (slotDef.StripHidden && args.User != uid)
|
if (!slotDef.StripHidden || args.User == uid)
|
||||||
continue;
|
RaiseLocalEvent(item, ev);
|
||||||
|
|
||||||
if (!containers.TryGetContainer(slotDef.Name, out var container))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (container is not ContainerSlot slot || slot.ContainedEntity is not { } ent)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RaiseLocalEvent(ent, ev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.Inventory;
|
namespace Content.Shared.Inventory;
|
||||||
|
|
||||||
@@ -28,9 +29,14 @@ public partial class InventorySystem : EntitySystem
|
|||||||
if (!_prototypeManager.TryIndex(component.TemplateId, out InventoryTemplatePrototype? invTemplate))
|
if (!_prototypeManager.TryIndex(component.TemplateId, out InventoryTemplatePrototype? invTemplate))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var slot in invTemplate.Slots)
|
component.Slots = invTemplate.Slots;
|
||||||
|
component.Containers = new ContainerSlot[component.Slots.Length];
|
||||||
|
for (var i = 0; i < component.Containers.Length; i++)
|
||||||
{
|
{
|
||||||
_containerSystem.EnsureContainer<ContainerSlot>(uid, slot.Name).OccludesLight = false;
|
var slot = component.Slots[i];
|
||||||
|
var container = _containerSystem.EnsureContainer<ContainerSlot>(uid, slot.Name);
|
||||||
|
container.OccludesLight = false;
|
||||||
|
component.Containers[i] = container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +58,8 @@ public partial class InventorySystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container is not ContainerSlot containerSlotChecked) return false;
|
if (container is not ContainerSlot containerSlotChecked)
|
||||||
|
return false;
|
||||||
|
|
||||||
containerSlot = containerSlotChecked;
|
containerSlot = containerSlotChecked;
|
||||||
return true;
|
return true;
|
||||||
@@ -67,12 +74,10 @@ public partial class InventorySystem : EntitySystem
|
|||||||
if (!Resolve(uid, ref inventory, false))
|
if (!Resolve(uid, ref inventory, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex<InventoryTemplatePrototype>(inventory.TemplateId, out var templatePrototype))
|
foreach (var slotDef in inventory.Slots)
|
||||||
return false;
|
|
||||||
|
|
||||||
foreach (var slotDef in templatePrototype.Slots)
|
|
||||||
{
|
{
|
||||||
if (!slotDef.Name.Equals(slot)) continue;
|
if (!slotDef.Name.Equals(slot))
|
||||||
|
continue;
|
||||||
slotDefinition = slotDef;
|
slotDefinition = slotDef;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -80,33 +85,36 @@ public partial class InventorySystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetContainerSlotEnumerator(EntityUid uid, out ContainerSlotEnumerator containerSlotEnumerator, InventoryComponent? component = null)
|
public bool TryGetContainerSlotEnumerator(Entity<InventoryComponent?> entity, out InventorySlotEnumerator containerSlotEnumerator, SlotFlags flags = SlotFlags.All)
|
||||||
|
{
|
||||||
|
if (!Resolve(entity.Owner, ref entity.Comp))
|
||||||
{
|
{
|
||||||
containerSlotEnumerator = default;
|
containerSlotEnumerator = default;
|
||||||
if (!Resolve(uid, ref component, false))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
containerSlotEnumerator = new ContainerSlotEnumerator(uid, component.TemplateId, _prototypeManager, this);
|
containerSlotEnumerator = new InventorySlotEnumerator(entity.Comp, flags);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetSlots(EntityUid uid, [NotNullWhen(true)] out SlotDefinition[]? slotDefinitions, InventoryComponent? inventoryComponent = null)
|
public InventorySlotEnumerator GetSlotEnumerator(Entity<InventoryComponent?> entity, SlotFlags flags = SlotFlags.All)
|
||||||
|
{
|
||||||
|
if (!Resolve(entity.Owner, ref entity.Comp))
|
||||||
|
return InventorySlotEnumerator.Empty;
|
||||||
|
|
||||||
|
return new InventorySlotEnumerator(entity.Comp, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetSlots(EntityUid uid, [NotNullWhen(true)] out SlotDefinition[]? slotDefinitions)
|
||||||
|
{
|
||||||
|
if (!TryComp(uid, out InventoryComponent? inv))
|
||||||
{
|
{
|
||||||
slotDefinitions = null;
|
slotDefinitions = null;
|
||||||
if (!Resolve(uid, ref inventoryComponent, false))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex<InventoryTemplatePrototype>(inventoryComponent.TemplateId, out var templatePrototype))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
slotDefinitions = templatePrototype.Slots;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlotDefinition[] GetSlots(EntityUid uid, InventoryComponent? inventoryComponent = null)
|
slotDefinitions = inv.Slots;
|
||||||
{
|
return true;
|
||||||
if (!Resolve(uid, ref inventoryComponent)) throw new InvalidOperationException();
|
|
||||||
return _prototypeManager.Index<InventoryTemplatePrototype>(inventoryComponent.TemplateId).Slots;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ViewVariablesPath? HandleViewVariablesSlots(EntityUid uid, InventoryComponent comp, string relativePath)
|
private ViewVariablesPath? HandleViewVariablesSlots(EntityUid uid, InventoryComponent comp, string relativePath)
|
||||||
@@ -118,48 +126,98 @@ public partial class InventorySystem : EntitySystem
|
|||||||
|
|
||||||
private IEnumerable<string> ListViewVariablesSlots(EntityUid uid, InventoryComponent comp)
|
private IEnumerable<string> ListViewVariablesSlots(EntityUid uid, InventoryComponent comp)
|
||||||
{
|
{
|
||||||
foreach (var slotDef in GetSlots(uid, comp))
|
foreach (var slotDef in comp.Slots)
|
||||||
{
|
{
|
||||||
yield return slotDef.Name;
|
yield return slotDef.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ContainerSlotEnumerator
|
/// <summary>
|
||||||
|
/// Enumerator for iterating over an inventory's slot containers. Also has methods that skip empty containers.
|
||||||
|
/// It should be safe to add or remove items while enumerating.
|
||||||
|
/// </summary>
|
||||||
|
public struct InventorySlotEnumerator
|
||||||
{
|
{
|
||||||
private readonly InventorySystem _inventorySystem;
|
|
||||||
private readonly EntityUid _uid;
|
|
||||||
private readonly SlotDefinition[] _slots;
|
private readonly SlotDefinition[] _slots;
|
||||||
|
private readonly ContainerSlot[] _containers;
|
||||||
private readonly SlotFlags _flags;
|
private readonly SlotFlags _flags;
|
||||||
private int _nextIdx = 0;
|
private int _nextIdx = 0;
|
||||||
|
public static InventorySlotEnumerator Empty = new(Array.Empty<SlotDefinition>(), Array.Empty<ContainerSlot>());
|
||||||
|
|
||||||
public ContainerSlotEnumerator(EntityUid uid, string prototypeId, IPrototypeManager prototypeManager, InventorySystem inventorySystem, SlotFlags flags = SlotFlags.All)
|
public InventorySlotEnumerator(InventoryComponent inventory, SlotFlags flags = SlotFlags.All)
|
||||||
|
: this(inventory.Slots, inventory.Containers, flags)
|
||||||
{
|
{
|
||||||
_uid = uid;
|
}
|
||||||
_inventorySystem = inventorySystem;
|
|
||||||
_flags = flags;
|
|
||||||
|
|
||||||
if (prototypeManager.TryIndex<InventoryTemplatePrototype>(prototypeId, out var prototype))
|
public InventorySlotEnumerator(SlotDefinition[] slots, ContainerSlot[] containers, SlotFlags flags = SlotFlags.All)
|
||||||
_slots = prototype.Slots;
|
{
|
||||||
else
|
DebugTools.Assert(flags != SlotFlags.NONE);
|
||||||
_slots = Array.Empty<SlotDefinition>();
|
DebugTools.AssertEqual(slots.Length, containers.Length);
|
||||||
|
_flags = flags;
|
||||||
|
_slots = slots;
|
||||||
|
_containers = containers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MoveNext([NotNullWhen(true)] out ContainerSlot? container)
|
public bool MoveNext([NotNullWhen(true)] out ContainerSlot? container)
|
||||||
{
|
{
|
||||||
container = null;
|
|
||||||
|
|
||||||
while (_nextIdx < _slots.Length)
|
while (_nextIdx < _slots.Length)
|
||||||
{
|
{
|
||||||
var slot = _slots[_nextIdx];
|
var i = _nextIdx++;
|
||||||
_nextIdx++;
|
var slot = _slots[i];
|
||||||
|
|
||||||
if ((slot.SlotFlags & _flags) == 0)
|
if ((slot.SlotFlags & _flags) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_inventorySystem.TryGetSlotContainer(_uid, slot.Name, out container, out _))
|
container = _containers[i];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool NextItem(out EntityUid item)
|
||||||
|
{
|
||||||
|
while (_nextIdx < _slots.Length)
|
||||||
|
{
|
||||||
|
var i = _nextIdx++;
|
||||||
|
var slot = _slots[i];
|
||||||
|
|
||||||
|
if ((slot.SlotFlags & _flags) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var container = _containers[i];
|
||||||
|
if (container.ContainedEntity is { } uid)
|
||||||
|
{
|
||||||
|
item = uid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool NextItem(out EntityUid item, [NotNullWhen(true)] out SlotDefinition? slot)
|
||||||
|
{
|
||||||
|
while (_nextIdx < _slots.Length)
|
||||||
|
{
|
||||||
|
var i = _nextIdx++;
|
||||||
|
slot = _slots[i];
|
||||||
|
|
||||||
|
if ((slot.SlotFlags & _flags) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var container = _containers[i];
|
||||||
|
if (container.ContainedEntity is { } uid)
|
||||||
|
{
|
||||||
|
item = uid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item = default;
|
||||||
|
slot = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,26 +42,26 @@ public sealed class MagnetPickupSystem : EntitySystem
|
|||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
var query = EntityQueryEnumerator<MagnetPickupComponent, StorageComponent, TransformComponent>();
|
var query = EntityQueryEnumerator<MagnetPickupComponent, StorageComponent, TransformComponent, MetaDataComponent>();
|
||||||
var currentTime = _timing.CurTime;
|
var currentTime = _timing.CurTime;
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out var comp, out var storage, out var xform))
|
while (query.MoveNext(out var uid, out var comp, out var storage, out var xform, out var meta))
|
||||||
{
|
{
|
||||||
if (comp.NextScan > currentTime)
|
if (comp.NextScan > currentTime)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
comp.NextScan += ScanDelay;
|
comp.NextScan += ScanDelay;
|
||||||
|
|
||||||
// No space
|
if (!_inventory.TryGetContainingSlot((uid, xform, meta), out var slotDef))
|
||||||
if (!_storage.HasSpace((uid, storage)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!_inventory.TryGetContainingSlot(uid, out var slotDef))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((slotDef.SlotFlags & comp.SlotFlags) == 0x0)
|
if ((slotDef.SlotFlags & comp.SlotFlags) == 0x0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// No space
|
||||||
|
if (!_storage.HasSpace((uid, storage)))
|
||||||
|
continue;
|
||||||
|
|
||||||
var parentUid = xform.ParentUid;
|
var parentUid = xform.ParentUid;
|
||||||
var playedSound = false;
|
var playedSound = false;
|
||||||
var finalCoords = xform.Coordinates;
|
var finalCoords = xform.Coordinates;
|
||||||
|
|||||||
@@ -32,24 +32,19 @@ public partial class SharedGunSystem
|
|||||||
private bool TryGetClothingSlotEntity(EntityUid uid, ClothingSlotAmmoProviderComponent component, [NotNullWhen(true)] out EntityUid? slotEntity)
|
private bool TryGetClothingSlotEntity(EntityUid uid, ClothingSlotAmmoProviderComponent component, [NotNullWhen(true)] out EntityUid? slotEntity)
|
||||||
{
|
{
|
||||||
slotEntity = null;
|
slotEntity = null;
|
||||||
if (!Containers.TryGetContainingContainer(uid, out var container))
|
|
||||||
return false;
|
|
||||||
var user = container.Owner;
|
|
||||||
|
|
||||||
if (!TryComp<InventoryComponent>(user, out var inventory))
|
if (!_inventory.TryGetContainerSlotEnumerator(uid, out var enumerator, component.TargetSlot))
|
||||||
return false;
|
return false;
|
||||||
var slots = _inventory.GetSlots(user, inventory);
|
|
||||||
foreach (var slot in slots)
|
while (enumerator.NextItem(out var item))
|
||||||
{
|
{
|
||||||
if (slot.SlotFlags != component.TargetSlot)
|
if (component.ProviderWhitelist == null || component.ProviderWhitelist.IsValid(item, EntityManager))
|
||||||
continue;
|
continue;
|
||||||
if (!_inventory.TryGetSlotEntity(user, slot.Name, out var e, inventory))
|
|
||||||
continue;
|
slotEntity = item;
|
||||||
if (component.ProviderWhitelist != null && !component.ProviderWhitelist.IsValid(e.Value, EntityManager))
|
return true;
|
||||||
continue;
|
|
||||||
slotEntity = e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return slotEntity != null;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user