diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index b84a414408..e53fbe21b1 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -68,7 +68,9 @@ + + @@ -121,4 +123,4 @@ - + \ No newline at end of file diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index 6e96ce1976..2a2f4ee15d 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -1,4 +1,5 @@ using Content.Client.GameObjects; +using Content.Client.GameObjects.Components.Clothing; using Content.Client.GameObjects.Components.Construction; using Content.Client.GameObjects.Components.Power; using Content.Client.GameObjects.Components.SmoothWalling; @@ -24,7 +25,6 @@ namespace Content.Client var factory = IoCManager.Resolve(); var prototypes = IoCManager.Resolve(); - factory.RegisterIgnore("Item"); factory.RegisterIgnore("Interactable"); factory.RegisterIgnore("Damageable"); factory.RegisterIgnore("Destructible"); @@ -48,7 +48,6 @@ namespace Content.Client factory.RegisterIgnore("MeleeWeapon"); factory.RegisterIgnore("Storeable"); - factory.RegisterIgnore("Clothing"); factory.RegisterIgnore("Material"); factory.RegisterIgnore("Stack"); @@ -61,6 +60,9 @@ namespace Content.Client factory.Register(); factory.Register(); factory.Register(); + factory.Register(); + factory.Register(); + factory.RegisterReference(); factory.RegisterIgnore("Construction"); factory.RegisterIgnore("Apc"); diff --git a/Content.Client/GameObjects/Components/Clothing/ClothingComponent.cs b/Content.Client/GameObjects/Components/Clothing/ClothingComponent.cs new file mode 100644 index 0000000000..6deb653030 --- /dev/null +++ b/Content.Client/GameObjects/Components/Clothing/ClothingComponent.cs @@ -0,0 +1,27 @@ +using Content.Shared.GameObjects.Components.Inventory; +using SS14.Client.Graphics; + +namespace Content.Client.GameObjects.Components.Clothing +{ + public class ClothingComponent : ItemComponent + { + public override string Name => "Clothing"; + + public (RSI rsi, RSI.StateId stateId)? GetEquippedStateInfo(EquipmentSlotDefines.SlotFlags slot) + { + if (RsiPath == null) + { + return null; + } + + var rsi = GetRSI(); + var stateId = EquippedPrefix != null ? $"{EquippedPrefix}-equipped-{slot}" : $"equipped-{slot}"; + if (rsi.TryGetState(stateId, out _)) + { + return (rsi, stateId); + } + + return null; + } + } +} diff --git a/Content.Client/GameObjects/Components/Inventory/ClientInventoryComponent.cs b/Content.Client/GameObjects/Components/Inventory/ClientInventoryComponent.cs index 6b3b85761d..04a03b8473 100644 --- a/Content.Client/GameObjects/Components/Inventory/ClientInventoryComponent.cs +++ b/Content.Client/GameObjects/Components/Inventory/ClientInventoryComponent.cs @@ -6,46 +6,118 @@ using SS14.Client.Interfaces.Input; using SS14.Client.UserInterface; using SS14.Client.UserInterface.Controls; using SS14.Client.UserInterface.CustomControls; -using SS14.Shared.ContentPack; using SS14.Shared.GameObjects; using SS14.Shared.Input; using SS14.Shared.Interfaces.GameObjects; using SS14.Shared.Interfaces.Network; using SS14.Shared.IoC; -using SS14.Shared.Log; -using SS14.Shared.Maths; using SS14.Shared.Serialization; using SS14.Shared.Utility; using System; using System.Collections.Generic; +using System.Linq; +using Content.Client.GameObjects.Components.Clothing; +using SS14.Shared.Interfaces.Reflection; using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines; using static Content.Shared.GameObjects.SharedInventoryComponent.ClientInventoryMessage; -using static Content.Shared.GameObjects.SharedInventoryComponent.ServerInventoryMessage; namespace Content.Client.GameObjects { public class ClientInventoryComponent : SharedInventoryComponent { - private InventoryWindow Window; - private string TemplateName = "HumanInventory"; //stored for serialization purposes + private Dictionary _slots = new Dictionary(); + + private InventoryWindow _window; + private string _templateName = "HumanInventory"; //stored for serialization purposes private InputCmdHandler _openMenuCmdHandler; + private Inventory _inventory; + + private ISpriteComponent _sprite; public override void OnRemove() { base.OnRemove(); - Window.Dispose(); + _window.Dispose(); + } + + public override void OnAdd() + { + base.OnAdd(); + + _openMenuCmdHandler = InputCmdHandler.FromDelegate(session => { _window.AddToScreen(); _window.Open(); }); + } + + public override void Initialize() + { + base.Initialize(); + + var reflectionManager = IoCManager.Resolve(); + var type = reflectionManager.LooseGetType(_templateName); + DebugTools.Assert(type != null); + _inventory = (Inventory)Activator.CreateInstance(type); + + _window = new InventoryWindow(this); + _window.CreateInventory(_inventory); + + if (Owner.TryGetComponent(out _sprite)) + { + foreach (var mask in _inventory.SlotMasks.OrderBy(s => _inventory.SlotDrawingOrder(s))) + { + if (mask == Slots.NONE) + { + continue; + } + _sprite.LayerMapReserveBlank(mask); + } + } + + // Component state already came in but we couldn't set anything visually because, well, we didn't initialize yet. + foreach (var (slot, entity) in _slots) + { + _setSlot(slot, entity); + } } public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); - Window = new InventoryWindow(this); - _openMenuCmdHandler = InputCmdHandler.FromDelegate(session => { Window.AddToScreen(); Window.Open(); }); - serializer.DataField(ref TemplateName, "Template", "HumanInventory"); - Window.CreateInventory(TemplateName); + serializer.DataField(ref _templateName, "Template", "HumanInventory"); + } + + public override void HandleComponentState(ComponentState state) + { + base.HandleComponentState(state); + var cast = (InventoryComponentState) state; + + var doneSlots = new HashSet(); + + var entityManager = IoCManager.Resolve(); + + foreach (var (slot, entityUid) in cast.Entities) + { + if (_slots.ContainsKey(slot)) + { + _slots.Remove(slot); + _clearSlot(slot); + } + + var entity = entityManager.GetEntity(entityUid); + _slots[slot] = entity; + _setSlot(slot, entity); + doneSlots.Add(slot); + } + + foreach (var slot in _slots.Keys.ToList()) + { + if (!doneSlots.Contains(slot)) + { + _clearSlot(slot); + _slots.Remove(slot); + } + } } public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null) @@ -53,18 +125,6 @@ namespace Content.Client.GameObjects var inputMgr = IoCManager.Resolve(); switch (message) { - //Updates what we are storing in UI slots - case ServerInventoryMessage msg: - if (msg.Updatetype == ServerInventoryUpdate.Addition) - { - Window.AddToSlot(msg); - } - else if (msg.Updatetype == ServerInventoryUpdate.Removal) - { - Window.RemoveFromSlot(msg); - } - break; - case PlayerAttachedMsg _: inputMgr.SetInputCommand(ContentKeyFunctions.OpenCharacterMenu, _openMenuCmdHandler); break; @@ -75,6 +135,34 @@ namespace Content.Client.GameObjects } } + private void _setSlot(Slots slot, IEntity entity) + { + if (_sprite != null && entity.TryGetComponent(out ClothingComponent clothing)) + { + var flag = SlotMasks[slot]; + var data = clothing.GetEquippedStateInfo(flag); + if (data == null) + { + _sprite.LayerSetVisible(slot, false); + } + else + { + var (rsi, state) = data.Value; + _sprite.LayerSetVisible(slot, true); + _sprite.LayerSetRSI(slot, rsi); + _sprite.LayerSetState(slot, state); + } + } + + _window?.AddToSlot(slot, entity); + } + + private void _clearSlot(Slots slot) + { + _window?.RemoveFromSlot(slot); + _sprite?.LayerSetVisible(slot, false); + } + public void SendUnequipMessage(Slots slot) { var unequipmessage = new ClientInventoryMessage(slot, ClientInventoryUpdate.Unequip); @@ -109,14 +197,10 @@ namespace Content.Client.GameObjects } /// - /// Creates a grid container filled with slot buttons loaded from an inventory template + /// Creates a grid container filled with slot buttons loaded from an inventory template /// - /// - public void CreateInventory(string TemplateName) + public void CreateInventory(Inventory inventory) { - Type type = AppDomain.CurrentDomain.GetAssemblyByName("Content.Shared").GetType("Content.Shared.GameObjects." + TemplateName); - Inventory inventory = (Inventory)Activator.CreateInstance(type); - elements_x = inventory.Columns; GridContainer = (GridContainer)Contents.GetChild("PanelContainer").GetChild("CenterContainer").GetChild("GridContainer"); @@ -151,14 +235,11 @@ namespace Content.Client.GameObjects /// /// Adds the item we have equipped to the slot texture and prepares the slot button for removal /// - /// - public void AddToSlot(ServerInventoryMessage message) + public void AddToSlot(Slots slot, IEntity entity) { - InventoryButton button = InventorySlots[message.Inventoryslot]; - var entity = IoCManager.Resolve().GetEntity(message.EntityUid); + var button = InventorySlots[slot]; - button.EntityUid = message.EntityUid; - var container = button.GetChild("CenterContainer"); + button.EntityUid = entity.Uid; button.GetChild