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.Server.Player; using SS14.Shared.Enums; 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 { /// /// Storage component for containing entities within this one, matches a UI on the client which shows stored entities /// public class ServerStorageComponent : SharedStorageComponent, IAttackby, IUse { private Container storage; private int StorageUsed = 0; private int StorageCapacityMax = 10000; public HashSet SubscribedSessions = new HashSet(); public override void OnAdd() { base.OnAdd(); storage = ContainerManagerComponent.Create("storagebase", Owner); } public override void ExposeData(EntitySerializer serializer) { base.ExposeData(serializer); serializer.DataField(ref StorageCapacityMax, "Capacity", 10000); } /// /// Removes from the storage container and updates the stored value /// /// /// bool Remove(IEntity toremove) { if (storage.Remove(toremove)) { Logger.InfoS("Storage", "Storage (UID {0}) had entity (UID {1}) removed from it.", Owner.Uid, toremove.Uid); StorageUsed -= toremove.GetComponent().ObjectSize; UpdateClientInventories(); return true; } return false; } /// /// Inserts into the storage container /// /// /// bool Insert(IEntity toinsert) { if (CanInsert(toinsert) && storage.Insert(toinsert)) { Logger.InfoS("Storage", "Storage (UID {0}) had entity (UID {1}) inserted into it.", Owner.Uid, toinsert.Uid); StorageUsed += toinsert.GetComponent().ObjectSize; UpdateClientInventories(); return true; } return false; } /// /// Verifies the object can be inserted by checking if it is storeable and if it keeps under the capacity limit /// /// /// bool CanInsert(IEntity toinsert) { if (toinsert.TryGetComponent(out StoreableComponent store)) { if (store.ObjectSize <= (StorageCapacityMax - StorageUsed)) return true; } return false; } /// /// Inserts storeable entities into this storage container if possible, otherwise return to the hand of the user /// /// /// /// bool IAttackby.Attackby(IEntity user, IEntity attackwith) { Logger.DebugS("Storage", "Storage (UID {0}) attacked by user (UID {1}) with entity (UID {2}).", Owner.Uid, user.Uid, attackwith.Uid); var hands = user.GetComponent(); //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()); } } return false; } /// /// Sends a message to open the storage UI /// /// /// bool IUse.UseEntity(IEntity user) { var user_session = user.GetComponent().playerSession; Logger.DebugS("Storage", "Storage (UID {0}) \"used\" by player session (UID {1}).", Owner.Uid, user_session.AttachedEntityUid); SubscribeSession(user_session); SendNetworkMessage(new OpenStorageUIMessage(), user_session.ConnectedClient); UpdateClientInventory(user_session); return false; } /// /// Updates the storage UI on all subscribed actors, informing them of the state of the container. /// private void UpdateClientInventories() { foreach (IPlayerSession session in SubscribedSessions) { UpdateClientInventory(session); } } /// /// Adds actor to the update list. /// /// public void SubscribeSession(IPlayerSession session) { if (!SubscribedSessions.Contains(session)) { Logger.DebugS("Storage", "Storage (UID {0}) subscribed player session (UID {1}).", Owner.Uid, session.AttachedEntityUid); session.PlayerStatusChanged += HandlePlayerSessionChangeEvent; SubscribedSessions.Add(session); } } /// /// Removes actor from the update list. /// /// public void UnsubscribeSession(IPlayerSession session) { Logger.DebugS("Storage", "Storage (UID {0}) unsubscribed player session (UID {1}).", Owner.Uid, session.AttachedEntityUid); SubscribedSessions.Remove(session); SendNetworkMessage(new CloseStorageUIMessage(), session.ConnectedClient); } public void HandlePlayerSessionChangeEvent(object obj, SessionStatusEventArgs SSEA) { Logger.DebugS("Storage", "Storage (UID {0}) handled a status change in player session (UID {1}).", Owner.Uid, SSEA.Session.AttachedEntityUid); if (SSEA.NewStatus != SessionStatus.InGame) { UnsubscribeSession(SSEA.Session); } } /// /// Updates storage UI on a client, informing them of the state of the container. /// private void UpdateClientInventory(IPlayerSession session) { if (session.AttachedEntity == null) { Logger.DebugS("Storage", "Storage (UID {0}) detected no attached entity in player session (UID {1}).", Owner.Uid, session.AttachedEntityUid); UnsubscribeSession(session); return; } Dictionary storedentities = new Dictionary(); foreach (var entities in storage.ContainedEntities) { storedentities.Add(entities.Uid, entities.GetComponent().ObjectSize); } SendNetworkMessage(new StorageHeldItemsMessage(storedentities, StorageUsed, StorageCapacityMax), session.ConnectedClient); } /// /// Receives messages to remove entities from storage, verifies the player can do them, /// and puts the removed entity in hand or on the ground /// /// /// /// 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(); var session = playerMan.GetSessionByChannel(netChannel); var playerentity = session.AttachedEntity; var ourtransform = Owner.GetComponent(); var playertransform = playerentity.GetComponent(); if (playertransform.LocalPosition.InRange(ourtransform.LocalPosition, 2) && (ourtransform.IsMapTransform || playertransform.ContainsEntity(ourtransform))) { var remove = (RemoveEntityMessage)message; var entity = IoCManager.Resolve().GetEntity(remove.EntityUid); if (entity != null && storage.Contains(entity)) { Remove(entity); var item = entity.GetComponent(); if (item != null && playerentity.TryGetComponent(out HandsComponent hands)) { if (hands.PutInHand(item)) return; } entity.GetComponent().WorldPosition = Owner.GetComponent().WorldPosition; } } break; } } } }