Storage Component (toolboxes, backpacks, etc) (#57)

* Fix
Finish and update submodule
Comments code, changes network messages
FIXES THE USE INTERACTION SO YOU CAN ACTUALLY ACTIVATE THINGS NOW
Need engine commits
We'll figure out what to do about this shit later eh mates? Maybe have a script in the build process that automatically moves them over to godot/scenes
Changes some prototypes and fixes stuff
Fixes some more bugs, makes storage values show up properly
Part 3
Part 2
Storage Take 1

* Doneso
This commit is contained in:
clusterfack
2018-04-22 06:11:38 -05:00
committed by Pieter-Jan Briers
parent 74193d1182
commit ea05c593aa
22 changed files with 1044 additions and 54 deletions

View File

@@ -1,10 +1,15 @@
using System;
using System.Collections.Generic;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces.GameObjects;
using Content.Shared.GameObjects;
using SS14.Server.Interfaces.GameObjects;
using SS14.Server.Interfaces.Player;
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.Utility;
using YamlDotNet.RepresentationModel;
@@ -81,6 +86,8 @@ namespace Content.Server.GameObjects
return slot.Item;
}
public IItemComponent GetActiveHand => GetHand(ActiveIndex);
/// <summary>
/// Enumerates over the hand keys, returning the active hand first.
/// </summary>
@@ -233,19 +240,40 @@ namespace Content.Server.GameObjects
ActiveIndex = orderedHands[index];
}
public override void HandleMessage(object owner, ComponentMessage message)
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null)
{
base.HandleMessage(owner, message);
base.HandleMessage(message, netChannel, component);
switch (message)
{
case ClientChangedHandMsg msg:
if (HasHand(msg.Index))
ActiveIndex = msg.Index;
break;
{
var playerMan = IoCManager.Resolve<IPlayerManager>();
var session = playerMan.GetSessionByChannel(netChannel);
var playerentity = session.AttachedEntity;
if (playerentity == Owner && HasHand(msg.Index))
ActiveIndex = msg.Index;
break;
}
case ActivateInhandMsg msg:
{
var playerMan = IoCManager.Resolve<IPlayerManager>();
var session = playerMan.GetSessionByChannel(netChannel);
var playerentity = session.AttachedEntity;
var used = GetActiveHand?.Owner;
if (playerentity == Owner && used != null)
{
InteractionSystem.TryUseInteraction(Owner, used);
}
break;
}
//Boundkeychangedmsg only works for the player entity
case BoundKeyChangedMsg msg:
if(msg.State != BoundKeyState.Down)
if (msg.State != BoundKeyState.Down)
return;
switch (msg.Function)
{
@@ -255,6 +283,13 @@ namespace Content.Server.GameObjects
case BoundKeyFunctions.Drop:
Drop(ActiveIndex);
break;
case BoundKeyFunctions.ActivateItemInHand:
var used = GetActiveHand?.Owner;
if(used != null)
{
InteractionSystem.TryUseInteraction(Owner, used);
}
break;
}
break;
}

View File

@@ -1,12 +1,11 @@
using Content.Server.Interfaces.GameObjects;
using SS14.Server.Interfaces.GameObjects;
using SS14.Shared.GameObjects;
using System;
using SS14.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects
{
public class ItemComponent : Component, IItemComponent, EntitySystems.IAttackHand
public class ItemComponent : StoreableComponent, IItemComponent, EntitySystems.IAttackHand
{
public override string Name => "Item";

View File

@@ -0,0 +1,184 @@
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces.GameObjects;
using Content.Shared.GameObjects.Components.Storage;
using SS14.Server.GameObjects;
using SS14.Server.GameObjects.Components.Container;
using SS14.Server.Interfaces.Player;
using SS14.Shared.GameObjects;
using SS14.Shared.GameObjects.Serialization;
using SS14.Shared.Interfaces.GameObjects;
using SS14.Shared.Interfaces.Network;
using SS14.Shared.IoC;
using SS14.Shared.Log;
using System.Collections.Generic;
namespace Content.Server.GameObjects
{
/// <summary>
/// Storage component for containing entities within this one, matches a UI on the client which shows stored entities
/// </summary>
public class ServerStorageComponent : SharedStorageComponent, IAttackby, IUse
{
private Container storage;
private int StorageUsed = 0;
private int StorageCapacityMax = 10000;
public override void OnAdd()
{
base.OnAdd();
storage = Container.Create("storagebase", Owner);
}
public override void ExposeData(EntitySerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref StorageCapacityMax, "Capacity", 10000);
}
/// <summary>
/// Removes from the storage container and updates the stored value
/// </summary>
/// <param name="toremove"></param>
/// <returns></returns>
bool Remove(IEntity toremove)
{
if(storage.Remove(toremove))
{
StorageUsed -= toremove.GetComponent<StoreableComponent>().ObjectSize;
UpdateClientInventory();
return true;
}
return false;
}
/// <summary>
/// Inserts into the storage container
/// </summary>
/// <param name="toinsert"></param>
/// <returns></returns>
bool Insert(IEntity toinsert)
{
if(CanInsert(toinsert) && storage.Insert(toinsert))
{
StorageUsed += toinsert.GetComponent<StoreableComponent>().ObjectSize;
UpdateClientInventory();
return true;
}
return false;
}
/// <summary>
/// Verifies the object can be inserted by checking if it is storeable and if it keeps under the capacity limit
/// </summary>
/// <param name="toinsert"></param>
/// <returns></returns>
bool CanInsert(IEntity toinsert)
{
if(toinsert.TryGetComponent(out StoreableComponent store))
{
if (store.ObjectSize <= (StorageCapacityMax - StorageUsed))
return true;
}
return false;
}
/// <summary>
/// Inserts storeable entities into this storage container if possible, otherwise return to the hand of the user
/// </summary>
/// <param name="user"></param>
/// <param name="attackwith"></param>
/// <returns></returns>
bool IAttackby.Attackby(IEntity user, IEntity attackwith)
{
var hands = user.GetComponent<HandsComponent>();
//Check that we can drop the item from our hands first otherwise we obviously cant put it inside
if(hands.Drop(hands.ActiveIndex))
{
var inserted = Insert(attackwith);
if (inserted)
{
return true;
}
else
{
//Return the object to the hand since its too big or something like that
hands.PutInHand(attackwith.GetComponent<IItemComponent>());
}
}
return false;
}
/// <summary>
/// Sends a message to open the storage UI
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
bool IUse.UseEntity(IEntity user)
{
SendNetworkMessage(new OpenStorageUIMessage());
return false;
}
/// <summary>
/// Updates the storage UI on all clients telling them of the entities stored in this container
/// </summary>
private void UpdateClientInventory()
{
Dictionary<EntityUid, int> storedentities = new Dictionary<EntityUid, int>();
foreach (var entities in storage.ContainedEntities)
{
storedentities.Add(entities.Uid, entities.GetComponent<StoreableComponent>().ObjectSize);
}
SendNetworkMessage(new StorageHeldItemsMessage(storedentities, StorageUsed, StorageCapacityMax));
}
/// <summary>
/// Receives messages to remove entities from storage, verifies the player can do them,
/// and puts the removed entity in hand or on the ground
/// </summary>
/// <param name="message"></param>
/// <param name="netChannel"></param>
/// <param name="component"></param>
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null)
{
base.HandleMessage(message, netChannel, component);
switch (message)
{
case RemoveEntityMessage msg:
var playerMan = IoCManager.Resolve<IPlayerManager>();
var session = playerMan.GetSessionByChannel(netChannel);
var playerentity = session.AttachedEntity;
var ourtransform = Owner.GetComponent<TransformComponent>();
var playertransform = playerentity.GetComponent<TransformComponent>();
if (playertransform.LocalPosition.InRange(ourtransform.LocalPosition, 2)
&& (ourtransform.IsMapTransform || playertransform.ContainsEntity(ourtransform)))
{
var remove = (RemoveEntityMessage)message;
var entity = IoCManager.Resolve<IEntityManager>().GetEntity(remove.EntityUid);
if (entity != null && storage.Contains(entity))
{
Remove(entity);
UpdateClientInventory();
var item = entity.GetComponent<IItemComponent>();
if (item != null && playerentity.TryGetComponent(out HandsComponent hands))
{
if (hands.PutInHand(item))
return;
}
entity.GetComponent<TransformComponent>().WorldPosition = Owner.GetComponent<TransformComponent>().WorldPosition;
}
}
break;
}
}
}
}

View File

@@ -0,0 +1,37 @@
using SS14.Shared.GameObjects;
using SS14.Shared.GameObjects.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Content.Server.GameObjects
{
public class StoreableComponent : Component
{
public override string Name => "Storeable";
public int ObjectSize = 0;
public override void ExposeData(EntitySerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref ObjectSize, "Size", 1);
}
}
/// <summary>
/// Enum for the storage capacity of various containers
/// </summary>
public enum ReferenceSizes
{
Wallet = 4,
Pocket = 12,
Box = 24,
Toolbox = 60,
Backpack = 100,
NoStoring = 9999
}
}