diff --git a/Content.Client/Construction/ConstructionMenu.cs b/Content.Client/Construction/ConstructionMenu.cs
index 12e919752c..7ae220d099 100644
--- a/Content.Client/Construction/ConstructionMenu.cs
+++ b/Content.Client/Construction/ConstructionMenu.cs
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Content.Client.GameObjects.Components.Construction;
-using Content.Client.Interfaces.GameObjects;
+using Content.Client.GameObjects.EntitySystems;
using Content.Shared.Construction;
using Content.Shared.GameObjects.Components.Interactable;
using Robust.Client.Graphics;
@@ -14,7 +13,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.Utility;
using Robust.Shared.Enums;
-using Robust.Shared.Interfaces.GameObjects.Components;
+using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
@@ -24,11 +23,11 @@ namespace Content.Client.Construction
public class ConstructionMenu : SS14Window
{
#pragma warning disable CS0649
- [Dependency] readonly IPrototypeManager PrototypeManager;
- [Dependency] readonly IResourceCache ResourceCache;
+ [Dependency] private readonly IPrototypeManager _prototypeManager;
+ [Dependency] private readonly IResourceCache _resourceCache;
+ [Dependency] private readonly IEntitySystemManager _systemManager;
#pragma warning restore
- public ConstructorComponent Owner { get; set; }
private readonly Button BuildButton;
private readonly Button EraseButton;
private readonly LineEdit SearchBar;
@@ -118,6 +117,7 @@ namespace Content.Client.Construction
PopulateTree();
}
+ ///
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
@@ -128,7 +128,7 @@ namespace Content.Client.Construction
}
}
- void OnItemSelected()
+ private void OnItemSelected()
{
var prototype = (ConstructionPrototype) RecipeList.Selected.Metadata;
@@ -162,17 +162,17 @@ namespace Content.Client.Construction
switch (mat.Material)
{
case ConstructionStepMaterial.MaterialType.Metal:
- icon = ResourceCache.GetResource(
+ icon = _resourceCache.GetResource(
"/Textures/Objects/Materials/sheet_metal.png");
text = $"Metal x{mat.Amount}";
break;
case ConstructionStepMaterial.MaterialType.Glass:
- icon = ResourceCache.GetResource(
+ icon = _resourceCache.GetResource(
"/Textures/Objects/Materials/sheet_glass.png");
text = $"Glass x{mat.Amount}";
break;
case ConstructionStepMaterial.MaterialType.Cable:
- icon = ResourceCache.GetResource(
+ icon = _resourceCache.GetResource(
"/Textures/Objects/Tools/cable_coil.png");
text = $"Cable Coil x{mat.Amount}";
break;
@@ -185,25 +185,25 @@ namespace Content.Client.Construction
switch (tool.ToolQuality)
{
case ToolQuality.Anchoring:
- icon = ResourceCache.GetResource("/Textures/Objects/Tools/wrench.png");
+ icon = _resourceCache.GetResource("/Textures/Objects/Tools/wrench.png");
text = "Wrench";
break;
case ToolQuality.Prying:
- icon = ResourceCache.GetResource("/Textures/Objects/Tools/crowbar.png");
+ icon = _resourceCache.GetResource("/Textures/Objects/Tools/crowbar.png");
text = "Crowbar";
break;
case ToolQuality.Screwing:
- icon = ResourceCache.GetResource(
+ icon = _resourceCache.GetResource(
"/Textures/Objects/Tools/screwdriver.png");
text = "Screwdriver";
break;
case ToolQuality.Welding:
- icon = ResourceCache.GetResource("/Textures/Objects/tools.rsi")
+ icon = _resourceCache.GetResource("/Textures/Objects/tools.rsi")
.RSI["welder"].Frame0;
text = $"Welding tool ({tool.Amount} fuel)";
break;
case ToolQuality.Cutting:
- icon = ResourceCache.GetResource(
+ icon = _resourceCache.GetResource(
"/Textures/Objects/Tools/wirecutter.png");
text = "Wirecutters";
break;
@@ -221,13 +221,13 @@ namespace Content.Client.Construction
}
}
- void OnTextEntered(LineEdit.LineEditEventArgs args)
+ private void OnTextEntered(LineEdit.LineEditEventArgs args)
{
var str = args.Text;
PopulateTree(string.IsNullOrWhiteSpace(str) ? null : str.ToLowerInvariant());
}
- void OnBuildToggled(BaseButton.ButtonToggledEventArgs args)
+ private void OnBuildToggled(BaseButton.ButtonToggledEventArgs args)
{
if (args.Pressed)
{
@@ -239,7 +239,8 @@ namespace Content.Client.Construction
if (prototype.Type == ConstructionType.Item)
{
- Owner.TryStartItemConstruction(prototype.ID);
+ var constructSystem = _systemManager.GetEntitySystem();
+ constructSystem.TryStartItemConstruction(prototype.ID);
BuildButton.Pressed = false;
return;
}
@@ -250,7 +251,7 @@ namespace Content.Client.Construction
IsTile = false,
PlacementOption = prototype.PlacementMode
},
- new ConstructionPlacementHijack(prototype, Owner));
+ new ConstructionPlacementHijack(_systemManager.GetEntitySystem(), prototype));
}
else
{
@@ -262,7 +263,7 @@ namespace Content.Client.Construction
private void OnEraseToggled(BaseButton.ButtonToggledEventArgs args)
{
if (args.Pressed) Placement.Clear();
- Placement.ToggleEraserHijacked(new ConstructionPlacementHijack(null, Owner));
+ Placement.ToggleEraserHijacked(new ConstructionPlacementHijack(_systemManager.GetEntitySystem(), null));
EraseButton.Pressed = args.Pressed;
}
@@ -272,12 +273,12 @@ namespace Content.Client.Construction
EraseButton.Pressed = false;
}
- void PopulatePrototypeList()
+ private void PopulatePrototypeList()
{
RootCategory = new CategoryNode("", null);
- int count = 1;
+ var count = 1;
- foreach (var prototype in PrototypeManager.EnumeratePrototypes())
+ foreach (var prototype in _prototypeManager.EnumeratePrototypes())
{
var currentNode = RootCategory;
@@ -316,7 +317,7 @@ namespace Content.Client.Construction
Recurse(RootCategory);
}
- void PopulateTree(string searchTerm = null)
+ private void PopulateTree(string searchTerm = null)
{
RecipeList.Clear();
@@ -378,18 +379,18 @@ namespace Content.Client.Construction
private static int ComparePrototype(ConstructionPrototype x, ConstructionPrototype y)
{
- return String.Compare(x.Name, y.Name, StringComparison.Ordinal);
+ return string.Compare(x.Name, y.Name, StringComparison.Ordinal);
}
- class CategoryNode
+ private class CategoryNode
{
public readonly string Name;
public readonly CategoryNode Parent;
- public SortedDictionary
+ public readonly SortedDictionary
ChildCategories = new SortedDictionary();
- public List Prototypes = new List();
+ public readonly List Prototypes = new List();
public int FlattenedIndex = -1;
public CategoryNode(string name, CategoryNode parent)
diff --git a/Content.Client/Construction/ConstructionPlacementHijack.cs b/Content.Client/Construction/ConstructionPlacementHijack.cs
index 5a4f56859f..57f5503dbc 100644
--- a/Content.Client/Construction/ConstructionPlacementHijack.cs
+++ b/Content.Client/Construction/ConstructionPlacementHijack.cs
@@ -1,49 +1,51 @@
-using Content.Client.GameObjects.Components.Construction;
+using Content.Client.GameObjects.Components.Construction;
+using Content.Client.GameObjects.EntitySystems;
using Content.Shared.Construction;
-using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Placement;
using Robust.Client.Utility;
using Robust.Shared.Interfaces.GameObjects;
-using Robust.Shared.IoC;
using Robust.Shared.Map;
namespace Content.Client.Construction
{
public class ConstructionPlacementHijack : PlacementHijack
{
- private readonly ConstructionPrototype Prototype;
- private readonly ConstructorComponent Owner;
+ private readonly ConstructionSystem _constructionSystem;
+ private readonly ConstructionPrototype _prototype;
- public ConstructionPlacementHijack(ConstructionPrototype prototype, ConstructorComponent owner)
+ public ConstructionPlacementHijack(ConstructionSystem constructionSystem, ConstructionPrototype prototype)
{
- Prototype = prototype;
- Owner = owner;
+ _constructionSystem = constructionSystem;
+ _prototype = prototype;
}
+ ///
public override bool HijackPlacementRequest(GridCoordinates coords)
{
- if (Prototype != null)
+ if (_prototype != null)
{
var dir = Manager.Direction;
- Owner.SpawnGhost(Prototype, coords, dir);
+ _constructionSystem.SpawnGhost(_prototype, coords, dir);
}
return true;
}
+ ///
public override bool HijackDeletion(IEntity entity)
{
if (entity.TryGetComponent(out ConstructionGhostComponent ghost))
{
- Owner.ClearGhost(ghost.GhostID);
+ _constructionSystem.ClearGhost(ghost.GhostID);
}
return true;
}
+ ///
public override void StartHijack(PlacementManager manager)
{
base.StartHijack(manager);
- manager.CurrentBaseSprite = Prototype.Icon.DirFrame0();
+ manager.CurrentBaseSprite = _prototype.Icon.DirFrame0();
}
}
}
diff --git a/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs b/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs
index 0bfc7a274e..17cbb51629 100644
--- a/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs
+++ b/Content.Client/GameObjects/Components/Construction/ConstructionGhostComponent.cs
@@ -10,7 +10,6 @@ namespace Content.Client.GameObjects.Components.Construction
public override string Name => "ConstructionGhost";
[ViewVariables] public ConstructionPrototype Prototype { get; set; }
- [ViewVariables] public ConstructorComponent Master { get; set; }
[ViewVariables] public int GhostID { get; set; }
}
}
diff --git a/Content.Client/GameObjects/Components/Construction/ConstructorComponent.cs b/Content.Client/GameObjects/Components/Construction/ConstructorComponent.cs
deleted file mode 100644
index 3c44298631..0000000000
--- a/Content.Client/GameObjects/Components/Construction/ConstructorComponent.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-using System.Collections.Generic;
-using Content.Client.Construction;
-using Content.Client.UserInterface;
-using Content.Shared.Construction;
-using Content.Shared.GameObjects.Components.Construction;
-using Robust.Client.GameObjects;
-using Robust.Client.Interfaces.GameObjects;
-using Robust.Shared.GameObjects;
-using Robust.Shared.Interfaces.GameObjects;
-using Robust.Shared.Interfaces.GameObjects.Components;
-using Robust.Shared.Interfaces.Network;
-using Robust.Shared.IoC;
-using Robust.Shared.Map;
-using Robust.Shared.Maths;
-using Robust.Shared.Players;
-
-namespace Content.Client.GameObjects.Components.Construction
-{
- [RegisterComponent]
- public class ConstructorComponent : SharedConstructorComponent
- {
-#pragma warning disable 649
- [Dependency] private readonly IGameHud _gameHud;
-#pragma warning restore 649
-
- private int nextId;
- private readonly Dictionary Ghosts = new Dictionary();
- public ConstructionMenu ConstructionMenu { get; private set; }
-
- public override void Initialize()
- {
- base.Initialize();
-
- Owner.GetComponent();
- }
-
- public override void HandleMessage(ComponentMessage message, IComponent component)
- {
- base.HandleMessage(message, component);
-
- switch (message)
- {
- case PlayerAttachedMsg _:
- if (ConstructionMenu == null)
- {
- ConstructionMenu = new ConstructionMenu {Owner = this};
- ConstructionMenu.OnClose += () => _gameHud.CraftingButtonDown = false;
- }
-
- _gameHud.CraftingButtonVisible = true;
- _gameHud.CraftingButtonToggled = b =>
- {
- if (b)
- {
- ConstructionMenu.Open();
- }
- else
- {
- ConstructionMenu.Close();
- }
- };
- break;
-
- case PlayerDetachedMsg _:
- _gameHud.CraftingButtonVisible = false;
- break;
-
- default:
- break;
- }
- }
-
- public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null)
- {
- base.HandleNetworkMessage(message, channel, session);
-
- switch (message)
- {
- case AckStructureConstructionMessage ackMsg:
- ClearGhost(ackMsg.Ack);
- break;
-
- default:
- break;
- }
- }
-
- public override void OnRemove()
- {
- ConstructionMenu?.Dispose();
- }
-
- public void SpawnGhost(ConstructionPrototype prototype, GridCoordinates loc, Direction dir)
- {
- var entMgr = IoCManager.Resolve();
- var ghost = entMgr.SpawnEntity("constructionghost", loc);
- var comp = ghost.GetComponent();
- comp.Prototype = prototype;
- comp.Master = this;
- comp.GhostID = nextId++;
- ghost.GetComponent().LocalRotation = dir.ToAngle();
- var sprite = ghost.GetComponent();
- sprite.LayerSetSprite(0, prototype.Icon);
- sprite.LayerSetVisible(0, true);
-
- Ghosts.Add(comp.GhostID, comp);
- }
-
- public void TryStartConstruction(int ghostId)
- {
- var ghost = Ghosts[ghostId];
- var transform = ghost.Owner.GetComponent();
- var msg = new TryStartStructureConstructionMessage(transform.GridPosition, ghost.Prototype.ID, transform.LocalRotation, ghostId);
- SendNetworkMessage(msg);
- }
-
- public void TryStartItemConstruction(string prototypeName)
- {
- var msg = new TryStartItemConstructionMessage(prototypeName);
- SendNetworkMessage(msg);
- }
-
- public void ClearGhost(int ghostId)
- {
- if (Ghosts.TryGetValue(ghostId, out var ghost))
- {
- ghost.Owner.Delete();
- Ghosts.Remove(ghostId);
- }
- }
- }
-}
diff --git a/Content.Client/GameObjects/EntitySystems/ConstructionSystem.cs b/Content.Client/GameObjects/EntitySystems/ConstructionSystem.cs
new file mode 100644
index 0000000000..327511cd82
--- /dev/null
+++ b/Content.Client/GameObjects/EntitySystems/ConstructionSystem.cs
@@ -0,0 +1,196 @@
+using System.Collections.Generic;
+using Content.Client.Construction;
+using Content.Client.GameObjects.Components.Construction;
+using Content.Client.UserInterface;
+using Content.Shared.Construction;
+using Content.Shared.Input;
+using JetBrains.Annotations;
+using Robust.Client.GameObjects;
+using Robust.Client.GameObjects.EntitySystems;
+using Robust.Client.Player;
+using Robust.Shared.Input;
+using Robust.Shared.Input.Binding;
+using Robust.Shared.Interfaces.GameObjects;
+using Robust.Shared.IoC;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+
+namespace Content.Client.GameObjects.EntitySystems
+{
+ ///
+ /// The client-side implementation of the construction system, which is used for constructing entities in game.
+ ///
+ [UsedImplicitly]
+ public class ConstructionSystem : Shared.GameObjects.EntitySystems.ConstructionSystem
+ {
+#pragma warning disable 649
+ [Dependency] private readonly IGameHud _gameHud;
+ [Dependency] private readonly IPlayerManager _playerManager;
+ [Dependency] private readonly IEntityManager _entityManager;
+#pragma warning restore 649
+
+ private int _nextId;
+ private readonly Dictionary _ghosts = new Dictionary();
+ private ConstructionMenu _constructionMenu;
+
+ ///
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(HandlePlayerAttached);
+ SubscribeNetworkEvent(HandleAckStructure);
+
+ CommandBinds.Builder
+ .Bind(ContentKeyFunctions.OpenCraftingMenu,
+ new PointerInputCmdHandler(HandleOpenCraftingMenu))
+ .Bind(EngineKeyFunctions.Use,
+ new PointerInputCmdHandler(HandleUse))
+ .Register();
+ }
+
+ private void HandleAckStructure(AckStructureConstructionMessage msg)
+ {
+ ClearGhost(msg.GhostId);
+ }
+
+ private void HandlePlayerAttached(PlayerAttachSysMessage msg)
+ {
+ if (msg.AttachedEntity == null)
+ {
+ _gameHud.CraftingButtonVisible = false;
+ return;
+ }
+
+ if (_constructionMenu == null)
+ {
+ _constructionMenu = new ConstructionMenu();
+ _constructionMenu.OnClose += () => _gameHud.CraftingButtonDown = false;
+ }
+
+ _gameHud.CraftingButtonVisible = true;
+ _gameHud.CraftingButtonToggled = b =>
+ {
+ if (b)
+ {
+ _constructionMenu.Open();
+ }
+ else
+ {
+ _constructionMenu.Close();
+ }
+ };
+ }
+
+ ///
+ public override void Shutdown()
+ {
+ _constructionMenu?.Dispose();
+
+ CommandBinds.Unregister();
+ base.Shutdown();
+ }
+
+ private bool HandleOpenCraftingMenu(in PointerInputCmdHandler.PointerInputCmdArgs args)
+ {
+ if (_playerManager.LocalPlayer.ControlledEntity == null)
+ {
+ return false;
+ }
+
+ var menu = _constructionMenu;
+
+ if (menu.IsOpen)
+ {
+ if (menu.IsAtFront())
+ {
+ SetOpenValue(menu, false);
+ }
+ else
+ {
+ menu.MoveToFront();
+ }
+ }
+ else
+ {
+ SetOpenValue(menu, true);
+ }
+
+ return true;
+ }
+
+ private bool HandleUse(in PointerInputCmdHandler.PointerInputCmdArgs args)
+ {
+ if (!args.EntityUid.IsValid() || !args.EntityUid.IsClientSide())
+ return false;
+
+ var entity = _entityManager.GetEntity(args.EntityUid);
+
+ if (!entity.TryGetComponent(out ConstructionGhostComponent ghostComp))
+ return false;
+
+ TryStartConstruction(ghostComp.GhostID);
+ return true;
+
+ }
+
+ private void SetOpenValue(ConstructionMenu menu, bool value)
+ {
+ if (value)
+ {
+ _gameHud.CraftingButtonDown = true;
+ menu.OpenCentered();
+ }
+ else
+ {
+ _gameHud.CraftingButtonDown = false;
+ menu.Close();
+ }
+ }
+
+ ///
+ /// Creates a construction ghost at the given location.
+ ///
+ public void SpawnGhost(ConstructionPrototype prototype, GridCoordinates loc, Direction dir)
+ {
+ var ghost = _entityManager.SpawnEntity("constructionghost", loc);
+ var comp = ghost.GetComponent();
+ comp.Prototype = prototype;
+ comp.GhostID = _nextId++;
+ ghost.Transform.LocalRotation = dir.ToAngle();
+ var sprite = ghost.GetComponent();
+ sprite.LayerSetSprite(0, prototype.Icon);
+ sprite.LayerSetVisible(0, true);
+
+ _ghosts.Add(comp.GhostID, comp);
+ }
+
+ private void TryStartConstruction(int ghostId)
+ {
+ var ghost = _ghosts[ghostId];
+ var transform = ghost.Owner.Transform;
+ var msg = new TryStartStructureConstructionMessage(transform.GridPosition, ghost.Prototype.ID, transform.LocalRotation, ghostId);
+ RaiseNetworkEvent(msg);
+ }
+
+ ///
+ /// Starts constructing an item underneath the attached entity.
+ ///
+ public void TryStartItemConstruction(string prototypeName)
+ {
+ RaiseNetworkEvent(new TryStartItemConstructionMessage(prototypeName));
+ }
+
+ ///
+ /// Removes a construction ghost entity with the given ID.
+ ///
+ public void ClearGhost(int ghostId)
+ {
+ if (_ghosts.TryGetValue(ghostId, out var ghost))
+ {
+ ghost.Owner.Delete();
+ _ghosts.Remove(ghostId);
+ }
+ }
+ }
+}
diff --git a/Content.Client/GameObjects/EntitySystems/ConstructorSystem.cs b/Content.Client/GameObjects/EntitySystems/ConstructorSystem.cs
deleted file mode 100644
index 95bec8cfd2..0000000000
--- a/Content.Client/GameObjects/EntitySystems/ConstructorSystem.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-using Content.Client.Construction;
-using Content.Client.GameObjects.Components.Construction;
-using Content.Client.UserInterface;
-using Content.Shared.Input;
-using Robust.Client.GameObjects.EntitySystems;
-using Robust.Client.Player;
-using Robust.Shared.GameObjects.Systems;
-using Robust.Shared.Input;
-using Robust.Shared.Input.Binding;
-using Robust.Shared.Interfaces.GameObjects;
-using Robust.Shared.IoC;
-
-namespace Content.Client.GameObjects.EntitySystems
-{
- public sealed class ConstructorSystem : EntitySystem
- {
-#pragma warning disable 649
- [Dependency] private readonly IGameHud _gameHud;
- [Dependency] private readonly IPlayerManager _playerManager;
- [Dependency] private readonly IEntityManager _entityManager;
-#pragma warning restore 649
-
- public override void Initialize()
- {
- base.Initialize();
-
- var inputSys = EntitySystemManager.GetEntitySystem();
-
- CommandBinds.Builder
- .Bind(ContentKeyFunctions.OpenCraftingMenu,
- new PointerInputCmdHandler(HandleOpenCraftingMenu))
- .Bind(EngineKeyFunctions.Use,
- new PointerInputCmdHandler(HandleUse))
- .Register();
- }
-
- public override void Shutdown()
- {
- CommandBinds.Unregister();
- base.Shutdown();
- }
-
- private bool HandleOpenCraftingMenu(in PointerInputCmdHandler.PointerInputCmdArgs args)
- {
- if (_playerManager.LocalPlayer.ControlledEntity == null
- || !_playerManager.LocalPlayer.ControlledEntity.TryGetComponent(out ConstructorComponent constructor))
- {
- return false;
- }
-
- var menu = constructor.ConstructionMenu;
-
- if (menu.IsOpen)
- {
- if (menu.IsAtFront())
- {
- _setOpenValue(menu, false);
- }
- else
- {
- menu.MoveToFront();
- }
- }
- else
- {
- _setOpenValue(menu, true);
- }
-
- return true;
- }
-
- private bool HandleUse(in PointerInputCmdHandler.PointerInputCmdArgs args)
- {
- if (!args.EntityUid.IsValid() || !args.EntityUid.IsClientSide())
- return false;
-
- var entity = _entityManager.GetEntity(args.EntityUid);
-
- if (!entity.TryGetComponent(out ConstructionGhostComponent ghostComp))
- return false;
-
- ghostComp.Master.TryStartConstruction(ghostComp.GhostID);
- return true;
-
- }
-
- private void _setOpenValue(ConstructionMenu menu, bool value)
- {
- if (value)
- {
- _gameHud.CraftingButtonDown = true;
- menu.OpenCentered();
- }
- else
- {
- _gameHud.CraftingButtonDown = false;
- menu.Close();
- }
- }
- }
-}
diff --git a/Content.Server/GameObjects/Components/Construction/ConstructorComponent.cs b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs
similarity index 62%
rename from Content.Server/GameObjects/Components/Construction/ConstructorComponent.cs
rename to Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs
index 3a32edeea3..5d4a169a3a 100644
--- a/Content.Server/GameObjects/Components/Construction/ConstructorComponent.cs
+++ b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs
@@ -1,26 +1,28 @@
using System;
+using Content.Server.GameObjects.Components.Construction;
using Content.Server.GameObjects.Components.Stack;
using Content.Server.Utility;
using Content.Shared.Construction;
-using Content.Shared.GameObjects.Components.Construction;
+using JetBrains.Annotations;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.GameObjects;
+using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
-using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
-using Robust.Shared.Players;
using Robust.Shared.Prototypes;
-using Robust.Shared.Utility;
-namespace Content.Server.GameObjects.Components.Construction
+namespace Content.Server.GameObjects.EntitySystems
{
- [RegisterComponent]
- public class ConstructorComponent : SharedConstructorComponent
+ ///
+ /// The server-side implementation of the construction system, which is used for constructing entities in game.
+ ///
+ [UsedImplicitly]
+ internal class ConstructionSystem : Shared.GameObjects.EntitySystems.ConstructionSystem
{
#pragma warning disable 649
[Dependency] private readonly IPrototypeManager _prototypeManager;
@@ -28,32 +30,41 @@ namespace Content.Server.GameObjects.Components.Construction
[Dependency] private readonly IServerEntityManager _serverEntityManager;
#pragma warning restore 649
- public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null)
+ ///
+ public override void Initialize()
{
- base.HandleNetworkMessage(message, channel, session);
+ base.Initialize();
- switch (message)
- {
- case TryStartStructureConstructionMessage tryStart:
- TryStartStructureConstruction(tryStart.Location, tryStart.PrototypeName, tryStart.Angle, tryStart.Ack);
- break;
- case TryStartItemConstructionMessage tryStart:
- TryStartItemConstruction(tryStart.PrototypeName);
- break;
- }
+ SubscribeNetworkEvent(HandleStartStructureConstruction);
+ SubscribeNetworkEvent(HandleStartItemConstruction);
}
- void TryStartStructureConstruction(GridCoordinates loc, string prototypeName, Angle angle, int ack)
+ private void HandleStartStructureConstruction(TryStartStructureConstructionMessage msg, EntitySessionEventArgs args)
+ {
+ var placingEnt = args.SenderSession.AttachedEntity;
+ var result = TryStartStructureConstruction(placingEnt, msg.Location, msg.PrototypeName, msg.Angle);
+ if (!result) return;
+ var responseMsg = new AckStructureConstructionMessage(msg.Ack);
+ var channel = ((IPlayerSession) args.SenderSession).ConnectedClient;
+ RaiseNetworkEvent(responseMsg, channel);
+ }
+
+ private void HandleStartItemConstruction(TryStartItemConstructionMessage msg, EntitySessionEventArgs args)
+ {
+ var placingEnt = args.SenderSession.AttachedEntity;
+ TryStartItemConstruction(placingEnt, msg.PrototypeName);
+ }
+
+ private bool TryStartStructureConstruction(IEntity placingEnt, GridCoordinates loc, string prototypeName, Angle angle)
{
var prototype = _prototypeManager.Index(prototypeName);
- if (!InteractionChecks.InRangeUnobstructed(Owner, loc.ToMap(_mapManager),
- ignoredEnt: Owner, insideBlockerValid: prototype.CanBuildInImpassable))
+ if (!InteractionChecks.InRangeUnobstructed(placingEnt, loc.ToMap(_mapManager),
+ ignoredEnt: placingEnt, insideBlockerValid: prototype.CanBuildInImpassable))
{
- return;
+ return false;
}
-
if (prototype.Stages.Count < 2)
{
throw new InvalidOperationException($"Prototype '{prototypeName}' does not have enough stages.");
@@ -66,25 +77,25 @@ namespace Content.Server.GameObjects.Components.Construction
}
// Try to find the stack with the material in the user's hand.
- var hands = Owner.GetComponent();
+ var hands = placingEnt.GetComponent();
var activeHand = hands.GetActiveHand?.Owner;
if (activeHand == null)
{
- return;
+ return false;
}
if (!activeHand.TryGetComponent(out StackComponent stack) || !ConstructionComponent.MaterialStackValidFor(matStep, stack))
{
- return;
+ return false;
}
if (!stack.Use(matStep.Amount))
{
- return;
+ return false;
}
// OK WE'RE GOOD CONSTRUCTION STARTED.
- EntitySystem.Get().PlayAtCoords("/Audio/items/deconstruct.ogg", loc);
+ Get().PlayAtCoords("/Audio/items/deconstruct.ogg", loc);
if (prototype.Stages.Count == 2)
{
// Exactly 2 stages, so don't make an intermediate frame.
@@ -99,11 +110,10 @@ namespace Content.Server.GameObjects.Components.Construction
frame.Transform.LocalRotation = angle;
}
- var msg = new AckStructureConstructionMessage(ack);
- SendNetworkMessage(msg);
+ return true;
}
- void TryStartItemConstruction(string prototypeName)
+ private void TryStartItemConstruction(IEntity placingEnt, string prototypeName)
{
var prototype = _prototypeManager.Index(prototypeName);
@@ -119,7 +129,7 @@ namespace Content.Server.GameObjects.Components.Construction
}
// Try to find the stack with the material in the user's hand.
- var hands = Owner.GetComponent();
+ var hands = placingEnt.GetComponent();
var activeHand = hands.GetActiveHand?.Owner;
if (activeHand == null)
{
@@ -137,17 +147,17 @@ namespace Content.Server.GameObjects.Components.Construction
}
// OK WE'RE GOOD CONSTRUCTION STARTED.
- EntitySystem.Get().PlayFromEntity("/Audio/items/deconstruct.ogg", Owner);
+ EntitySystem.Get().PlayFromEntity("/Audio/items/deconstruct.ogg", placingEnt);
if (prototype.Stages.Count == 2)
{
// Exactly 2 stages, so don't make an intermediate frame.
- var ent = _serverEntityManager.SpawnEntity(prototype.Result, Owner.Transform.GridPosition);
+ var ent = _serverEntityManager.SpawnEntity(prototype.Result, placingEnt.Transform.GridPosition);
hands.PutInHandOrDrop(ent.GetComponent());
}
else
{
//TODO: Make these viable as an item and try putting them in the players hands
- var frame = _serverEntityManager.SpawnEntity("structureconstructionframe", Owner.Transform.GridPosition);
+ var frame = _serverEntityManager.SpawnEntity("structureconstructionframe", placingEnt.Transform.GridPosition);
var construction = frame.GetComponent();
construction.Init(prototype);
}
diff --git a/Content.Shared/Content.Shared.csproj b/Content.Shared/Content.Shared.csproj
index 4afb38c225..a01fa26d38 100644
--- a/Content.Shared/Content.Shared.csproj
+++ b/Content.Shared/Content.Shared.csproj
@@ -26,6 +26,7 @@
+
diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs
index 44838998b2..5c37c53bb1 100644
--- a/Content.Shared/GameObjects/ContentNetIDs.cs
+++ b/Content.Shared/GameObjects/ContentNetIDs.cs
@@ -11,7 +11,8 @@
public const uint STORAGE = 1005;
public const uint INVENTORY = 1006;
public const uint POWER_DEBUG_TOOL = 1007;
- public const uint CONSTRUCTOR = 1008;
+ // 1008
+ // 1009
public const uint RANGED_WEAPON = 1010;
public const uint CAMERA_RECOIL = 1011;
public const uint SOUND = 1012;
diff --git a/Content.Shared/GameObjects/Components/Construction/SharedConstructorComponent.cs b/Content.Shared/GameObjects/EntitySystems/ConstructionSystem.cs
similarity index 69%
rename from Content.Shared/GameObjects/Components/Construction/SharedConstructorComponent.cs
rename to Content.Shared/GameObjects/EntitySystems/ConstructionSystem.cs
index d7c9389fa2..c03e1dc632 100644
--- a/Content.Shared/GameObjects/Components/Construction/SharedConstructorComponent.cs
+++ b/Content.Shared/GameObjects/EntitySystems/ConstructionSystem.cs
@@ -1,25 +1,22 @@
-using System;
+using System;
+using JetBrains.Annotations;
using Robust.Shared.GameObjects;
+using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
-namespace Content.Shared.GameObjects.Components.Construction
+namespace Content.Shared.GameObjects.EntitySystems
{
- ///
- /// Basically handles the logic of "this mob can do construction".
- ///
- public abstract class SharedConstructorComponent : Component
+ [UsedImplicitly]
+ public class ConstructionSystem : EntitySystem
{
- public override string Name => "Constructor";
- public override uint? NetID => ContentNetIDs.CONSTRUCTOR;
-
///
/// Sent client -> server to to tell the server that we started building
/// a structure-construction.
///
[Serializable, NetSerializable]
- protected class TryStartStructureConstructionMessage : ComponentMessage
+ public class TryStartStructureConstructionMessage : EntitySystemMessage
{
///
/// Position to start building.
@@ -40,7 +37,6 @@ namespace Content.Shared.GameObjects.Components.Construction
public TryStartStructureConstructionMessage(GridCoordinates loc, string prototypeName, Angle angle, int ack)
{
- Directed = true;
Location = loc;
PrototypeName = prototypeName;
Angle = angle;
@@ -53,7 +49,7 @@ namespace Content.Shared.GameObjects.Components.Construction
/// an item-construction.
///
[Serializable, NetSerializable]
- protected class TryStartItemConstructionMessage : ComponentMessage
+ public class TryStartItemConstructionMessage : EntitySystemMessage
{
///
/// The construction prototype to start building.
@@ -62,21 +58,21 @@ namespace Content.Shared.GameObjects.Components.Construction
public TryStartItemConstructionMessage(string prototypeName)
{
- Directed = true;
PrototypeName = prototypeName;
}
}
-
+ ///
+ /// Send server -> client to tell the client that a ghost has started to be constructed.
+ ///
[Serializable, NetSerializable]
- protected class AckStructureConstructionMessage : ComponentMessage
+ public class AckStructureConstructionMessage : EntitySystemMessage
{
- public readonly int Ack;
+ public readonly int GhostId;
- public AckStructureConstructionMessage(int ack)
+ public AckStructureConstructionMessage(int ghostId)
{
- Directed = true;
- Ack = ack;
+ GhostId = ghostId;
}
}
}
diff --git a/Resources/Prototypes/Entities/Mobs/human.yml b/Resources/Prototypes/Entities/Mobs/human.yml
index 85af91f67b..5683331652 100644
--- a/Resources/Prototypes/Entities/Mobs/human.yml
+++ b/Resources/Prototypes/Entities/Mobs/human.yml
@@ -24,7 +24,6 @@
max_volume: 250
digestionDelay: 20
- type: Inventory
- - type: Constructor
- type: Clickable
- type: InteractionOutline
- type: Sprite