Equipment & inhands. (#110)

* Equipment WiP

* Equipment's starting to work.

* Equipment works properly 100% now.

* Inhands work.

Also more clothes.
This commit is contained in:
Pieter-Jan Briers
2018-09-19 18:54:04 +02:00
committed by GitHub
parent c612806ef1
commit 74541e23a4
97 changed files with 1094 additions and 273 deletions

View File

@@ -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;
}
}
}

View File

@@ -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, IEntity> _slots = new Dictionary<Slots, IEntity>();
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<IReflectionManager>();
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<Slots>();
var entityManager = IoCManager.Resolve<IEntityManager>();
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<IInputManager>();
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
}
/// <summary>
/// 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
/// </summary>
/// <param name="TemplateName"></param>
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
/// <summary>
/// Adds the item we have equipped to the slot texture and prepares the slot button for removal
/// </summary>
/// <param name="message"></param>
public void AddToSlot(ServerInventoryMessage message)
public void AddToSlot(Slots slot, IEntity entity)
{
InventoryButton button = InventorySlots[message.Inventoryslot];
var entity = IoCManager.Resolve<IEntityManager>().GetEntity(message.EntityUid);
var button = InventorySlots[slot];
button.EntityUid = message.EntityUid;
var container = button.GetChild("CenterContainer");
button.EntityUid = entity.Uid;
button.GetChild<Button>("Button").OnPressed += RemoveFromInventory;
button.GetChild<Button>("Button").OnPressed -= AddToInventory;
@@ -187,10 +268,9 @@ namespace Content.Client.GameObjects
/// <summary>
/// Remove element from the UI and update its button to blank texture and prepare for insertion again
/// </summary>
/// <param name="message"></param>
public void RemoveFromSlot(ServerInventoryMessage message)
public void RemoveFromSlot(Slots slot)
{
InventoryButton button = InventorySlots[message.Inventoryslot];
var button = InventorySlots[slot];
button.GetChild<SpriteView>("SpriteView").Sprite = null;
button.EntityUid = EntityUid.Invalid;
button.GetChild<Button>("Button").OnPressed -= RemoveFromInventory;

View File

@@ -6,19 +6,60 @@ using SS14.Shared.GameObjects;
using SS14.Shared.Interfaces.GameObjects;
using SS14.Shared.IoC;
using System.Collections.Generic;
using System.Linq;
using SS14.Client.GameObjects;
using SS14.Client.Interfaces.GameObjects.Components;
using SS14.Shared.Interfaces.Network;
using SS14.Shared.Serialization;
using SS14.Shared.Utility;
using SS14.Shared.ViewVariables;
namespace Content.Client.GameObjects
{
public class HandsComponent : SharedHandsComponent, IHandsComponent
{
private readonly Dictionary<string, IEntity> hands = new Dictionary<string, IEntity>();
[ViewVariables]
public string ActiveIndex { get; private set; }
private HandsGui _gui;
private IUserInterfaceManager _userInterfaceManager;
[ViewVariables] private readonly Dictionary<string, IEntity> _hands = new Dictionary<string, IEntity>();
[ViewVariables] public string ActiveIndex { get; private set; }
[ViewVariables] private ISpriteComponent _sprite;
public override void OnAdd()
{
base.OnAdd();
_userInterfaceManager = IoCManager.Resolve<IUserInterfaceManager>();
}
public override void OnRemove()
{
base.OnRemove();
_gui?.Dispose();
}
public override void Initialize()
{
base.Initialize();
_userInterfaceManager = IoCManager.Resolve<IUserInterfaceManager>();
if (Owner.TryGetComponent(out _sprite))
{
foreach (var slot in _hands.Keys)
{
_sprite.LayerMapReserveBlank($"hand-{slot}");
_setHand(slot, _hands[slot]);
}
}
}
public IEntity GetEntity(string index)
{
if (hands.TryGetValue(index, out var entity))
if (_hands.TryGetValue(index, out var entity))
{
return entity;
}
@@ -28,31 +69,104 @@ namespace Content.Client.GameObjects
public override void HandleComponentState(ComponentState state)
{
var cast = (HandsComponentState)state;
hands.Clear();
foreach (var hand in cast.Hands)
var cast = (HandsComponentState) state;
foreach (var (slot, uid) in cast.Hands)
{
IEntity entity = null;
try
{
entity = Owner.EntityManager.GetEntity(hand.Value);
entity = Owner.EntityManager.GetEntity(uid);
}
catch
{
// Nothing.
}
hands[hand.Key] = entity;
_hands[slot] = entity;
_setHand(slot, entity);
}
foreach (var slot in _hands.Keys.ToList())
{
if (!cast.Hands.ContainsKey(slot))
{
_hands[slot] = null;
_setHand(slot, null);
}
}
ActiveIndex = cast.ActiveIndex;
// Tell UI to update.
var uiMgr = IoCManager.Resolve<IUserInterfaceManager>();
if (!uiMgr.StateRoot.TryGetChild<HandsGui>("HandsGui", out var control))
_gui?.UpdateHandIcons();
}
private void _setHand(string hand, IEntity entity)
{
if (_sprite == null)
{
control = new HandsGui();
uiMgr.StateRoot.AddChild(control);
return;
}
if (entity == null)
{
_sprite.LayerSetVisible($"hand-{hand}", false);
return;
}
var item = entity.GetComponent<ItemComponent>();
var maybeInhands = item.GetInHandStateInfo(hand);
if (!maybeInhands.HasValue)
{
_sprite.LayerSetVisible($"hand-{hand}", false);
}
else
{
var (rsi, state) = maybeInhands.Value;
_sprite.LayerSetVisible($"hand-{hand}", true);
_sprite.LayerSetState($"hand-{hand}", state, rsi);
}
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
if (!serializer.Reading)
{
return;
}
foreach (var slot in serializer.ReadDataFieldCached("hands", new List<string>()))
{
_hands.Add(slot, null);
}
}
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null,
IComponent component = null)
{
base.HandleMessage(message, netChannel, component);
switch (message)
{
case PlayerAttachedMsg _:
if (_gui == null)
{
_gui = new HandsGui();
}
else
{
_gui.Parent?.RemoveChild(_gui);
}
_userInterfaceManager.StateRoot.AddChild(_gui);
_gui.UpdateHandIcons();
break;
case PlayerDetachedMsg _:
_gui.Parent?.RemoveChild(_gui);
break;
}
control.UpdateHandIcons();
}
public void SendChangeHand(string index)

View File

@@ -0,0 +1,60 @@
using Content.Shared.GameObjects.Components.Inventory;
using SS14.Client.Graphics;
using SS14.Client.Interfaces.ResourceManagement;
using SS14.Client.ResourceManagement;
using SS14.Shared.GameObjects;
using SS14.Shared.GameObjects.Components.Renderable;
using SS14.Shared.IoC;
using SS14.Shared.Serialization;
using SS14.Shared.Utility;
using SS14.Shared.ViewVariables;
namespace Content.Client.GameObjects
{
public class ItemComponent : Component
{
public override string Name => "Item";
[ViewVariables] protected ResourcePath RsiPath;
private string _equippedPrefix;
[ViewVariables(VVAccess.ReadWrite)]
public string EquippedPrefix
{
get => _equippedPrefix;
set => _equippedPrefix = value;
}
public (RSI rsi, RSI.StateId stateId)? GetInHandStateInfo(string hand)
{
if (RsiPath == null)
{
return null;
}
var rsi = GetRSI();
var stateId = EquippedPrefix != null ? $"{EquippedPrefix}-inhand-{hand}" : $"inhand-{hand}";
if (rsi.TryGetState(stateId, out _))
{
return (rsi, stateId);
}
return null;
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataFieldCached(ref RsiPath, "sprite", null);
serializer.DataFieldCached(ref _equippedPrefix, "prefix", null);
}
protected RSI GetRSI()
{
var resourceCache = IoCManager.Resolve<IResourceCache>();
return resourceCache.GetResource<RSIResource>(SharedSpriteComponent.TextureRoot / RsiPath).RSI;
}
}
}