From d4876be6f058ec54a5d7cab9d6d167b1bb5049af Mon Sep 17 00:00:00 2001 From: TemporalOroboros Date: Sat, 21 Jun 2025 08:23:19 -0700 Subject: [PATCH] Kills TurfHelpers (#37939) * Create TurfSystem equivalent for and obsolete TurfHelpers.GetTileRef * Fix EntitySystem uses of TurfHelpers.GetTileRef * Fix EntitySystem uses of TurfHelpers.TryGetTileRef * Fix construction condition uses of TurfHelpers.GetTileRef * Fix last use of TurfHelpers.IsBlockedTurf * Create TurfSystem equivalent to and obsolete TurfHelpers.GetContentTileDefinition * Fix uses of TurfHelpers.GetContentTileDefinition(TileRef) * Fix uses of TurfHelpers.GetContentTileDefinition(Tile) * Create TurfSystem equivalent to and obsolete TurfHelpers.IsSpace * Fix EntitySystem uses of TurfHelpers.IsSpace(Tile) * Fix EntitySystem uses of TurfHelpers.IsSpace(TileRef) * Fix remaining uses of TurfHelpers.IsSpace * Fix uses of TurfHelpers.GetEntitiesInTile * Delete TurfHelpers.cs * Add GetEntitiesInTile lookup methods * Convert some GetEntitiesInTile methods to LookupSystem extension methods * Use new GetEntitiesInTile methods * Recycle spiderweb hashset * Recycle floor tile hashset --- Content.Client/Mapping/MappingState.cs | 2 +- .../Abilities/Mime/MimePowersSystem.cs | 2 +- .../Commands/VariantizeCommand.cs | 4 +- .../TileReactions/CreateEntityTileReaction.cs | 42 ++--- .../Conditions/ComponentInTile.cs | 4 +- .../Decals/Commands/AddDecalCommand.cs | 3 +- Content.Server/Decals/DecalSystem.cs | 6 +- Content.Server/Dragon/DragonSystem.cs | 4 +- .../Electrocution/ElectrocutionSystem.cs | 3 +- .../EntityEffects/EntityEffectSystem.cs | 3 +- .../EntitySystems/SmokeOnTriggerSystem.cs | 3 +- .../Fluids/EntitySystems/PuddleSystem.cs | 4 +- Content.Server/Nuke/NukeSystem.cs | 4 +- .../Physics/Controllers/ConveyorController.cs | 3 +- Content.Server/Pinpointer/NavMapSystem.cs | 4 +- .../DungeonJob/DungeonJob.Exterior.cs | 2 +- .../Procedural/DungeonJob/DungeonJob.cs | 3 + Content.Server/Procedural/DungeonSystem.cs | 3 + .../Respawn/SpecialRespawnSystem.cs | 5 +- .../Revenant/EntitySystems/RevenantSystem.cs | 3 +- .../Systems/ShuttleSystem.FasterThanLight.cs | 2 +- .../Shuttles/Systems/ShuttleSystem.Impact.cs | 4 +- .../Shuttles/Systems/ShuttleSystem.cs | 3 +- .../Shuttles/Systems/ThrusterSystem.cs | 6 +- Content.Server/Spider/SpiderSystem.cs | 11 +- Content.Server/Spreader/SpreaderSystem.cs | 3 +- .../Debris/SimpleFloorPlanPopulatorSystem.cs | 3 +- .../Goliath/GoliathTentacleSystem.cs | 2 +- Content.Shared/Blocking/BlockingSystem.cs | 3 +- .../Construction/Conditions/TileNotBlocked.cs | 12 +- .../Construction/Conditions/TileType.cs | 7 +- Content.Shared/Magic/SharedMagicSystem.cs | 5 +- Content.Shared/Maps/TurfHelpers.cs | 144 ------------------ Content.Shared/Maps/TurfSystem.cs | 136 ++++++++++++++++- Content.Shared/RCD/Systems/RCDSystem.cs | 10 +- Content.Shared/Sound/SharedEmitSoundSystem.cs | 4 +- Content.Shared/Tiles/FloorTileSystem.cs | 14 +- 37 files changed, 249 insertions(+), 227 deletions(-) delete mode 100644 Content.Shared/Maps/TurfHelpers.cs diff --git a/Content.Client/Mapping/MappingState.cs b/Content.Client/Mapping/MappingState.cs index 6430f1db1e..97fbee70bc 100644 --- a/Content.Client/Mapping/MappingState.cs +++ b/Content.Client/Mapping/MappingState.cs @@ -793,7 +793,7 @@ public sealed class MappingState : GameplayStateBase if (_mapMan.TryFindGridAt(mapPos, out var gridUid, out var grid) && _entityManager.System().TryGetTileRef(gridUid, grid, coords, out var tileRef) && - _allPrototypesDict.TryGetValue(tileRef.GetContentTileDefinition(), out button)) + _allPrototypesDict.TryGetValue(_entityManager.System().GetContentTileDefinition(tileRef), out button)) { OnSelected(button); return true; diff --git a/Content.Server/Abilities/Mime/MimePowersSystem.cs b/Content.Server/Abilities/Mime/MimePowersSystem.cs index 3de356f608..29c7b1710c 100644 --- a/Content.Server/Abilities/Mime/MimePowersSystem.cs +++ b/Content.Server/Abilities/Mime/MimePowersSystem.cs @@ -82,7 +82,7 @@ namespace Content.Server.Abilities.Mime // Get the tile in front of the mime var offsetValue = xform.LocalRotation.ToWorldVec(); var coords = xform.Coordinates.Offset(offsetValue).SnapToGrid(EntityManager, _mapMan); - var tile = coords.GetTileRef(EntityManager, _mapMan); + var tile = _turf.GetTileRef(coords); if (tile == null) return; diff --git a/Content.Server/Administration/Commands/VariantizeCommand.cs b/Content.Server/Administration/Commands/VariantizeCommand.cs index 3f9b7efd07..a75f72b1c7 100644 --- a/Content.Server/Administration/Commands/VariantizeCommand.cs +++ b/Content.Server/Administration/Commands/VariantizeCommand.cs @@ -10,7 +10,6 @@ namespace Content.Server.Administration.Commands; public sealed class VariantizeCommand : IConsoleCommand { [Dependency] private readonly IEntityManager _entManager = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; public string Command => "variantize"; @@ -40,10 +39,11 @@ public sealed class VariantizeCommand : IConsoleCommand var mapsSystem = _entManager.System(); var tileSystem = _entManager.System(); + var turfSystem = _entManager.System(); foreach (var tile in mapsSystem.GetAllTiles(euid.Value, gridComp)) { - var def = tile.GetContentTileDefinition(_tileDefManager); + var def = turfSystem.GetContentTileDefinition(tile); var newTile = new Tile(tile.Tile.TypeId, tile.Tile.Flags, tileSystem.PickVariant(def)); mapsSystem.SetTile(euid.Value, gridComp, tile.GridIndices, newTile); } diff --git a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs index 0249b6255a..1499967a42 100644 --- a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs @@ -41,33 +41,33 @@ public sealed partial class CreateEntityTileReaction : ITileReaction IEntityManager entityManager, List? data) { - if (reactVolume >= Usage) + if (reactVolume < Usage) + return FixedPoint2.Zero; + + if (Whitelist != null) { - if (Whitelist != null) + var lookup = entityManager.System(); + + int acc = 0; + foreach (var ent in lookup.GetEntitiesInTile(tile, LookupFlags.Static)) { - int acc = 0; - foreach (var ent in tile.GetEntitiesInTile()) - { - var whitelistSystem = entityManager.System(); - if (whitelistSystem.IsWhitelistPass(Whitelist, ent)) - acc += 1; + var whitelistSystem = entityManager.System(); + if (whitelistSystem.IsWhitelistPass(Whitelist, ent)) + acc += 1; - if (acc >= MaxOnTile) - return FixedPoint2.Zero; - } + if (acc >= MaxOnTile) + return FixedPoint2.Zero; } + } - var random = IoCManager.Resolve(); - var xoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax); - var yoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax); - - var center = entityManager.System().GetTileCenter(tile); - var pos = center.Offset(new Vector2(xoffs, yoffs)); - entityManager.SpawnEntity(Entity, pos); + var random = IoCManager.Resolve(); + var xoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax); + var yoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax); - return Usage; - } + var center = entityManager.System().GetTileCenter(tile); + var pos = center.Offset(new Vector2(xoffs, yoffs)); + entityManager.SpawnEntity(Entity, pos); - return FixedPoint2.Zero; + return Usage; } } diff --git a/Content.Server/Construction/Conditions/ComponentInTile.cs b/Content.Server/Construction/Conditions/ComponentInTile.cs index 429c4fdabf..6af8c36e24 100644 --- a/Content.Server/Construction/Conditions/ComponentInTile.cs +++ b/Content.Server/Construction/Conditions/ComponentInTile.cs @@ -58,9 +58,7 @@ namespace Content.Server.Construction.Conditions if (!entityManager.System().TryGetTileRef(transform.GridUid.Value, grid, indices, out var tile)) return !HasEntity; - var entities = tile.GetEntitiesInTile(LookupFlags.Approximate | LookupFlags.Static, lookup); - - foreach (var ent in entities) + foreach (var ent in lookup.GetEntitiesInTile(tile, flags: LookupFlags.Approximate | LookupFlags.Static)) { if (entityManager.HasComponent(ent, type)) return HasEntity; diff --git a/Content.Server/Decals/Commands/AddDecalCommand.cs b/Content.Server/Decals/Commands/AddDecalCommand.cs index 2d9c5a1b25..e7463ff9cb 100644 --- a/Content.Server/Decals/Commands/AddDecalCommand.cs +++ b/Content.Server/Decals/Commands/AddDecalCommand.cs @@ -54,8 +54,9 @@ namespace Content.Server.Decals.Commands } var mapSystem = _entManager.System(); + var turfSystem = _entManager.System(); var coordinates = new EntityCoordinates(gridIdRaw.Value, new Vector2(x, y)); - if (mapSystem.GetTileRef(gridIdRaw.Value, grid, coordinates).IsSpace()) + if (turfSystem.IsSpace(mapSystem.GetTileRef(gridIdRaw.Value, grid, coordinates))) { shell.WriteError($"Cannot create decal on space tile at {coordinates}."); return; diff --git a/Content.Server/Decals/DecalSystem.cs b/Content.Server/Decals/DecalSystem.cs index 690d24c2e4..bc77900df7 100644 --- a/Content.Server/Decals/DecalSystem.cs +++ b/Content.Server/Decals/DecalSystem.cs @@ -29,7 +29,6 @@ namespace Content.Server.Decals { [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IAdminManager _adminManager = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefMan = default!; [Dependency] private readonly IParallelManager _parMan = default!; [Dependency] private readonly ChunkingSystem _chunking = default!; [Dependency] private readonly IConfigurationManager _conf = default!; @@ -37,6 +36,7 @@ namespace Content.Server.Decals [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly SharedMapSystem _mapSystem = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly TurfSystem _turf = default!; private readonly Dictionary> _dirtyChunks = new(); private readonly Dictionary>> _previousSentChunks = new(); @@ -167,7 +167,7 @@ namespace Content.Server.Decals foreach (var change in args.Changes) { - if (!change.NewTile.IsSpace(_tileDefMan)) + if (!_turf.IsSpace(change.NewTile)) continue; var indices = GetChunkIndices(change.GridIndices); @@ -308,7 +308,7 @@ namespace Content.Server.Decals if (!TryComp(gridId, out MapGridComponent? grid)) return false; - if (_mapSystem.GetTileRef(gridId.Value, grid, coordinates).IsSpace(_tileDefMan)) + if (_turf.IsSpace(_mapSystem.GetTileRef(gridId.Value, grid, coordinates))) return false; if (!TryComp(gridId, out DecalGridComponent? comp)) diff --git a/Content.Server/Dragon/DragonSystem.cs b/Content.Server/Dragon/DragonSystem.cs index efac049b35..960365a7ca 100644 --- a/Content.Server/Dragon/DragonSystem.cs +++ b/Content.Server/Dragon/DragonSystem.cs @@ -21,7 +21,6 @@ namespace Content.Server.Dragon; public sealed partial class DragonSystem : EntitySystem { [Dependency] private readonly CarpRiftsConditionSystem _carpRifts = default!; - [Dependency] private readonly ITileDefinitionManager _tileDef = default!; [Dependency] private readonly MovementSpeedModifierSystem _movement = default!; [Dependency] private readonly NpcFactionSystem _faction = default!; [Dependency] private readonly PopupSystem _popup = default!; @@ -30,6 +29,7 @@ public sealed partial class DragonSystem : EntitySystem [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly SharedMapSystem _map = default!; [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly TurfSystem _turf = default!; private EntityQuery _objQuery; @@ -159,7 +159,7 @@ public sealed partial class DragonSystem : EntitySystem // cant put a rift on solars foreach (var tile in _map.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(_transform.GetWorldPosition(xform), RiftTileRadius), false)) { - if (!tile.IsSpace(_tileDef)) + if (!_turf.IsSpace(tile)) continue; _popup.PopupEntity(Loc.GetString("carp-rift-space-proximity", ("proximity", RiftTileRadius)), uid, uid); diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index 957f881bed..8647f087fc 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -57,6 +57,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem [Dependency] private readonly SharedStutteringSystem _stuttering = default!; [Dependency] private readonly TagSystem _tag = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; + [Dependency] private readonly TurfSystem _turf = default!; [ValidatePrototypeId] private const string StatusEffectKey = "Electrocution"; @@ -137,7 +138,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem return false; if (electrified.NoWindowInTile) { - var tileRef = transform.Coordinates.GetTileRef(EntityManager, _mapManager); + var tileRef = _turf.GetTileRef(transform.Coordinates); if (tileRef != null) { diff --git a/Content.Server/EntityEffects/EntityEffectSystem.cs b/Content.Server/EntityEffects/EntityEffectSystem.cs index 164199c200..03a0c8bb2b 100644 --- a/Content.Server/EntityEffects/EntityEffectSystem.cs +++ b/Content.Server/EntityEffects/EntityEffectSystem.cs @@ -74,6 +74,7 @@ public sealed class EntityEffectSystem : EntitySystem [Dependency] private readonly TemperatureSystem _temperature = default!; [Dependency] private readonly SharedTransformSystem _xform = default!; [Dependency] private readonly VomitSystem _vomit = default!; + [Dependency] private readonly TurfSystem _turf = default!; public override void Initialize() { @@ -529,7 +530,7 @@ public sealed class EntityEffectSystem : EntitySystem return; } - if (_spreader.RequiresFloorToSpread(args.Effect.PrototypeId) && tileRef.Tile.IsSpace()) + if (_spreader.RequiresFloorToSpread(args.Effect.PrototypeId) && _turf.IsSpace(tileRef)) return; var coords = _map.MapToGrid(gridUid, mapCoords); diff --git a/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs b/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs index 31b4746ec2..19335d3446 100644 --- a/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs @@ -20,6 +20,7 @@ public sealed class SmokeOnTriggerSystem : SharedSmokeOnTriggerSystem [Dependency] private readonly SmokeSystem _smoke = default!; [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly SpreaderSystem _spreader = default!; + [Dependency] private readonly TurfSystem _turf = default!; public override void Initialize() { @@ -39,7 +40,7 @@ public sealed class SmokeOnTriggerSystem : SharedSmokeOnTriggerSystem return; } - if (_spreader.RequiresFloorToSpread(comp.SmokePrototype.ToString()) && tileRef.Tile.IsSpace()) + if (_spreader.RequiresFloorToSpread(comp.SmokePrototype.ToString()) && _turf.IsSpace(tileRef)) return; var coords = _map.MapToGrid(gridUid, mapCoords); diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index 94951b0113..bb7b06bd0b 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -47,7 +47,6 @@ public sealed partial class PuddleSystem : SharedPuddleSystem [Dependency] private readonly SharedMapSystem _map = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefMan = default!; [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly ReactiveSystem _reactive = default!; @@ -59,6 +58,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem [Dependency] private readonly SpeedModifierContactsSystem _speedModContacts = default!; [Dependency] private readonly TileFrictionController _tile = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly TurfSystem _turf = default!; [ValidatePrototypeId] private const string Blood = "Blood"; @@ -686,7 +686,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem } // If space return early, let that spill go out into the void - if (tileRef.Tile.IsEmpty || tileRef.IsSpace(_tileDefMan)) + if (tileRef.Tile.IsEmpty || _turf.IsSpace(tileRef)) { puddleUid = EntityUid.Invalid; return false; diff --git a/Content.Server/Nuke/NukeSystem.cs b/Content.Server/Nuke/NukeSystem.cs index 77be71f7bc..81fbf074da 100644 --- a/Content.Server/Nuke/NukeSystem.cs +++ b/Content.Server/Nuke/NukeSystem.cs @@ -32,7 +32,6 @@ public sealed class NukeSystem : EntitySystem [Dependency] private readonly ChatSystem _chatSystem = default!; [Dependency] private readonly ExplosionSystem _explosions = default!; [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; [Dependency] private readonly ItemSlotsSystem _itemSlots = default!; [Dependency] private readonly NavMapSystem _navMap = default!; [Dependency] private readonly PointLightSystem _pointLight = default!; @@ -45,6 +44,7 @@ public sealed class NukeSystem : EntitySystem [Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; [Dependency] private readonly AppearanceSystem _appearance = default!; + [Dependency] private readonly TurfSystem _turf = default!; /// /// Used to calculate when the nuke song should start playing for maximum kino with the nuke sfx @@ -210,7 +210,7 @@ public sealed class NukeSystem : EntitySystem foreach (var tile in _map.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(worldPos, component.RequiredFloorRadius), false)) { - if (!tile.IsSpace(_tileDefManager)) + if (!_turf.IsSpace(tile)) continue; var msg = Loc.GetString("nuke-component-cant-anchor-floor"); diff --git a/Content.Server/Physics/Controllers/ConveyorController.cs b/Content.Server/Physics/Controllers/ConveyorController.cs index fa278278e2..9ec05be9b7 100644 --- a/Content.Server/Physics/Controllers/ConveyorController.cs +++ b/Content.Server/Physics/Controllers/ConveyorController.cs @@ -19,6 +19,7 @@ public sealed class ConveyorController : SharedConveyorController [Dependency] private readonly DeviceLinkSystem _signalSystem = default!; [Dependency] private readonly MaterialReclaimerSystem _materialReclaimer = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly TurfSystem _turf = default!; public override void Initialize() { @@ -123,7 +124,7 @@ public sealed class ConveyorController : SharedConveyorController var xform = ent.Comp; - var beltTileRef = xform.Coordinates.GetTileRef(EntityManager, MapManager); + var beltTileRef = _turf.GetTileRef(xform.Coordinates); if (beltTileRef != null) { diff --git a/Content.Server/Pinpointer/NavMapSystem.cs b/Content.Server/Pinpointer/NavMapSystem.cs index 7511e60cde..89e2837b35 100644 --- a/Content.Server/Pinpointer/NavMapSystem.cs +++ b/Content.Server/Pinpointer/NavMapSystem.cs @@ -28,7 +28,7 @@ public sealed partial class NavMapSystem : SharedNavMapSystem [Dependency] private readonly SharedTransformSystem _transformSystem = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; + [Dependency] private readonly TurfSystem _turfSystem = default!; public const float CloseDistance = 15f; public const float FarDistance = 30f; @@ -118,7 +118,7 @@ public sealed partial class NavMapSystem : SharedNavMapSystem var relative = SharedMapSystem.GetChunkRelative(tile, ChunkSize); ref var tileData = ref chunk.TileData[GetTileIndex(relative)]; - if (change.NewTile.IsSpace(_tileDefManager)) + if (_turfSystem.IsSpace(change.NewTile)) { tileData = 0; if (PruneEmpty((ev.Entity, navMap), chunk)) diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.Exterior.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Exterior.cs index 92237dca2a..4f2f564ded 100644 --- a/Content.Server/Procedural/DungeonJob/DungeonJob.Exterior.cs +++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Exterior.cs @@ -30,7 +30,7 @@ public sealed partial class DungeonJob SharedPathfindingSystem.GridCast(startTile, position, tile => { if (!_maps.TryGetTileRef(_gridUid, _grid, tile, out var tileRef) || - tileRef.Tile.IsSpace(_tileDefManager)) + _turf.IsSpace(tileRef.Tile)) { return true; } diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.cs index f2bd5a4394..77404fc963 100644 --- a/Content.Server/Procedural/DungeonJob/DungeonJob.cs +++ b/Content.Server/Procedural/DungeonJob/DungeonJob.cs @@ -42,6 +42,7 @@ public sealed partial class DungeonJob : Job> private readonly EntityTableSystem _entTable; private readonly TagSystem _tags; private readonly TileSystem _tile; + private readonly TurfSystem _turf; private readonly SharedMapSystem _maps; private readonly SharedTransformSystem _transform; @@ -70,6 +71,7 @@ public sealed partial class DungeonJob : Job> DungeonSystem dungeon, EntityLookupSystem lookup, TileSystem tile, + TurfSystem turf, SharedTransformSystem transform, DungeonConfig gen, MapGridComponent grid, @@ -89,6 +91,7 @@ public sealed partial class DungeonJob : Job> _dungeon = dungeon; _lookup = lookup; _tile = tile; + _turf = turf; _tags = _entManager.System(); _maps = _entManager.System(); _entTable = _entManager.System(); diff --git a/Content.Server/Procedural/DungeonSystem.cs b/Content.Server/Procedural/DungeonSystem.cs index 9cc3fbb158..3a0a7ab2cd 100644 --- a/Content.Server/Procedural/DungeonSystem.cs +++ b/Content.Server/Procedural/DungeonSystem.cs @@ -36,6 +36,7 @@ public sealed partial class DungeonSystem : SharedDungeonSystem [Dependency] private readonly DecalSystem _decals = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly TileSystem _tile = default!; + [Dependency] private readonly TurfSystem _turf = default!; [Dependency] private readonly MapLoaderSystem _loader = default!; [Dependency] private readonly SharedMapSystem _maps = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; @@ -212,6 +213,7 @@ public sealed partial class DungeonSystem : SharedDungeonSystem this, _lookup, _tile, + _turf, _transform, gen, grid, @@ -244,6 +246,7 @@ public sealed partial class DungeonSystem : SharedDungeonSystem this, _lookup, _tile, + _turf, _transform, gen, grid, diff --git a/Content.Server/Respawn/SpecialRespawnSystem.cs b/Content.Server/Respawn/SpecialRespawnSystem.cs index cde0fd2aa0..45229b7418 100644 --- a/Content.Server/Respawn/SpecialRespawnSystem.cs +++ b/Content.Server/Respawn/SpecialRespawnSystem.cs @@ -17,7 +17,6 @@ namespace Content.Server.Respawn; public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem { [Dependency] private readonly IAdminLogManager _adminLog = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly AtmosphereSystem _atmosphere = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; @@ -108,7 +107,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem foreach (var tile in _map.GetTilesIntersecting(entityGridUid.Value, grid, circle)) { - if (tile.IsSpace(_tileDefinitionManager) + if (_turf.IsSpace(tile) || _turf.IsTileBlocked(tile, CollisionGroup.MobMask) || !_atmosphere.IsTileMixtureProbablySafe(entityGridUid, entityMapUid.Value, _map.TileIndicesFor((entityGridUid.Value, grid), mapPos))) @@ -179,7 +178,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem foreach (var newTileRef in _map.GetTilesIntersecting(targetGrid, grid, circle)) { - if (newTileRef.IsSpace(_tileDefinitionManager) || _turf.IsTileBlocked(newTileRef, CollisionGroup.MobMask) || !_atmosphere.IsTileMixtureProbablySafe(targetGrid, targetMap, mapTarget)) + if (_turf.IsSpace(newTileRef) || _turf.IsTileBlocked(newTileRef, CollisionGroup.MobMask) || !_atmosphere.IsTileMixtureProbablySafe(targetGrid, targetMap, mapTarget)) continue; found = true; diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs index b319db09e0..0501f5afc3 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs @@ -45,6 +45,7 @@ public sealed partial class RevenantSystem : EntitySystem [Dependency] private readonly StoreSystem _store = default!; [Dependency] private readonly TagSystem _tag = default!; [Dependency] private readonly VisibilitySystem _visibility = default!; + [Dependency] private readonly TurfSystem _turf = default!; [ValidatePrototypeId] private const string RevenantShopId = "ActionRevenantShop"; @@ -164,7 +165,7 @@ public sealed partial class RevenantSystem : EntitySystem return false; } - var tileref = Transform(uid).Coordinates.GetTileRef(); + var tileref = _turf.GetTileRef(Transform(uid).Coordinates); if (tileref != null) { if(_physics.GetEntitiesIntersectingBody(uid, (int) CollisionGroup.Impassable).Count > 0) diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs index 2fc11db4a4..13e13bf8f3 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs @@ -679,7 +679,7 @@ public sealed partial class ShuttleSystem // only toss if its on lattice/space var tile = _mapSystem.GetTileRef(shuttleEntity, shuttleGrid, childXform.Coordinates); - if (!tile.IsSpace(_tileDefManager)) + if (!_turf.IsSpace(tile)) return; var throwDirection = childXform.LocalPosition - shuttleBody.LocalCenter; diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.Impact.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.Impact.cs index f165990f1c..29657af295 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.Impact.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.Impact.cs @@ -275,7 +275,7 @@ public sealed partial class ShuttleSystem foreach (var tileRef in _mapSystem.GetLocalTilesIntersecting(uid, grid, new Circle(centerTile, radius))) { - var def = (ContentTileDefinition)_tileDefManager[tileRef.Tile.TypeId]; + var def = _turf.GetContentTileDefinition(tileRef); mass += def.Mass; tileCount++; @@ -402,7 +402,7 @@ public sealed partial class ShuttleSystem continue; // Mark tiles for breaking/effects - var def = (ContentTileDefinition)_tileDefManager[_mapSystem.GetTileRef(uid, grid, tileData.Tile).Tile.TypeId]; + var def = _turf.GetContentTileDefinition(_mapSystem.GetTileRef(uid, grid, tileData.Tile)); if (tileData.Energy > def.Mass * _tileBreakEnergyMultiplier) brokenTiles.Add((tileData.Tile, Tile.Empty)); diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.cs index 71d51e3187..f271be108f 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.cs @@ -28,6 +28,7 @@ using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; +using Content.Shared.Maps; namespace Content.Server.Shuttles.Systems; @@ -40,7 +41,6 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPrototypeManager _protoManager = default!; [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; [Dependency] private readonly BiomeSystem _biomes = default!; [Dependency] private readonly BodySystem _bobby = default!; [Dependency] private readonly BuckleSystem _buckle = default!; @@ -62,6 +62,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem [Dependency] private readonly ThrowingSystem _throwing = default!; [Dependency] private readonly ThrusterSystem _thruster = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; + [Dependency] private readonly TurfSystem _turf = default!; private EntityQuery _buckleQuery; private EntityQuery _gridQuery; diff --git a/Content.Server/Shuttles/Systems/ThrusterSystem.cs b/Content.Server/Shuttles/Systems/ThrusterSystem.cs index 42c249c9ab..e7f93043cb 100644 --- a/Content.Server/Shuttles/Systems/ThrusterSystem.cs +++ b/Content.Server/Shuttles/Systems/ThrusterSystem.cs @@ -26,13 +26,13 @@ namespace Content.Server.Shuttles.Systems; public sealed class ThrusterSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; [Dependency] private readonly SharedMapSystem _mapSystem = default!; [Dependency] private readonly AmbientSoundSystem _ambient = default!; [Dependency] private readonly FixtureSystem _fixtureSystem = default!; [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly SharedPointLightSystem _light = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly TurfSystem _turf = default!; // Essentially whenever thruster enables we update the shuttle's available impulses which are used for movement. // This is done for each direction available. @@ -97,7 +97,7 @@ public sealed class ThrusterSystem : EntitySystem foreach (var change in args.Changes) { // If the old tile was space but the new one isn't then disable all adjacent thrusters - if (change.NewTile.IsSpace(_tileDefManager) || !change.OldTile.IsSpace(_tileDefManager)) + if (_turf.IsSpace(change.NewTile) || !_turf.IsSpace(change.OldTile)) continue; var tilePos = change.GridIndices; @@ -457,7 +457,7 @@ public sealed class ThrusterSystem : EntitySystem var mapGrid = Comp(xform.GridUid.Value); var tile = _mapSystem.GetTileRef(xform.GridUid.Value, mapGrid, new Vector2i((int)Math.Floor(x), (int)Math.Floor(y))); - return tile.Tile.IsSpace(); + return _turf.IsSpace(tile); } #region Burning diff --git a/Content.Server/Spider/SpiderSystem.cs b/Content.Server/Spider/SpiderSystem.cs index 449e43984c..6e2e2b59a2 100644 --- a/Content.Server/Spider/SpiderSystem.cs +++ b/Content.Server/Spider/SpiderSystem.cs @@ -10,6 +10,13 @@ namespace Content.Server.Spider; public sealed class SpiderSystem : SharedSpiderSystem { [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly TurfSystem _turf = default!; + + /// + /// A recycled hashset used to check turfs for spiderwebs. + /// + private readonly HashSet _webs = []; public override void Initialize() { @@ -66,7 +73,9 @@ public sealed class SpiderSystem : SharedSpiderSystem private bool IsTileBlockedByWeb(EntityCoordinates coords) { - foreach (var entity in coords.GetEntitiesInTile()) + _webs.Clear(); + _turf.GetEntitiesInTile(coords, _webs); + foreach (var entity in _webs) { if (HasComp(entity)) return true; diff --git a/Content.Server/Spreader/SpreaderSystem.cs b/Content.Server/Spreader/SpreaderSystem.cs index 50f5d81183..328f4f0504 100644 --- a/Content.Server/Spreader/SpreaderSystem.cs +++ b/Content.Server/Spreader/SpreaderSystem.cs @@ -23,6 +23,7 @@ public sealed class SpreaderSystem : EntitySystem [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly SharedMapSystem _map = default!; [Dependency] private readonly TagSystem _tag = default!; + [Dependency] private readonly TurfSystem _turf = default!; /// /// Cached maximum number of updates per spreader prototype. This is applied per-grid. @@ -246,7 +247,7 @@ public sealed class SpreaderSystem : EntitySystem if (!_map.TryGetTileRef(neighborEnt, neighborGrid, neighborPos, out var tileRef) || tileRef.Tile.IsEmpty) continue; - if (spreaderPrototype.PreventSpreadOnSpaced && tileRef.Tile.IsSpace()) + if (spreaderPrototype.PreventSpreadOnSpaced && _turf.IsSpace(tileRef)) continue; var directionEnumerator = _map.GetAnchoredEntitiesEnumerator(neighborEnt, neighborGrid, neighborPos); diff --git a/Content.Server/Worldgen/Systems/Debris/SimpleFloorPlanPopulatorSystem.cs b/Content.Server/Worldgen/Systems/Debris/SimpleFloorPlanPopulatorSystem.cs index ed26053114..e936d550bb 100644 --- a/Content.Server/Worldgen/Systems/Debris/SimpleFloorPlanPopulatorSystem.cs +++ b/Content.Server/Worldgen/Systems/Debris/SimpleFloorPlanPopulatorSystem.cs @@ -14,6 +14,7 @@ public sealed class SimpleFloorPlanPopulatorSystem : BaseWorldSystem [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinition = default!; [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly TurfSystem _turf = default!; /// public override void Initialize() @@ -30,7 +31,7 @@ public sealed class SimpleFloorPlanPopulatorSystem : BaseWorldSystem while (enumerator.MoveNext(out var tile)) { var coords = _map.GridTileToLocal(uid, grid, tile.Value.GridIndices); - var selector = tile.Value.Tile.GetContentTileDefinition(_tileDefinition).ID; + var selector = _turf.GetContentTileDefinition(tile.Value).ID; if (!component.Caches.TryGetValue(selector, out var cache)) continue; diff --git a/Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs b/Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs index e0a0453285..a220781420 100644 --- a/Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs +++ b/Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs @@ -55,7 +55,7 @@ public sealed class GoliathTentacleSystem : EntitySystem foreach (var pos in spawnPos) { if (!_map.TryGetTileRef(grid, gridComp, pos, out var tileRef) || - tileRef.IsSpace() || + _turf.IsSpace(tileRef) || _turf.IsTileBlocked(tileRef, CollisionGroup.Impassable)) { continue; diff --git a/Content.Shared/Blocking/BlockingSystem.cs b/Content.Shared/Blocking/BlockingSystem.cs index c920fde13b..619adf7918 100644 --- a/Content.Shared/Blocking/BlockingSystem.cs +++ b/Content.Shared/Blocking/BlockingSystem.cs @@ -31,6 +31,7 @@ public sealed partial class BlockingSystem : EntitySystem [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly ExamineSystemShared _examine = default!; + [Dependency] private readonly TurfSystem _turf = default!; public override void Initialize() { @@ -165,7 +166,7 @@ public sealed partial class BlockingSystem : EntitySystem } //Don't allow someone to block if someone else is on the same tile - var playerTileRef = xform.Coordinates.GetTileRef(); + var playerTileRef = _turf.GetTileRef(xform.Coordinates); if (playerTileRef != null) { var intersecting = _lookup.GetLocalEntitiesIntersecting(playerTileRef.Value, 0f); diff --git a/Content.Shared/Construction/Conditions/TileNotBlocked.cs b/Content.Shared/Construction/Conditions/TileNotBlocked.cs index 02bc84f736..c56dcb1583 100644 --- a/Content.Shared/Construction/Conditions/TileNotBlocked.cs +++ b/Content.Shared/Construction/Conditions/TileNotBlocked.cs @@ -1,4 +1,5 @@ using Content.Shared.Maps; +using Content.Shared.Physics; using JetBrains.Annotations; using Robust.Shared.Map; @@ -14,24 +15,25 @@ public sealed partial class TileNotBlocked : IConstructionCondition public bool Condition(EntityUid user, EntityCoordinates location, Direction direction) { - var tileRef = location.GetTileRef(); + if (!IoCManager.Resolve().TrySystem(out var turfSystem)) + return false; - if (tileRef == null) + if (!turfSystem.TryGetTileRef(location, out var tileRef)) { return false; } - if (tileRef.Value.IsSpace() && _failIfSpace) + if (turfSystem.IsSpace(tileRef.Value) && _failIfSpace) { return false; } - if (!tileRef.Value.GetContentTileDefinition().Sturdy && _failIfNotSturdy) + if (!turfSystem.GetContentTileDefinition(tileRef.Value).Sturdy && _failIfNotSturdy) { return false; } - return !tileRef.Value.IsBlockedTurf(_filterMobs); + return !turfSystem.IsTileBlocked(tileRef.Value, _filterMobs ? CollisionGroup.MobMask : CollisionGroup.Impassable); } public ConstructionGuideEntry GenerateGuideEntry() diff --git a/Content.Shared/Construction/Conditions/TileType.cs b/Content.Shared/Construction/Conditions/TileType.cs index 3ffdf66050..e066e6af2e 100644 --- a/Content.Shared/Construction/Conditions/TileType.cs +++ b/Content.Shared/Construction/Conditions/TileType.cs @@ -20,12 +20,13 @@ namespace Content.Shared.Construction.Conditions public bool Condition(EntityUid user, EntityCoordinates location, Direction direction) { - var tileFound = location.GetTileRef(); + if (!IoCManager.Resolve().TrySystem(out var turfSystem)) + return false; - if (tileFound == null) + if (!turfSystem.TryGetTileRef(location, out var tileFound)) return false; - var tile = tileFound.Value.Tile.GetContentTileDefinition(); + var tile = turfSystem.GetContentTileDefinition(tileFound.Value); foreach (var targetTile in TargetTiles) { if (tile.ID == targetTile) diff --git a/Content.Shared/Magic/SharedMagicSystem.cs b/Content.Shared/Magic/SharedMagicSystem.cs index 4bfe2e1fe5..09b289c2be 100644 --- a/Content.Shared/Magic/SharedMagicSystem.cs +++ b/Content.Shared/Magic/SharedMagicSystem.cs @@ -62,6 +62,7 @@ public abstract class SharedMagicSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedMindSystem _mind = default!; [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly TurfSystem _turf = default!; private static readonly ProtoId InvalidForGlobalSpawnSpellTag = "InvalidForGlobalSpawnSpell"; @@ -158,7 +159,7 @@ public abstract class SharedMagicSystem : EntitySystem if (!TryComp(casterXform.GridUid, out var mapGrid)) return new List(); - if (!directionPos.TryGetTileRef(out var tileReference, EntityManager, _mapManager)) + if (!_turf.TryGetTileRef(directionPos, out var tileReference)) return new List(); var tileIndex = tileReference.Value.GridIndices; @@ -171,7 +172,7 @@ public abstract class SharedMagicSystem : EntitySystem if (!TryComp(casterXform.GridUid, out var mapGrid)) return new List(); - if (!directionPos.TryGetTileRef(out var tileReference, EntityManager, _mapManager)) + if (!_turf.TryGetTileRef(directionPos, out var tileReference)) return new List(); var tileIndex = tileReference.Value.GridIndices; diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs deleted file mode 100644 index dfa12f3d8f..0000000000 --- a/Content.Shared/Maps/TurfHelpers.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; -using Content.Shared.Physics; -using Robust.Shared.Map; -using Robust.Shared.Map.Components; -using Robust.Shared.Random; - -namespace Content.Shared.Maps -{ - // TODO move all these methods to LookupSystem or TurfSystem - // That, or make the interface arguments non-optional so people stop failing to pass them in. - public static class TurfHelpers - { - /// - /// Attempts to get the turf at a certain coordinates or null if no such turf is found. - /// - public static TileRef? GetTileRef(this EntityCoordinates coordinates, IEntityManager? entityManager = null, IMapManager? mapManager = null) - { - entityManager ??= IoCManager.Resolve(); - - if (!coordinates.IsValid(entityManager)) - return null; - - mapManager ??= IoCManager.Resolve(); - var pos = entityManager.System().ToMapCoordinates(coordinates); - if (!mapManager.TryFindGridAt(pos, out _, out var grid)) - return null; - - if (!grid.TryGetTileRef(coordinates, out var tile)) - return null; - - return tile; - } - - public static bool TryGetTileRef(this EntityCoordinates coordinates, [NotNullWhen(true)] out TileRef? turf, IEntityManager? entityManager = null, IMapManager? mapManager = null) - { - return (turf = coordinates.GetTileRef(entityManager, mapManager)) != null; - } - - /// - /// Returns the content tile definition for a tile. - /// - public static ContentTileDefinition GetContentTileDefinition(this Tile tile, ITileDefinitionManager? tileDefinitionManager = null) - { - tileDefinitionManager ??= IoCManager.Resolve(); - return (ContentTileDefinition)tileDefinitionManager[tile.TypeId]; - } - - /// - /// Returns whether a tile is considered space. - /// - public static bool IsSpace(this Tile tile, ITileDefinitionManager? tileDefinitionManager = null) - { - return tile.GetContentTileDefinition(tileDefinitionManager).MapAtmosphere; - } - - /// - /// Returns the content tile definition for a tile ref. - /// - public static ContentTileDefinition GetContentTileDefinition(this TileRef tile, ITileDefinitionManager? tileDefinitionManager = null) - { - return tile.Tile.GetContentTileDefinition(tileDefinitionManager); - } - - /// - /// Returns whether a tile ref is considered space. - /// - public static bool IsSpace(this TileRef tile, ITileDefinitionManager? tileDefinitionManager = null) - { - return tile.Tile.IsSpace(tileDefinitionManager); - } - - /// - /// Helper that returns all entities in a turf. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [Obsolete("Use the lookup system")] - public static IEnumerable GetEntitiesInTile(this TileRef turf, LookupFlags flags = LookupFlags.Static, EntityLookupSystem? lookupSystem = null) - { - lookupSystem ??= EntitySystem.Get(); - - if (!GetWorldTileBox(turf, out var worldBox)) - return Enumerable.Empty(); - - return lookupSystem.GetEntitiesIntersecting(turf.GridUid, worldBox, flags); - } - - /// - /// Helper that returns all entities in a turf. - /// - [Obsolete("Use the lookup system")] - public static IEnumerable GetEntitiesInTile(this EntityCoordinates coordinates, LookupFlags flags = LookupFlags.Static, EntityLookupSystem? lookupSystem = null) - { - var turf = coordinates.GetTileRef(); - - if (turf == null) - return Enumerable.Empty(); - - return GetEntitiesInTile(turf.Value, flags, lookupSystem); - } - - /// - /// Checks if a turf has something dense on it. - /// - [Obsolete("Use turf system")] - public static bool IsBlockedTurf(this TileRef turf, bool filterMobs, EntityLookupSystem? physics = null) - { - CollisionGroup mask = filterMobs - ? CollisionGroup.MobMask - : CollisionGroup.Impassable; - - return IoCManager.Resolve().GetEntitySystem().IsTileBlocked(turf, mask); - } - - /// - /// Creates a box the size of a tile, at the same position in the world as the tile. - /// - [Obsolete] - private static bool GetWorldTileBox(TileRef turf, out Box2Rotated res) - { - var entManager = IoCManager.Resolve(); - var xformSystem = entManager.System(); - - if (entManager.TryGetComponent(turf.GridUid, out var tileGrid)) - { - var gridRot = xformSystem.GetWorldRotation(turf.GridUid); - - // This is scaled to 90 % so it doesn't encompass walls on other tiles. - var tileBox = Box2.UnitCentered.Scale(0.9f); - tileBox = tileBox.Scale(tileGrid.TileSize); - var worldPos = tileGrid.GridTileToWorldPos(turf.GridIndices); - tileBox = tileBox.Translated(worldPos); - // Now tileBox needs to be rotated to match grid rotation - res = new Box2Rotated(tileBox, gridRot, worldPos); - return true; - } - - // Have to "return something" - res = Box2Rotated.UnitCentered; - return false; - } - } -} diff --git a/Content.Shared/Maps/TurfSystem.cs b/Content.Shared/Maps/TurfSystem.cs index 8a4bbf68be..f5477441d9 100644 --- a/Content.Shared/Maps/TurfSystem.cs +++ b/Content.Shared/Maps/TurfSystem.cs @@ -1,8 +1,11 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Numerics; using Content.Shared.Physics; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics; +using Robust.Shared.Toolshed.Commands.Values; namespace Content.Shared.Maps; @@ -11,8 +14,43 @@ namespace Content.Shared.Maps; /// public sealed class TurfSystem : EntitySystem { + [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly EntityLookupSystem _entityLookup = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedMapSystem _mapSystem = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefinitions = default!; + + + /// + /// Attempts to get the turf at or under some given coordinates or null if no such turf exists. + /// + /// The coordinates to search for a turf. + /// A for the turf found at the given coordinates or null if no such turf exists. + public TileRef? GetTileRef(EntityCoordinates coordinates) + { + if (!coordinates.IsValid(EntityManager)) + return null; + + var pos = _transform.ToMapCoordinates(coordinates); + if (!_mapManager.TryFindGridAt(pos, out var gridUid, out var gridComp)) + return null; + + if (!_mapSystem.TryGetTileRef(gridUid, gridComp, coordinates, out var tile)) + return null; + + return tile; + } + + /// + /// Attempts to get the turf at or under some given coordinates. + /// + /// The coordinates to search for a turf. + /// Returns the turf found at the given coordinates if any. + /// True if a turf was found at the given coordinates, false otherwise. + public bool TryGetTileRef(EntityCoordinates coordinates, [NotNullWhen(true)] out TileRef? tile) + { + return (tile = GetTileRef(coordinates)) is not null; + } /// /// Returns true if a given tile is blocked by physics-enabled entities. @@ -63,14 +101,14 @@ public sealed class TurfSystem : EntitySystem rot -= gridRot; pos = (-gridRot).RotateVec(pos - gridPos); - var xform = new Transform(pos, (float) rot.Theta); + var xform = new Transform(pos, (float)rot.Theta); foreach (var fixture in fixtures.Fixtures.Values) { if (!fixture.Hard) continue; - if ((fixture.CollisionLayer & (int) mask) == 0) + if ((fixture.CollisionLayer & (int)mask) == 0) continue; for (var i = 0; i < fixture.Shape.ChildCount; i++) @@ -86,6 +124,26 @@ public sealed class TurfSystem : EntitySystem return false; } + /// + /// Returns whether a tile is considered to be space or directly exposed to space. + /// + /// The tile in question. + /// True if the tile is considered to be space, false otherwise. + public bool IsSpace(Tile tile) + { + return GetContentTileDefinition(tile).MapAtmosphere; + } + + /// + /// Returns whether a tile is considered to be space or directly exposed to space. + /// + /// The tile in question. + /// True if the tile is considered to be space, false otherwise. + public bool IsSpace(TileRef tile) + { + return IsSpace(tile.Tile); + } + /// /// Returns the location of the centre of the tile in grid coordinates. /// @@ -95,4 +153,78 @@ public sealed class TurfSystem : EntitySystem var center = (turf.GridIndices + new Vector2(0.5f, 0.5f)) * grid.TileSize; return new EntityCoordinates(turf.GridUid, center); } + + /// + /// Returns the content tile definition for a tile. + /// + public ContentTileDefinition GetContentTileDefinition(Tile tile) + { + return (ContentTileDefinition)_tileDefinitions[tile.TypeId]; + } + + /// + /// Returns the content tile definition for a tile ref. + /// + public ContentTileDefinition GetContentTileDefinition(TileRef tile) + { + return GetContentTileDefinition(tile.Tile); + } + + /// + /// Collects all of the entities intersecting with the turf at a given position into a provided + /// + /// The position of the turf to search for entities. + /// The hashset used to collect the relevant entities. + /// A set of lookup categories to search for relevant entities. + public void GetEntitiesInTile(EntityCoordinates coords, HashSet intersecting, LookupFlags flags = LookupFlags.Static) + { + if (!TryGetTileRef(coords, out var tileRef)) + return; + + _entityLookup.GetEntitiesInTile(tileRef.Value, intersecting, flags); + } + + /// + /// Returns a collection containing all of the entities overlapping with the turf at a given position. + /// + /// + /// A hashset containing all of the entities overlapping with the turf in question. + public HashSet GetEntitiesInTile(EntityCoordinates coords, LookupFlags flags = LookupFlags.Static) + { + if (!TryGetTileRef(coords, out var tileRef)) + return []; + + return _entityLookup.GetEntitiesInTile(tileRef.Value, flags); + } +} + +/// +/// Extension methods for looking up entities with respect to given turfs. +/// +public static partial class TurfLookupExtensions +{ + /// + /// Collects all of the entities overlapping with a given turf into a provided . + /// + /// The turf in question. + /// The hashset used to collect the relevant entities. + /// A set of lookup categories to search for relevant entities. + public static void GetEntitiesInTile(this EntityLookupSystem lookupSystem, TileRef turf, HashSet intersecting, LookupFlags flags = LookupFlags.Static) + { + var bounds = lookupSystem.GetWorldBounds(turf); + bounds.Box = bounds.Box.Scale(0.9f); // Otherwise the box can clip into neighboring tiles. + lookupSystem.GetEntitiesIntersecting(turf.GridUid, bounds, intersecting, flags); + } + + /// + /// Returns a collection containing all of the entities overlapping with a given turf. + /// + /// + /// A hashset containing all of the entities overlapping with the turf in question. + public static HashSet GetEntitiesInTile(this EntityLookupSystem lookupSystem, TileRef turf, LookupFlags flags = LookupFlags.Static) + { + var intersecting = new HashSet(); + lookupSystem.GetEntitiesInTile(turf, intersecting, flags); + return intersecting; + } } diff --git a/Content.Shared/RCD/Systems/RCDSystem.cs b/Content.Shared/RCD/Systems/RCDSystem.cs index 238daf6bf7..6d85b171e0 100644 --- a/Content.Shared/RCD/Systems/RCDSystem.cs +++ b/Content.Shared/RCD/Systems/RCDSystem.cs @@ -175,7 +175,7 @@ public sealed class RCDSystem : EntitySystem else { var deconstructedTile = _mapSystem.GetTileRef(gridUid.Value, mapGrid, location); - var protoName = !deconstructedTile.IsSpace() ? _deconstructTileProto : _deconstructLatticeProto; + var protoName = !_turf.IsSpace(deconstructedTile) ? _deconstructTileProto : _deconstructLatticeProto; if (_protoManager.TryIndex(protoName, out var deconProto)) { @@ -383,7 +383,7 @@ public sealed class RCDSystem : EntitySystem } // Check rule: Must place on subfloor - if (prototype.ConstructionRules.Contains(RcdConstructionRule.MustBuildOnSubfloor) && !tile.Tile.GetContentTileDefinition().IsSubFloor) + if (prototype.ConstructionRules.Contains(RcdConstructionRule.MustBuildOnSubfloor) && !_turf.GetContentTileDefinition(tile).IsSubFloor) { if (popMsgs) _popup.PopupClient(Loc.GetString("rcd-component-must-build-on-subfloor-message"), uid, user); @@ -404,7 +404,7 @@ public sealed class RCDSystem : EntitySystem } // Check rule: Tiles can't be identical - if (tile.Tile.GetContentTileDefinition().ID == prototype.Prototype) + if (_turf.GetContentTileDefinition(tile).ID == prototype.Prototype) { if (popMsgs) _popup.PopupClient(Loc.GetString("rcd-component-cannot-build-identical-tile"), uid, user); @@ -487,7 +487,7 @@ public sealed class RCDSystem : EntitySystem } // The tile cannot be destroyed - var tileDef = (ContentTileDefinition) _tileDefMan[tile.Tile.TypeId]; + var tileDef = _turf.GetContentTileDefinition(tile); if (tileDef.Indestructible) { @@ -559,7 +559,7 @@ public sealed class RCDSystem : EntitySystem if (target == null) { // Deconstruct tile (either converts the tile to lattice, or removes lattice) - var tileDef = (tile.Tile.GetContentTileDefinition().ID != "Lattice") ? new Tile(_tileDefMan["Lattice"].TileId) : Tile.Empty; + var tileDef = (_turf.GetContentTileDefinition(tile).ID != "Lattice") ? new Tile(_tileDefMan["Lattice"].TileId) : Tile.Empty; _mapSystem.SetTile(gridUid, mapGrid, position, tileDef); _adminLogger.Add(LogType.RCD, LogImpact.High, $"{ToPrettyString(user):user} used RCD to set grid: {gridUid} tile: {position} open to space"); } diff --git a/Content.Shared/Sound/SharedEmitSoundSystem.cs b/Content.Shared/Sound/SharedEmitSoundSystem.cs index 58d541e363..38af0677fa 100644 --- a/Content.Shared/Sound/SharedEmitSoundSystem.cs +++ b/Content.Shared/Sound/SharedEmitSoundSystem.cs @@ -31,13 +31,13 @@ public abstract class SharedEmitSoundSystem : EntitySystem { [Dependency] protected readonly IGameTiming Timing = default!; [Dependency] private readonly INetManager _netMan = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefMan = default!; [Dependency] protected readonly IRobustRandom Random = default!; [Dependency] private readonly SharedAmbientSoundSystem _ambient = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; [Dependency] protected readonly SharedPopupSystem Popup = default!; [Dependency] private readonly SharedMapSystem _map = default!; [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + [Dependency] private readonly TurfSystem _turf = default!; public override void Initialize() { @@ -135,7 +135,7 @@ public abstract class SharedEmitSoundSystem : EntitySystem var tile = _map.GetTileRef(xform.GridUid.Value, grid, xform.Coordinates); // Handle maps being grids (we'll still emit the sound). - if (xform.GridUid != xform.MapUid && tile.IsSpace(_tileDefMan)) + if (xform.GridUid != xform.MapUid && _turf.IsSpace(tile)) return; // hand throwing not predicted sadly diff --git a/Content.Shared/Tiles/FloorTileSystem.cs b/Content.Shared/Tiles/FloorTileSystem.cs index d798fa2473..67283eeea0 100644 --- a/Content.Shared/Tiles/FloorTileSystem.cs +++ b/Content.Shared/Tiles/FloorTileSystem.cs @@ -37,9 +37,15 @@ public sealed class FloorTileSystem : EntitySystem [Dependency] private readonly TileSystem _tile = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly TurfSystem _turf = default!; private static readonly Vector2 CheckRange = new(1f, 1f); + /// + /// A recycled hashset used to check for walls when trying to place tiles on turfs. + /// + private readonly HashSet _turfCheck = []; + public override void Initialize() { base.Initialize(); @@ -104,14 +110,16 @@ public sealed class FloorTileSystem : EntitySystem // if user can access tile center then they can place floor // otherwise check it isn't blocked by a wall - if (!canAccessCenter) + if (!canAccessCenter && _turf.TryGetTileRef(location, out var tileRef)) { - foreach (var ent in location.GetEntitiesInTile(lookupSystem: _lookup)) + _turfCheck.Clear(); + _lookup.GetEntitiesInTile(tileRef.Value, _turfCheck); + foreach (var ent in _turfCheck) { if (physicQuery.TryGetComponent(ent, out var phys) && phys.BodyType == BodyType.Static && phys.Hard && - (phys.CollisionLayer & (int) CollisionGroup.Impassable) != 0) + (phys.CollisionLayer & (int)CollisionGroup.Impassable) != 0) { return; } -- 2.51.2