Files
OldThink/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs

450 lines
15 KiB
C#
Raw Normal View History

using System;
using System.Linq;
using System.Threading.Tasks;
Bodysystem and damagesystem rework (#1544) * Things and stuff with grids, unfinished w/ code debug changes. * Updated submodule and also lost some progress cause I fucked it up xd * First unfinished draft of the BodySystem. Doesn't compile. * More changes to make it compile, but still just a framework. Doesn't do anything at the moment. * Many cleanup changes. * Revert "Merge branch 'master' of https://github.com/GlassEclipse/space-station-14 into body_system" This reverts commit ddd4aebbc76cf2a0b7b102f72b93d55a0816c88c, reversing changes made to 12d0dd752706bdda8879393bd8191a1199a0c978. * Commit human.yml * Updated a lot of things to be more classy, more progress overall, etc. etc. * Latest update with many changes * Minor changes * Fixed Travis build bug * Adds first draft of Body Scanner console, apparently I also forgot to tie Mechanisms into body parts so now a heart just sits in the Torso like a good boy :) * Commit rest of stuff * Latest changes * Latest changes again * 14 naked cowboys * Yay! * Latest changes (probably doesnt compile) * Surgery!!!!!!!!!~1116y * Cleaned some stuff up * More cleanup * Refactoring of code. Basic surgery path now done. * Removed readme, has been added to HackMD * Fixes typo (and thus test errors) * WIP changes, committing so I can pull latest master changes * Still working on that god awful merge * Latest changes * Latest changes!! * Beginning of refactor to BoundUserInterface * Surgery! * Latest changes - fixes pr change requests and random fixes * oops * Fixes bodypart recursion * Beginning of work on revamping the damage system. * More latest changes * Latest changes * Finished merge * Commit before removing old healthcode * Almost done with removing speciescomponent... * It compiles!!! * yahoo more work * Fixes to make it work * Merge conflict fixes * Deleting species visualizer was a mistake * IDE warnings are VERBOTEN * makes the server not kill itself on startup, some cleanup (#1) * Namespaces, comments and exception fixes * Fix conveyor and conveyor switch serialization SS14 in reactive when * Move damage, acts and body to shared Damage cleanup Comment cleanup * Rename SpeciesComponent to RotationComponent and cleanup Damage cleanup Comment cleanup * Fix nullable warnings * Address old reviews Fix off welder suicide damage type, deathmatch and suspicion * Fix new test fail with units being able to accept items when unpowered * Remove RotationComponent, change references to IBodyManagerComponent * Add a bloodstream to humans * More cleanups * Add body conduits, connections, connectors substances and valves * Revert "Add body conduits, connections, connectors substances and valves" This reverts commit 9ab0b50e6b15fe98852d7b0836c0cdbf4bd76d20. * Implement the heart mechanism behavior with the circulatory network * Added network property to mechanism behaviors * Changed human organ sprites and added missing ones * Fix tests * Add individual body part sprite rendering * Fix error where dropped mechanisms are not initialized * Implement client/server body damage * Make DamageContainer take care of raising events * Reimplement medical scanner with the new body system * Improve the medical scanner ui * Merge conflict fixes * Fix crash when colliding with something * Fix microwave suicides and eyes sprite rendering * Fix nullable reference error * Fix up surgery client side * Fix missing using from merge conflict * Add breathing *inhale * Merge conflict fixes * Fix accumulatedframetime being reset to 0 instead of decreased by the threshold https://github.com/space-wizards/space-station-14/pull/1617 * Use and add to the new AtmosHelpers * Fix feet * Add proper coloring to dropped body parts * Fix Urist's lungs being too strong * Merge conflict fixes * Merge conflict fixes * Merge conflict fixes Co-authored-by: GlassEclipse <tsymall5@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
2020-08-17 01:42:42 +02:00
using Content.Server.GameObjects.Components.Body;
Add changing the amount of hands on the GUI depending on your body parts (#1406) * Multiple hands in gui first pass * Remove IHandsComponent interface * Create hand class and more hand textures * Refactor ServerHandsComponent to use a single list of hands * Seal SharedHand * Fix picked up items not showing on top of the hand buttons * Remove HandsGui buttons and panels dictionaries * Fix items in hands rendering * Fix wrong hand container comparison * Fix not updating the location of duplicate hands * Change ClientHandsComponent to use a SortedList instead of a dictionary * More merge conflict fixes * Change SortedList to List * Fix hand button order * Add item tooltip for more than 2 hands and updating when removing hands * Add add hand and remove hand command * Merge conflict fixes * Remove nullable reference type from ContainerSlot * Fix texture errors * Fix error when reaching 0 hands * Fix error when swapping hands with no hands * Merged remove hand methods * Fix item panel texture errors * Merge conflict fixes * Fix addhand and removehand command descriptions * Add properly displaying tooltips for 2 hands * Make hand indexes and locations consistent across the client and server * Add dropping held entity if a hand is removed * Change hand location to be calculated by index * Made different hand gui updates more consistent * Remove human body yml testing changes * Sanitize addhand and removehand commands * Merge conflict fixes * Remove testing changes * Revert body system changes * Add missing imports * Remove obsolete hands parameter in yml files * Fix broken import * Fix startup error and adding and removing hands on the same tick * Make hand container id use an uint In case someone gets more than 2 billion hands * Rename hand component files * Make hands state use an array
2020-07-25 15:11:16 +02:00
using Content.Server.GameObjects.Components.GUI;
2020-05-25 13:58:56 +02:00
using Content.Server.GameObjects.Components.Interactable;
using Content.Shared.GameObjects.Components.Body;
2020-05-25 13:58:56 +02:00
using Content.Shared.GameObjects.Components.Interactable;
2019-07-31 15:02:36 +02:00
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
2020-05-25 13:58:56 +02:00
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
2019-07-31 15:02:36 +02:00
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
2020-05-25 13:58:56 +02:00
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Items.Storage
{
2019-07-31 15:02:36 +02:00
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(IStorageComponent))]
public class EntityStorageComponent : Component, IActivate, IStorageComponent, IInteractUsing, IDestroyAct, IActionBlocker, IExAct
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override string Name => "EntityStorage";
private const float MaxSize = 1.0f; // maximum width or height of an entity allowed inside the storage.
2020-05-25 13:58:56 +02:00
private static readonly TimeSpan InternalOpenAttemptDelay = TimeSpan.FromSeconds(0.5);
private TimeSpan _lastInternalOpenAttempt;
[ViewVariables]
private int _storageCapacityMax;
2020-05-25 13:58:56 +02:00
[ViewVariables]
private bool _isCollidableWhenOpen;
2020-05-25 13:58:56 +02:00
[ViewVariables]
private IEntityQuery _entityQuery;
private bool _showContents;
private bool _occludesLight;
private bool _open;
2020-05-25 13:58:56 +02:00
private bool _isWeldedShut;
[ViewVariables]
protected Container Contents;
/// <summary>
/// Determines if the container contents should be drawn when the container is closed.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public bool ShowContents
{
get => _showContents;
set
{
_showContents = value;
Contents.ShowContents = _showContents;
}
}
[ViewVariables(VVAccess.ReadWrite)]
public bool OccludesLight
{
get => _occludesLight;
set
{
_occludesLight = value;
Contents.OccludesLight = _occludesLight;
}
}
2020-05-25 13:58:56 +02:00
[ViewVariables(VVAccess.ReadWrite)]
public bool Open
{
get => _open;
private set => _open = value;
}
[ViewVariables(VVAccess.ReadWrite)]
public bool IsWeldedShut
{
get => _isWeldedShut;
set
{
_isWeldedShut = value;
if (Owner.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(StorageVisuals.Welded, value);
}
}
}
[ViewVariables(VVAccess.ReadWrite)]
public bool CanWeldShut { get; set; }
/// <inheritdoc />
public override void Initialize()
{
base.Initialize();
Contents = ContainerManagerComponent.Ensure<Container>(nameof(EntityStorageComponent), Owner);
_entityQuery = new IntersectingEntityQuery(Owner);
Contents.ShowContents = _showContents;
Contents.OccludesLight = _occludesLight;
if (Owner.TryGetComponent<PlaceableSurfaceComponent>(out var placeableSurfaceComponent))
{
placeableSurfaceComponent.IsPlaceable = Open;
}
}
/// <inheritdoc />
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _storageCapacityMax, "Capacity", 30);
serializer.DataField(ref _isCollidableWhenOpen, "IsCollidableWhenOpen", false);
serializer.DataField(ref _showContents, "showContents", false);
serializer.DataField(ref _occludesLight, "occludesLight", true);
serializer.DataField(ref _open, "open", false);
2020-05-25 13:58:56 +02:00
serializer.DataField(this, a => a.IsWeldedShut, "IsWeldedShut", false);
serializer.DataField(this, a => a.CanWeldShut, "CanWeldShut", true);
}
public virtual void Activate(ActivateEventArgs eventArgs)
{
2020-05-25 13:58:56 +02:00
ToggleOpen(eventArgs.User);
}
private void ToggleOpen(IEntity user)
{
2020-05-25 13:58:56 +02:00
if (IsWeldedShut)
{
Owner.PopupMessage(user, Loc.GetString("It's welded completely shut!"));
return;
}
if (Open)
{
CloseStorage();
}
else
{
2020-05-25 13:58:56 +02:00
TryOpenStorage(user);
}
}
public virtual void CloseStorage()
{
Open = false;
var entities = Owner.EntityManager.GetEntities(_entityQuery);
var count = 0;
foreach (var entity in entities)
{
// prevents taking items out of inventories, out of containers, and orphaning child entities
if(!entity.Transform.IsMapTransform)
continue;
// only items that can be stored in an inventory, or a mob, can be eaten by a locker
Bodysystem and damagesystem rework (#1544) * Things and stuff with grids, unfinished w/ code debug changes. * Updated submodule and also lost some progress cause I fucked it up xd * First unfinished draft of the BodySystem. Doesn't compile. * More changes to make it compile, but still just a framework. Doesn't do anything at the moment. * Many cleanup changes. * Revert "Merge branch 'master' of https://github.com/GlassEclipse/space-station-14 into body_system" This reverts commit ddd4aebbc76cf2a0b7b102f72b93d55a0816c88c, reversing changes made to 12d0dd752706bdda8879393bd8191a1199a0c978. * Commit human.yml * Updated a lot of things to be more classy, more progress overall, etc. etc. * Latest update with many changes * Minor changes * Fixed Travis build bug * Adds first draft of Body Scanner console, apparently I also forgot to tie Mechanisms into body parts so now a heart just sits in the Torso like a good boy :) * Commit rest of stuff * Latest changes * Latest changes again * 14 naked cowboys * Yay! * Latest changes (probably doesnt compile) * Surgery!!!!!!!!!~1116y * Cleaned some stuff up * More cleanup * Refactoring of code. Basic surgery path now done. * Removed readme, has been added to HackMD * Fixes typo (and thus test errors) * WIP changes, committing so I can pull latest master changes * Still working on that god awful merge * Latest changes * Latest changes!! * Beginning of refactor to BoundUserInterface * Surgery! * Latest changes - fixes pr change requests and random fixes * oops * Fixes bodypart recursion * Beginning of work on revamping the damage system. * More latest changes * Latest changes * Finished merge * Commit before removing old healthcode * Almost done with removing speciescomponent... * It compiles!!! * yahoo more work * Fixes to make it work * Merge conflict fixes * Deleting species visualizer was a mistake * IDE warnings are VERBOTEN * makes the server not kill itself on startup, some cleanup (#1) * Namespaces, comments and exception fixes * Fix conveyor and conveyor switch serialization SS14 in reactive when * Move damage, acts and body to shared Damage cleanup Comment cleanup * Rename SpeciesComponent to RotationComponent and cleanup Damage cleanup Comment cleanup * Fix nullable warnings * Address old reviews Fix off welder suicide damage type, deathmatch and suspicion * Fix new test fail with units being able to accept items when unpowered * Remove RotationComponent, change references to IBodyManagerComponent * Add a bloodstream to humans * More cleanups * Add body conduits, connections, connectors substances and valves * Revert "Add body conduits, connections, connectors substances and valves" This reverts commit 9ab0b50e6b15fe98852d7b0836c0cdbf4bd76d20. * Implement the heart mechanism behavior with the circulatory network * Added network property to mechanism behaviors * Changed human organ sprites and added missing ones * Fix tests * Add individual body part sprite rendering * Fix error where dropped mechanisms are not initialized * Implement client/server body damage * Make DamageContainer take care of raising events * Reimplement medical scanner with the new body system * Improve the medical scanner ui * Merge conflict fixes * Fix crash when colliding with something * Fix microwave suicides and eyes sprite rendering * Fix nullable reference error * Fix up surgery client side * Fix missing using from merge conflict * Add breathing *inhale * Merge conflict fixes * Fix accumulatedframetime being reset to 0 instead of decreased by the threshold https://github.com/space-wizards/space-station-14/pull/1617 * Use and add to the new AtmosHelpers * Fix feet * Add proper coloring to dropped body parts * Fix Urist's lungs being too strong * Merge conflict fixes * Merge conflict fixes * Merge conflict fixes Co-authored-by: GlassEclipse <tsymall5@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
2020-08-17 01:42:42 +02:00
if (!entity.HasComponent<StorableComponent>() &&
!entity.HasComponent<IBody>())
continue;
if (!AddToContents(entity))
{
continue;
}
count++;
if (count >= _storageCapacityMax)
{
break;
}
}
ModifyComponents();
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Machines/closetclose.ogg", Owner);
2020-05-25 13:58:56 +02:00
_lastInternalOpenAttempt = default;
}
private void OpenStorage()
{
Open = true;
EmptyContents();
ModifyComponents();
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Machines/closetopen.ogg", Owner);
}
private void ModifyComponents()
{
if (!_isCollidableWhenOpen && Owner.TryGetComponent<IPhysicsComponent>(out var physics))
{
if (Open)
{
physics.Hard = false;
}
else
{
physics.Hard = true;
}
}
if (Owner.TryGetComponent<PlaceableSurfaceComponent>(out var placeableSurfaceComponent))
{
placeableSurfaceComponent.IsPlaceable = Open;
}
if (Owner.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(StorageVisuals.Open, Open);
}
}
private bool AddToContents(IEntity entity)
{
var physics = Owner.GetComponent<IPhysicsComponent>();
if (entity.TryGetComponent(out IPhysicsComponent entityPhysicsComponent))
{
if(MaxSize < entityPhysicsComponent.WorldAABB.Size.X
|| MaxSize < entityPhysicsComponent.WorldAABB.Size.Y)
{
return false;
}
if (physics.WorldAABB.Left > entityPhysicsComponent.WorldAABB.Left)
{
entity.Transform.WorldPosition += new Vector2(physics.WorldAABB.Left - entityPhysicsComponent.WorldAABB.Left, 0);
}
else if (physics.WorldAABB.Right < entityPhysicsComponent.WorldAABB.Right)
{
entity.Transform.WorldPosition += new Vector2(physics.WorldAABB.Right - entityPhysicsComponent.WorldAABB.Right, 0);
}
if (physics.WorldAABB.Bottom > entityPhysicsComponent.WorldAABB.Bottom)
{
entity.Transform.WorldPosition += new Vector2(0, physics.WorldAABB.Bottom - entityPhysicsComponent.WorldAABB.Bottom);
}
else if (physics.WorldAABB.Top < entityPhysicsComponent.WorldAABB.Top)
{
entity.Transform.WorldPosition += new Vector2(0, physics.WorldAABB.Top - entityPhysicsComponent.WorldAABB.Top);
}
}
if (Contents.CanInsert(entity))
{
// Because Insert sets the local position to (0,0), and we want to keep the contents spread out,
// we re-apply the world position after inserting.
Vector2 worldPos;
if (entity.HasComponent<IActorComponent>())
{
worldPos = Owner.Transform.WorldPosition;
}
else
{
worldPos = entity.Transform.WorldPosition;
}
Contents.Insert(entity);
entity.Transform.WorldPosition = worldPos;
if (entityPhysicsComponent != null)
{
entityPhysicsComponent.CanCollide = false;
}
return true;
}
return false;
}
private void EmptyContents()
{
foreach (var contained in Contents.ContainedEntities.ToArray())
{
if(Contents.Remove(contained))
{
if (contained.TryGetComponent<IPhysicsComponent>(out var physics))
{
physics.CanCollide = true;
}
}
}
}
/// <inheritdoc />
2020-04-20 10:36:02 +01:00
public override void HandleMessage(ComponentMessage message, IComponent component)
{
2020-04-20 10:36:02 +01:00
base.HandleMessage(message, component);
switch (message)
{
case RelayMovementEntityMessage msg:
if (msg.Entity.HasComponent<HandsComponent>())
{
if (_gameTiming.CurTime <
2020-05-25 13:58:56 +02:00
_lastInternalOpenAttempt + InternalOpenAttemptDelay)
{
break;
}
_lastInternalOpenAttempt = _gameTiming.CurTime;
2020-05-25 13:58:56 +02:00
TryOpenStorage(msg.Entity);
}
break;
}
}
2020-05-25 13:58:56 +02:00
protected virtual void TryOpenStorage(IEntity user)
{
if (IsWeldedShut)
{
Owner.PopupMessage(user, Loc.GetString("It's welded completely shut!"));
return;
}
OpenStorage();
}
/// <inheritdoc />
public bool Remove(IEntity entity)
{
return Contents.CanRemove(entity);
}
/// <inheritdoc />
public bool Insert(IEntity entity)
{
// Trying to add while open just dumps it on the ground below us.
if (Open)
{
entity.Transform.WorldPosition = Owner.Transform.WorldPosition;
return true;
}
return Contents.Insert(entity);
}
/// <inheritdoc />
public bool CanInsert(IEntity entity)
{
if (Open)
{
return true;
}
if (Contents.ContainedEntities.Count >= _storageCapacityMax)
{
return false;
}
return Contents.CanInsert(entity);
}
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{
if (Open)
return false;
if (!CanWeldShut)
return false;
if (Contents.Contains(eventArgs.User))
{
Owner.PopupMessage(eventArgs.User, Loc.GetString("It's too Cramped!"));
return false;
}
if (!eventArgs.Using.TryGetComponent(out WelderComponent tool))
return false;
if (!await tool.UseTool(eventArgs.User, Owner, 1f, ToolQuality.Welding, 1f))
return false;
IsWeldedShut ^= true;
return true;
}
void IDestroyAct.OnDestroy(DestructionEventArgs eventArgs)
{
Open = true;
EmptyContents();
}
[Verb]
private sealed class OpenToggleVerb : Verb<EntityStorageComponent>
{
protected override void GetData(IEntity user, EntityStorageComponent component, VerbData data)
{
if (!ActionBlockerSystem.CanInteract(user))
{
data.Visibility = VerbVisibility.Invisible;
return;
}
2020-05-25 13:58:56 +02:00
component.OpenVerbGetData(user, component, data);
}
/// <inheritdoc />
protected override void Activate(IEntity user, EntityStorageComponent component)
{
2020-05-25 13:58:56 +02:00
component.ToggleOpen(user);
}
}
2020-05-25 13:58:56 +02:00
protected virtual void OpenVerbGetData(IEntity user, EntityStorageComponent component, VerbData data)
{
if (!ActionBlockerSystem.CanInteract(user))
{
data.Visibility = VerbVisibility.Invisible;
return;
}
2020-05-25 13:58:56 +02:00
if (IsWeldedShut)
{
data.Visibility = VerbVisibility.Disabled;
var verb = Loc.GetString(component.Open ? "Close" : "Open");
data.Text = Loc.GetString("{0} (welded shut)", verb);
return;
}
data.Text = Loc.GetString(component.Open ? "Close" : "Open");
2020-05-25 13:58:56 +02:00
}
void IExAct.OnExplosion(ExplosionEventArgs eventArgs)
{
if (eventArgs.Severity < ExplosionSeverity.Heavy)
{
return;
}
foreach (var entity in Contents.ContainedEntities)
{
var exActs = entity.GetAllComponents<IExAct>().ToArray();
foreach (var exAct in exActs)
{
exAct.OnExplosion(eventArgs);
}
}
}
}
}