From 40d6f690dd0ba9e27eda7022e20cde5c234dd4e3 Mon Sep 17 00:00:00 2001 From: Rane <60792108+Elijahrane@users.noreply.github.com> Date: Fri, 3 Jun 2022 06:08:09 -0400 Subject: [PATCH] Floor tile ECS (#8577) --- Content.Server/Tiles/FloorTileComponent.cs | 20 ++++ .../Tiles/FloorTileItemComponent.cs | 104 ------------------ Content.Server/Tiles/FloorTileSystem.cs | 91 +++++++++++++++ 3 files changed, 111 insertions(+), 104 deletions(-) create mode 100644 Content.Server/Tiles/FloorTileComponent.cs delete mode 100644 Content.Server/Tiles/FloorTileItemComponent.cs create mode 100644 Content.Server/Tiles/FloorTileSystem.cs diff --git a/Content.Server/Tiles/FloorTileComponent.cs b/Content.Server/Tiles/FloorTileComponent.cs new file mode 100644 index 0000000000..05cdc6c309 --- /dev/null +++ b/Content.Server/Tiles/FloorTileComponent.cs @@ -0,0 +1,20 @@ +using Content.Shared.Maps; +using Content.Shared.Sound; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Server.Tiles +{ + /// + /// This gives items floor tile behavior, but it doesn't have to be a literal floor tile. + /// A lot of materials use this too. Note that the AfterInteract will fail without a stack component on the item. + /// + [RegisterComponent] + public sealed class FloorTileComponent : Component + { + [DataField("outputs", customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List? OutputTiles; + + [DataField("placeTileSound")] + public SoundSpecifier PlaceTileSound = new SoundPathSpecifier("/Audio/Items/genhit.ogg"); + } +} diff --git a/Content.Server/Tiles/FloorTileItemComponent.cs b/Content.Server/Tiles/FloorTileItemComponent.cs deleted file mode 100644 index b70ed17560..0000000000 --- a/Content.Server/Tiles/FloorTileItemComponent.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Threading.Tasks; -using Content.Server.Stack; -using Content.Shared.Audio; -using Content.Shared.Interaction; -using Content.Shared.Maps; -using Content.Shared.Sound; -using Robust.Shared.Audio; -using Robust.Shared.Map; -using Robust.Shared.Player; -using Robust.Shared.Random; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; - -namespace Content.Server.Tiles -{ - [RegisterComponent] - [ComponentProtoName("FloorTile")] - public sealed class FloorTileItemComponent : Component, IAfterInteract - { - [Dependency] private readonly IEntityManager _entMan = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; - [Dependency] private readonly IRobustRandom _random = default!; - - [DataField("outputs", customTypeSerializer: typeof(PrototypeIdListSerializer))] - private List? _outputTiles; - - [DataField("placeTileSound")] SoundSpecifier _placeTileSound = new SoundPathSpecifier("/Audio/Items/genhit.ogg"); - - protected override void Initialize() - { - base.Initialize(); - Owner.EnsureComponent(); - } - - private bool HasBaseTurf(ContentTileDefinition tileDef, string baseTurf) - { - foreach (var tileBaseTurf in tileDef.BaseTurfs) - { - if (baseTurf == tileBaseTurf) - { - return true; - } - } - - return false; - } - - private void PlaceAt(IMapGrid mapGrid, EntityCoordinates location, ushort tileId, float offset = 0) - { - var variant = _random.Pick(((ContentTileDefinition) _tileDefinitionManager[tileId]).PlacementVariants); - mapGrid.SetTile(location.Offset(new Vector2(offset, offset)), new Tile(tileId, 0, variant)); - SoundSystem.Play(Filter.Pvs(location), _placeTileSound.GetSound(), location, AudioHelpers.WithVariation(0.125f)); - } - - async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) - { - if (!eventArgs.CanReach) - return true; - - if (!_entMan.TryGetComponent(Owner, out StackComponent? stack)) - return true; - - var mapManager = IoCManager.Resolve(); - - var location = eventArgs.ClickLocation.AlignWithClosestGridTile(); - var locationMap = location.ToMap(_entMan); - if (locationMap.MapId == MapId.Nullspace) - return true; - mapManager.TryGetGrid(location.GetGridId(_entMan), out var mapGrid); - - if (_outputTiles == null) - return true; - - foreach (var currentTile in _outputTiles) - { - var currentTileDefinition = (ContentTileDefinition) _tileDefinitionManager[currentTile]; - - if (mapGrid != null) - { - var tile = mapGrid.GetTileRef(location); - var baseTurf = (ContentTileDefinition) _tileDefinitionManager[tile.Tile.TypeId]; - - if (HasBaseTurf(currentTileDefinition, baseTurf.ID)) - { - if (!EntitySystem.Get().Use(Owner, 1, stack)) - continue; - - PlaceAt(mapGrid, location, currentTileDefinition.TileId); - break; - } - } - else if (HasBaseTurf(currentTileDefinition, "space")) - { - mapGrid = mapManager.CreateGrid(locationMap.MapId); - mapGrid.WorldPosition = locationMap.Position; - location = new EntityCoordinates(mapGrid.GridEntityId, Vector2.Zero); - PlaceAt(mapGrid, location, _tileDefinitionManager[_outputTiles[0]].TileId, mapGrid.TileSize / 2f); - break; - } - } - - return true; - } - } -} diff --git a/Content.Server/Tiles/FloorTileSystem.cs b/Content.Server/Tiles/FloorTileSystem.cs new file mode 100644 index 0000000000..effd6d63d7 --- /dev/null +++ b/Content.Server/Tiles/FloorTileSystem.cs @@ -0,0 +1,91 @@ +using Content.Server.Stack; +using Content.Shared.Audio; +using Content.Shared.Interaction; +using Content.Shared.Maps; +using Content.Shared.Sound; +using Robust.Shared.Audio; +using Robust.Shared.Map; +using Robust.Shared.Player; +using Robust.Shared.Random; + +namespace Content.Server.Tiles +{ + public sealed class FloorTileSystem : EntitySystem + { + [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly StackSystem _stackSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAfterInteract); + } + + private void OnAfterInteract(EntityUid uid, FloorTileComponent component, AfterInteractEvent args) + { + if (!args.CanReach) + return; + + if (!TryComp(uid, out var stack)) + return; + + if (component.OutputTiles == null) + return; + + // this looks a bit sussy but it might be because it needs to be able to place off of grids and expand them + var location = args.ClickLocation.AlignWithClosestGridTile(); + var locationMap = location.ToMap(EntityManager); + if (locationMap.MapId == MapId.Nullspace) + return; + _mapManager.TryGetGrid(location.GetGridId(EntityManager), out var mapGrid); + + foreach (var currentTile in component.OutputTiles) + { + var currentTileDefinition = (ContentTileDefinition) _tileDefinitionManager[currentTile]; + + if (mapGrid != null) + { + var tile = mapGrid.GetTileRef(location); + var baseTurf = (ContentTileDefinition) _tileDefinitionManager[tile.Tile.TypeId]; + + if (HasBaseTurf(currentTileDefinition, baseTurf.ID)) + { + if (!_stackSystem.Use(uid, 1, stack)) + continue; + + PlaceAt(mapGrid, location, currentTileDefinition.TileId, component.PlaceTileSound); + return; + } + } + if (HasBaseTurf(currentTileDefinition, "space")) + { + mapGrid = _mapManager.CreateGrid(locationMap.MapId); + mapGrid.WorldPosition = locationMap.Position; + location = new EntityCoordinates(mapGrid.GridEntityId, Vector2.Zero); + PlaceAt(mapGrid, location, _tileDefinitionManager[component.OutputTiles[0]].TileId, component.PlaceTileSound, mapGrid.TileSize / 2f); + return; + } + } + } + + public bool HasBaseTurf(ContentTileDefinition tileDef, string baseTurf) + { + foreach (var tileBaseTurf in tileDef.BaseTurfs) + { + if (baseTurf == tileBaseTurf) + return true; + } + + return false; + } + + private void PlaceAt(IMapGrid mapGrid, EntityCoordinates location, ushort tileId, SoundSpecifier placeSound, float offset = 0) + { + var variant = _random.Pick(((ContentTileDefinition) _tileDefinitionManager[tileId]).PlacementVariants); + mapGrid.SetTile(location.Offset(new Vector2(offset, offset)), new Tile(tileId, 0, variant)); + SoundSystem.Play(Filter.Pvs(location), placeSound.GetSound(), location, AudioHelpers.WithVariation(0.125f, _random)); + } + } +}