diff --git a/Content.Client/IconSmoothing/IconSmoothSystem.cs b/Content.Client/IconSmoothing/IconSmoothSystem.cs index 73fb5843ba..e30cc8ef86 100644 --- a/Content.Client/IconSmoothing/IconSmoothSystem.cs +++ b/Content.Client/IconSmoothing/IconSmoothSystem.cs @@ -24,7 +24,7 @@ namespace Content.Client.IconSmoothing { base.Initialize(); - SubscribeLocalEvent(HandleAnchorChanged); + SubscribeLocalEvent(OnAnchorChanged); } public override void FrameUpdate(float frameTime) @@ -87,7 +87,7 @@ namespace Content.Client.IconSmoothing } } - private void HandleAnchorChanged(EntityUid uid, IconSmoothComponent component, ref AnchorStateChangedEvent args) + private void OnAnchorChanged(EntityUid uid, IconSmoothComponent component, ref AnchorStateChangedEvent args) { UpdateSmoothing(uid, component); } diff --git a/Content.IntegrationTests/Tests/EntityTest.cs b/Content.IntegrationTests/Tests/EntityTest.cs index e24e4be9fe..a33be0fd8d 100644 --- a/Content.IntegrationTests/Tests/EntityTest.cs +++ b/Content.IntegrationTests/Tests/EntityTest.cs @@ -9,6 +9,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Map; +using Robust.Shared.Maths; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -249,10 +250,8 @@ namespace Content.IntegrationTests.Tests var tileDefinition = tileDefinitionManager["underplating"]; var tile = new Tile(tileDefinition.TileId); - var coordinates = grid.ToCoordinates(); - - grid.SetTile(coordinates, tile); + grid.SetTile(Vector2i.Zero, tile); mapManager.DoMapInitialize(mapId); }); diff --git a/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs b/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs index 3d8692bf9c..8b4cc02605 100644 --- a/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs +++ b/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs @@ -18,8 +18,6 @@ namespace Content.IntegrationTests.Tests.Fluids; [TestOf(typeof(FluidSpreaderSystem))] public sealed class FluidSpill : ContentIntegrationTest { - private const string SpillMapsYml = "Maps/Test/floor3x3.yml"; - private static PuddleComponent? GetPuddle(IEntityManager entityManager, IMapGrid mapGrid, Vector2i pos) { foreach (var uid in mapGrid.GetAnchoredEntities(pos)) @@ -44,7 +42,7 @@ public sealed class FluidSpill : ContentIntegrationTest }; - private readonly Vector2i _origin = new(-1, -1); + private readonly Vector2i _origin = new(1, 1); [Test] public async Task SpillEvenlyTest() @@ -54,28 +52,30 @@ public sealed class FluidSpill : ContentIntegrationTest await server.WaitIdleAsync(); var mapManager = server.ResolveDependency(); - var mapLoader = server.ResolveDependency(); var entityManager = server.ResolveDependency(); var spillSystem = server.ResolveDependency().GetEntitySystem(); var gameTiming = server.ResolveDependency(); MapId mapId; - GridId? gridid = null; + GridId gridId = default; await server.WaitPost(() => { mapId = mapManager.CreateMap(); - gridid = mapLoader.LoadBlueprint(mapId, SpillMapsYml).gridId; - }); + var grid = mapManager.CreateGrid(mapId); + gridId = grid.Index; - if (gridid == null) - { - Assert.Fail($"Test blueprint {SpillMapsYml} not found."); - return; - } + for (var x = 0; x < 3; x++) + { + for (var y = 0; y < 3; y++) + { + grid.SetTile(new Vector2i(x, y), new Tile(1)); + } + } + }); await server.WaitAssertion(() => { - var grid = mapManager.GetGrid(gridid.Value); + var grid = mapManager.GetGrid(gridId); var solution = new Solution("Water", FixedPoint2.New(100)); var tileRef = grid.GetTileRef(_origin); var puddle = spillSystem.SpillAt(tileRef, solution, "PuddleSmear"); @@ -88,7 +88,7 @@ public sealed class FluidSpill : ContentIntegrationTest server.Assert(() => { - var grid = mapManager.GetGrid(gridid.Value); + var grid = mapManager.GetGrid(gridId); var puddle = GetPuddle(entityManager, grid, _origin); Assert.That(puddle, Is.Not.Null); @@ -115,47 +115,44 @@ public sealed class FluidSpill : ContentIntegrationTest await server.WaitIdleAsync(); var mapManager = server.ResolveDependency(); - var mapLoader = server.ResolveDependency(); var entityManager = server.ResolveDependency(); var spillSystem = server.ResolveDependency().GetEntitySystem(); var gameTiming = server.ResolveDependency(); MapId mapId; - GridId? gridId = null; + GridId gridId = default; await server.WaitPost(() => { mapId = mapManager.CreateMap(); - gridId = mapLoader.LoadBlueprint(mapId, SpillMapsYml).gridId; - }); + var grid = mapManager.CreateGrid(mapId); - if (gridId == null) - { - Assert.Fail($"Test blueprint {SpillMapsYml} not found."); - return; - } + for (var x = 0; x < 3; x++) + { + for (var y = 0; y < 3; y++) + { + grid.SetTile(new Vector2i(x, y), new Tile(1)); + } + } + + gridId = grid.Index; + }); await server.WaitAssertion(() => { var solution = new Solution("Water", FixedPoint2.New(20.01)); - var grid = mapManager.GetGrid(gridId.Value); + var grid = mapManager.GetGrid(gridId); var tileRef = grid.GetTileRef(_origin); var puddle = spillSystem.SpillAt(tileRef, solution, "PuddleSmear"); Assert.That(puddle, Is.Not.Null); }); - if (gridId == null) - { - Assert.Fail($"Test blueprint {SpillMapsYml} not found."); - return; - } - var sTimeToWait = (int) Math.Ceiling(2f * gameTiming.TickRate); await server.WaitRunTicks(sTimeToWait); server.Assert(() => { - var grid = mapManager.GetGrid(gridId.Value); + var grid = mapManager.GetGrid(gridId); var puddle = GetPuddle(entityManager, grid, _origin); Assert.That(puddle, Is.Not.Null); Assert.That(puddle!.CurrentVolume, Is.EqualTo(FixedPoint2.New(20))); diff --git a/Content.Server/Atmos/EntitySystems/AirtightSystem.cs b/Content.Server/Atmos/EntitySystems/AirtightSystem.cs index 8757a6234c..97e8bee234 100644 --- a/Content.Server/Atmos/EntitySystems/AirtightSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AirtightSystem.cs @@ -22,6 +22,7 @@ namespace Content.Server.Atmos.EntitySystems SubscribeLocalEvent(OnAirtightInit); SubscribeLocalEvent(OnAirtightShutdown); SubscribeLocalEvent(OnAirtightPositionChanged); + SubscribeLocalEvent(OnAirtightReAnchor); SubscribeLocalEvent(OnAirtightRotated); } @@ -57,7 +58,7 @@ namespace Content.Server.Atmos.EntitySystems private void OnAirtightPositionChanged(EntityUid uid, AirtightComponent airtight, ref AnchorStateChangedEvent args) { - var xform = EntityManager.GetComponent(uid); + var xform = Transform(uid); var gridId = xform.GridID; var coords = xform.Coordinates; @@ -70,6 +71,16 @@ namespace Content.Server.Atmos.EntitySystems InvalidatePosition(gridId, tilePos); } + private void OnAirtightReAnchor(EntityUid uid, AirtightComponent airtight, ref ReAnchorEvent args) + { + foreach (var gridId in new[] { args.OldGrid, args.GridId }) + { + // Update and invalidate new position. + airtight.LastPosition = (gridId, args.TilePos); + InvalidatePosition(gridId, args.TilePos); + } + } + private void OnAirtightRotated(EntityUid uid, AirtightComponent airtight, ref RotateEvent ev) { if (!airtight.RotateAirBlocked || airtight.InitialAirBlockedDirection == (int)AtmosDirection.Invalid) diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Grid.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Grid.cs index eb26d6375f..cb3ceed6ea 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Grid.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Grid.cs @@ -28,6 +28,7 @@ namespace Content.Server.Atmos.EntitySystems private void InitializeGrid() { SubscribeLocalEvent(OnGridAtmosphereInit); + SubscribeLocalEvent(OnGridSplit); } private void OnGridAtmosphereInit(EntityUid uid, GridAtmosphereComponent gridAtmosphere, ComponentInit args) @@ -60,6 +61,56 @@ namespace Content.Server.Atmos.EntitySystems GridRepopulateTiles(mapGrid.Grid, gridAtmosphere); } + private void OnGridSplit(EntityUid uid, GridAtmosphereComponent originalGridAtmos, ref GridSplitEvent args) + { + foreach (var newGrid in args.NewGrids) + { + // Make extra sure this is a valid grid. + if (!_mapManager.TryGetGrid(newGrid, out var mapGrid)) + continue; + + var entity = mapGrid.GridEntityId; + + // If the new split grid has an atmosphere already somehow, use that. Otherwise, add a new one. + if (!TryComp(entity, out GridAtmosphereComponent? newGridAtmos)) + newGridAtmos = AddComp(entity); + + // We assume the tiles on the new grid have the same coordinates as they did on the old grid... + var enumerator = mapGrid.GetAllTilesEnumerator(); + + while (enumerator.MoveNext(out var tile)) + { + var indices = tile.Value.GridIndices; + + // This split event happens *before* the spaced tiles have been invalidated, therefore we can still + // access their gas data. On the next atmos update tick, these tiles will be spaced. Poof! + if (!originalGridAtmos.Tiles.TryGetValue(indices, out var tileAtmosphere)) + continue; + + // The new grid atmosphere has been initialized, meaning it has all the needed TileAtmospheres... + if (!newGridAtmos.Tiles.TryGetValue(indices, out var newTileAtmosphere)) + // Let's be honest, this is really not gonna happen, but just in case...! + continue; + + // Copy a bunch of data over... Not great, maybe put this in TileAtmosphere? + newTileAtmosphere.Air = tileAtmosphere.Air?.Clone() ?? null; + newTileAtmosphere.Hotspot = tileAtmosphere.Hotspot; + newTileAtmosphere.HeatCapacity = tileAtmosphere.HeatCapacity; + newTileAtmosphere.Temperature = tileAtmosphere.Temperature; + newTileAtmosphere.PressureDifference = tileAtmosphere.PressureDifference; + newTileAtmosphere.PressureDirection = tileAtmosphere.PressureDirection; + + // TODO ATMOS: Somehow force GasTileOverlaySystem to perform an update *right now, right here.* + // The reason why is that right now, gas will flicker until the next GasTileOverlay update. + // That looks bad, of course. We want to avoid that! Anyway that's a bit more complicated so out of scope. + + // Invalidate the tile, it's redundant but redundancy is good! Also HashSet so really, no duplicates. + InvalidateTile(originalGridAtmos, indices); + InvalidateTile(newGridAtmos, indices); + } + } + } + #region Grid Is Simulated /// @@ -217,10 +268,11 @@ namespace Content.Server.Atmos.EntitySystems private AtmosDirection GetBlockedDirections(IMapGrid mapGrid, Vector2i indices) { var value = AtmosDirection.Invalid; + var enumerator = GetObstructingComponentsEnumerator(mapGrid, indices); - foreach (var airtightComponent in GetObstructingComponents(mapGrid, indices)) + while (enumerator.MoveNext(out var airtightComponent)) { - if(airtightComponent.AirBlocked) + if (airtightComponent.AirBlocked) value |= airtightComponent.AirBlockedDirection; } diff --git a/Content.Server/Atmos/EntitySystems/AutomaticAtmosSystem.cs b/Content.Server/Atmos/EntitySystems/AutomaticAtmosSystem.cs index 17a84a0f2a..b89599a156 100644 --- a/Content.Server/Atmos/EntitySystems/AutomaticAtmosSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AutomaticAtmosSystem.cs @@ -11,7 +11,6 @@ namespace Content.Server.Atmos.EntitySystems; /// public sealed class AutomaticAtmosSystem : EntitySystem { - [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; public override void Initialize() @@ -20,7 +19,6 @@ public sealed class AutomaticAtmosSystem : EntitySystem SubscribeLocalEvent(OnTileChanged); } - private void OnTileChanged(TileChangedEvent ev) { // Only if a atmos-holding tile has been added or removed. @@ -28,18 +26,18 @@ public sealed class AutomaticAtmosSystem : EntitySystem // TODO: Make tiledefmanager cache the IsSpace property, and turn this lookup-through-two-interfaces into // TODO: a simple array lookup, as tile IDs are likely contiguous, and there's at most 2^16 possibilities anyway. if (!((ev.OldTile.IsSpace(_tileDefinitionManager) && !ev.NewTile.IsSpace(_tileDefinitionManager)) || - (!ev.OldTile.IsSpace(_tileDefinitionManager) && ev.NewTile.IsSpace(_tileDefinitionManager)))) + (!ev.OldTile.IsSpace(_tileDefinitionManager) && ev.NewTile.IsSpace(_tileDefinitionManager))) || + HasComp(ev.Entity)) return; - var uid = _mapManager.GetGridEuid(ev.NewTile.GridIndex); - if (!TryComp(uid, out var physics)) + if (!TryComp(ev.Entity, out var physics)) return; // We can't actually count how many tiles there are efficiently, so instead estimate with the mass. - if (physics.Mass / ShuttleSystem.TileMassMultiplier >= 7.0f && !HasComp(uid)) + if (physics.Mass / ShuttleSystem.TileMassMultiplier >= 7.0f) { - AddComp(uid); - Logger.InfoS("atmos", $"Giving grid {uid} GridAtmosphereComponent."); + AddComp(ev.Entity); + Logger.InfoS("atmos", $"Giving grid {ev.Entity} GridAtmosphereComponent."); } // It's not super important to remove it should the grid become too small again. // If explosions ever gain the ability to outright shatter grids, do rethink this. diff --git a/Content.Server/Atmos/GasMixture.cs b/Content.Server/Atmos/GasMixture.cs index 50ec54b27a..9b976ebcca 100644 --- a/Content.Server/Atmos/GasMixture.cs +++ b/Content.Server/Atmos/GasMixture.cs @@ -18,7 +18,7 @@ namespace Content.Server.Atmos /// [Serializable] [DataDefinition] - public sealed class GasMixture : IEquatable, ICloneable, ISerializationHooks + public sealed class GasMixture : IEquatable, ISerializationHooks { public static GasMixture SpaceGas => new() {Volume = Atmospherics.CellVolume, Temperature = Atmospherics.TCMB, Immutable = true}; @@ -296,7 +296,7 @@ namespace Content.Server.Atmos return hashCode.ToHashCode(); } - public object Clone() + public GasMixture Clone() { var newMixture = new GasMixture() { diff --git a/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs b/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs index 0ee6caafc2..be6d404cb2 100644 --- a/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs +++ b/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs @@ -26,6 +26,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems SubscribeLocalEvent(OnDeviceInitialize); SubscribeLocalEvent(OnDeviceShutdown); + // Re-anchoring should be handled by the parent change. SubscribeLocalEvent(OnDeviceParentChanged); SubscribeLocalEvent(OnDeviceAnchorChanged); } @@ -104,7 +105,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems if (!component.RequireAnchored) return; - if(EntityManager.GetComponent(component.Owner).Anchored) + if (args.Anchored) JoinAtmosphere(component); else LeaveAtmosphere(component); diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs index 3bdd6081e9..4bc275343a 100644 --- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs +++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs @@ -36,6 +36,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems SubscribeLocalEvent(OnChangeNodePercentageMessage); SubscribeLocalEvent(OnToggleStatusMessage); + // Shouldn't need re-anchor event SubscribeLocalEvent(OnAnchorChanged); } diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs index f238a51dde..b5bddcda15 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs @@ -22,6 +22,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems base.Initialize(); SubscribeLocalEvent(OnPortableAnchorAttempt); + // Shouldn't need re-anchored event. SubscribeLocalEvent(OnAnchorChanged); } diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 34b5f2f0c3..461b8e2fb2 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -11,6 +11,7 @@ namespace Content.Server.Atmos /// Internal Atmos class that stores data about the atmosphere in a grid. /// You shouldn't use this directly, use instead. /// + [Friend(typeof(AtmosphereSystem))] public sealed class TileAtmosphere : IGasMixtureHolder { [ViewVariables] diff --git a/Content.Server/BarSign/Systems/BarSignSystem.cs b/Content.Server/BarSign/Systems/BarSignSystem.cs index 1c3627e255..f8d8cf420c 100644 --- a/Content.Server/BarSign/Systems/BarSignSystem.cs +++ b/Content.Server/BarSign/Systems/BarSignSystem.cs @@ -24,7 +24,8 @@ namespace Content.Server.BarSign.Systems private void UpdateBarSignVisuals(EntityUid owner, BarSignComponent component, PowerChangedEvent args) { - if (component.LifeStage is < ComponentLifeStage.Initialized or > ComponentLifeStage.Running) return; + var lifestage = MetaData(owner).EntityLifeStage; + if (lifestage is < EntityLifeStage.Initialized or >= EntityLifeStage.Terminating) return; if (!TryComp(owner, out SpriteComponent? sprite)) { diff --git a/Content.Server/Cargo/CargoSystem.Telepad.cs b/Content.Server/Cargo/CargoSystem.Telepad.cs index 5ddee3f718..40adc59b92 100644 --- a/Content.Server/Cargo/CargoSystem.Telepad.cs +++ b/Content.Server/Cargo/CargoSystem.Telepad.cs @@ -13,9 +13,11 @@ namespace Content.Server.Cargo; public sealed partial class CargoSystem { [Dependency] private readonly PaperSystem _paperSystem = default!; + private void InitializeTelepad() { SubscribeLocalEvent(OnTelepadPowerChange); + // Shouldn't need re-anchored event SubscribeLocalEvent(OnTelepadAnchorChange); } diff --git a/Content.Server/Decals/DecalSystem.cs b/Content.Server/Decals/DecalSystem.cs index 40e0c9e356..087f16ce69 100644 --- a/Content.Server/Decals/DecalSystem.cs +++ b/Content.Server/Decals/DecalSystem.cs @@ -15,6 +15,7 @@ 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 SharedTransformSystem _transform = default!; private readonly Dictionary> _dirtyChunks = new(); @@ -37,7 +38,7 @@ namespace Content.Server.Decals base.Initialize(); _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; - MapManager.TileChanged += OnTileChanged; + SubscribeLocalEvent(OnTileChanged); SubscribeNetworkEvent(OnDecalPlacementRequest); SubscribeNetworkEvent(OnDecalRemovalRequest); @@ -48,23 +49,22 @@ namespace Content.Server.Decals base.Shutdown(); _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged; - MapManager.TileChanged -= OnTileChanged; } - private void OnTileChanged(object? sender, TileChangedEventArgs e) + private void OnTileChanged(TileChangedEvent args) { - if (!e.NewTile.IsSpace()) + if (!args.NewTile.IsSpace(_tileDefMan)) return; - var chunkCollection = ChunkCollection(e.NewTile.GridIndex); - var indices = GetChunkIndices(e.NewTile.GridIndices); + var chunkCollection = ChunkCollection(args.Entity); + var indices = GetChunkIndices(args.NewTile.GridIndices); var toDelete = new HashSet(); if (chunkCollection.TryGetValue(indices, out var chunk)) { foreach (var (uid, decal) in chunk) { if (new Vector2((int) Math.Floor(decal.Coordinates.X), (int) Math.Floor(decal.Coordinates.Y)) == - e.NewTile.GridIndices) + args.NewTile.GridIndices) { toDelete.Add(uid); } @@ -75,10 +75,10 @@ namespace Content.Server.Decals foreach (var uid in toDelete) { - RemoveDecalInternal(e.NewTile.GridIndex, uid); + RemoveDecalInternal(args.NewTile.GridIndex, uid); } - DirtyChunk(e.NewTile.GridIndex, indices); + DirtyChunk(args.NewTile.GridIndex, indices); } private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index a3194e0f20..4adcadfd3b 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -46,6 +46,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems { base.Initialize(); + // Shouldn't need re-anchoring. SubscribeLocalEvent(OnAnchorChanged); // TODO: Predict me when hands predicted SubscribeLocalEvent(HandleMovement); @@ -244,7 +245,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems { return; } - + if (!CanInsert(component, args.Used) || !_handsSystem.TryDropIntoContainer(args.User, args.Used, component.Container)) { return; diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.GridMap.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.GridMap.cs index bc6495f8be..26c8d2cae2 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.GridMap.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.GridMap.cs @@ -160,7 +160,7 @@ public sealed partial class ExplosionSystem : EntitySystem // if this ever changes, this needs to do a try-get. var data = new BlockedSpaceTile(); transformedEdges[tile] = data; - + data.UnblockedDirections = AtmosDirection.Invalid; // all directions are blocked automatically. if ((dir & NeighborFlag.Cardinal) == 0) @@ -225,11 +225,11 @@ public sealed partial class ExplosionSystem : EntitySystem if (!ev.NewTile.Tile.IsEmpty && !ev.OldTile.IsEmpty) return; - var tileRef = ev.NewTile; - - if (!_mapManager.TryGetGrid(tileRef.GridIndex, out var grid)) + if (!_mapManager.TryGetGrid(ev.Entity, out var grid)) return; + var tileRef = ev.NewTile; + if (!_gridEdges.TryGetValue(tileRef.GridIndex, out var edges)) { edges = new(); diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs index f25c237a3a..95181875ad 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs @@ -21,6 +21,7 @@ public sealed partial class TriggerSystem SubscribeLocalEvent(OnProximityEndCollide); SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnProximityShutdown); + // Shouldn't need re-anchoring. SubscribeLocalEvent(OnProximityAnchor); } diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index f18fcf1904..4ea7192008 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -21,6 +21,7 @@ namespace Content.Server.Fluids.EntitySystems { base.Initialize(); + // Shouldn't need re-anchoring. SubscribeLocalEvent(OnAnchorChanged); SubscribeLocalEvent(HandlePuddleExamined); SubscribeLocalEvent(OnUpdate); diff --git a/Content.Server/Fluids/EntitySystems/SpillableSystem.cs b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs index 07ecda9c47..fd8a7dd19c 100644 --- a/Content.Server/Fluids/EntitySystems/SpillableSystem.cs +++ b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs @@ -184,7 +184,7 @@ public sealed class SpillableSystem : EntitySystem // Get normalized co-ordinate for spill location and spill it in the centre // TODO: Does SnapGrid or something else already do this? - var spillGridCoords = mapGrid.GridTileToWorld(tileRef.GridIndices); + var spillGridCoords = mapGrid.GridTileToLocal(tileRef.GridIndices); var startEntity = EntityUid.Invalid; PuddleComponent? puddleComponent = null; diff --git a/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs b/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs index c0a987ded9..cdc1478f4c 100644 --- a/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs +++ b/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs @@ -22,6 +22,7 @@ namespace Content.Server.NodeContainer.EntitySystems SubscribeLocalEvent(OnStartupEvent); SubscribeLocalEvent(OnShutdownEvent); SubscribeLocalEvent(OnAnchorStateChanged); + SubscribeLocalEvent(OnReAnchor); SubscribeLocalEvent(OnRotateEvent); SubscribeLocalEvent(OnExamine); } @@ -71,6 +72,15 @@ namespace Content.Server.NodeContainer.EntitySystems } } + private void OnReAnchor(EntityUid uid, NodeContainerComponent component, ref ReAnchorEvent args) + { + foreach (var node in component.Nodes.Values) + { + _nodeGroupSystem.QueueNodeRemove(node); + _nodeGroupSystem.QueueReflood(node); + } + } + private void OnRotateEvent(EntityUid uid, NodeContainerComponent container, ref RotateEvent ev) { if (ev.NewRotation == ev.OldRotation) diff --git a/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs b/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs index abf1088da0..30a67a83dc 100644 --- a/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs +++ b/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs @@ -157,8 +157,8 @@ namespace Content.Server.NodeContainer.EntitySystems var sw = Stopwatch.StartNew(); - var xformQuery = EntityManager.GetEntityQuery(); - var nodeQuery = EntityManager.GetEntityQuery(); + var xformQuery = GetEntityQuery(); + var nodeQuery = GetEntityQuery(); foreach (var toRemove in _toRemove) { diff --git a/Content.Server/NodeContainer/NodeGroups/NodeGroupFactory.cs b/Content.Server/NodeContainer/NodeGroups/NodeGroupFactory.cs index dbd5917260..4b5f9dca86 100644 --- a/Content.Server/NodeContainer/NodeGroups/NodeGroupFactory.cs +++ b/Content.Server/NodeContainer/NodeGroups/NodeGroupFactory.cs @@ -55,7 +55,7 @@ namespace Content.Server.NodeContainer.NodeGroups } } - public enum NodeGroupID + public enum NodeGroupID : byte { Default, HVPower, diff --git a/Content.Server/Nuke/NukeSystem.cs b/Content.Server/Nuke/NukeSystem.cs index f50f845c9c..f2dc977bc6 100644 --- a/Content.Server/Nuke/NukeSystem.cs +++ b/Content.Server/Nuke/NukeSystem.cs @@ -34,6 +34,7 @@ namespace Content.Server.Nuke // anchoring logic SubscribeLocalEvent(OnAnchorAttempt); SubscribeLocalEvent(OnUnanchorAttempt); + // Shouldn't need re-anchoring. SubscribeLocalEvent(OnAnchorChanged); // ui events diff --git a/Content.Server/Power/EntitySystems/CableSystem.cs b/Content.Server/Power/EntitySystems/CableSystem.cs index 2540ee344f..a06b4c1793 100644 --- a/Content.Server/Power/EntitySystems/CableSystem.cs +++ b/Content.Server/Power/EntitySystems/CableSystem.cs @@ -26,6 +26,7 @@ public sealed partial class CableSystem : EntitySystem SubscribeLocalEvent(OnInteractUsing); SubscribeLocalEvent(OnCableCut); + // Shouldn't need re-anchoring. SubscribeLocalEvent(OnAnchorChanged); } diff --git a/Content.Server/Power/EntitySystems/ExtensionCableSystem.cs b/Content.Server/Power/EntitySystems/ExtensionCableSystem.cs index 4ba2075e62..2aafb23b23 100644 --- a/Content.Server/Power/EntitySystems/ExtensionCableSystem.cs +++ b/Content.Server/Power/EntitySystems/ExtensionCableSystem.cs @@ -25,7 +25,10 @@ namespace Content.Server.Power.EntitySystems //Anchoring SubscribeLocalEvent(OnReceiverAnchorStateChanged); + SubscribeLocalEvent(OnReceiverReAnchor); + SubscribeLocalEvent(OnProviderAnchorStateChanged); + SubscribeLocalEvent(OnProviderReAnchor); } #region Provider @@ -41,14 +44,7 @@ namespace Content.Server.Power.EntitySystems private void OnProviderStarted(EntityUid uid, ExtensionCableProviderComponent provider, ComponentStartup args) { - foreach (var receiver in FindAvailableReceivers(uid, provider.TransferRange)) - { - receiver.Provider?.LinkedReceivers.Remove(receiver); - receiver.Provider = provider; - provider.LinkedReceivers.Add(receiver); - RaiseLocalEvent(receiver.Owner, new ProviderConnectedEvent(provider), broadcast: false); - RaiseLocalEvent(uid, new ReceiverConnectedEvent(receiver), broadcast: false); - } + Connect(uid, provider); } private void OnProviderShutdown(EntityUid uid, ExtensionCableProviderComponent provider, ComponentShutdown args) @@ -61,34 +57,44 @@ namespace Content.Server.Power.EntitySystems if (MetaData(grid.GridEntityId).EntityLifeStage > EntityLifeStage.MapInitialized) return; } - provider.Connectable = false; - ResetReceivers(provider); + Disconnect(uid, provider); } private void OnProviderAnchorStateChanged(EntityUid uid, ExtensionCableProviderComponent provider, ref AnchorStateChangedEvent args) { if (args.Anchored) - { - provider.Connectable = true; - - // same as OnProviderStarted - foreach (var receiver in FindAvailableReceivers(uid, provider.TransferRange)) - { - receiver.Provider?.LinkedReceivers.Remove(receiver); - receiver.Provider = provider; - provider.LinkedReceivers.Add(receiver); - RaiseLocalEvent(receiver.Owner, new ProviderConnectedEvent(provider), broadcast: false); - RaiseLocalEvent(uid, new ReceiverConnectedEvent(receiver), broadcast: false); - } - } + Connect(uid, provider); else + Disconnect(uid, provider); + } + + private void Connect(EntityUid uid, ExtensionCableProviderComponent provider) + { + provider.Connectable = true; + + foreach (var receiver in FindAvailableReceivers(uid, provider.TransferRange)) { - // same as OnProviderShutdown - provider.Connectable = false; - ResetReceivers(provider); + receiver.Provider?.LinkedReceivers.Remove(receiver); + receiver.Provider = provider; + provider.LinkedReceivers.Add(receiver); + RaiseLocalEvent(receiver.Owner, new ProviderConnectedEvent(provider), broadcast: false); + RaiseLocalEvent(uid, new ReceiverConnectedEvent(receiver), broadcast: false); } } + private void Disconnect(EntityUid uid, ExtensionCableProviderComponent provider) + { + // same as OnProviderShutdown + provider.Connectable = false; + ResetReceivers(provider); + } + + private void OnProviderReAnchor(EntityUid uid, ExtensionCableProviderComponent component, ref ReAnchorEvent args) + { + Disconnect(uid, component); + Connect(uid, component); + } + private void ResetReceivers(ExtensionCableProviderComponent provider) { var receivers = provider.LinkedReceivers.ToArray(); @@ -179,37 +185,49 @@ namespace Content.Server.Power.EntitySystems private void OnReceiverShutdown(EntityUid uid, ExtensionCableReceiverComponent receiver, ComponentShutdown args) { - if (receiver.Provider == null) return; - - receiver.Provider.LinkedReceivers.Remove(receiver); - RaiseLocalEvent(uid, new ProviderDisconnectedEvent(receiver.Provider), broadcast: false); - RaiseLocalEvent(receiver.Provider.Owner, new ReceiverDisconnectedEvent(receiver), broadcast: false); + Disconnect(uid, receiver); } private void OnReceiverAnchorStateChanged(EntityUid uid, ExtensionCableReceiverComponent receiver, ref AnchorStateChangedEvent args) { if (args.Anchored) { - receiver.Connectable = true; - if (receiver.Provider == null) - { - TryFindAndSetProvider(receiver); - } + Connect(uid, receiver); } else { - receiver.Connectable = false; - RaiseLocalEvent(uid, new ProviderDisconnectedEvent(receiver.Provider), broadcast: false); - if (receiver.Provider != null) - { - RaiseLocalEvent(receiver.Provider.Owner, new ReceiverDisconnectedEvent(receiver), broadcast: false); - receiver.Provider.LinkedReceivers.Remove(receiver); - } - - receiver.Provider = null; + Disconnect(uid, receiver); } } + private void OnReceiverReAnchor(EntityUid uid, ExtensionCableReceiverComponent receiver, ref ReAnchorEvent args) + { + Disconnect(uid, receiver); + Connect(uid, receiver); + } + + private void Connect(EntityUid uid, ExtensionCableReceiverComponent receiver) + { + receiver.Connectable = true; + if (receiver.Provider == null) + { + TryFindAndSetProvider(receiver); + } + } + + private void Disconnect(EntityUid uid, ExtensionCableReceiverComponent receiver) + { + receiver.Connectable = false; + RaiseLocalEvent(uid, new ProviderDisconnectedEvent(receiver.Provider), broadcast: false); + if (receiver.Provider != null) + { + RaiseLocalEvent(receiver.Provider.Owner, new ReceiverDisconnectedEvent(receiver), broadcast: false); + receiver.Provider.LinkedReceivers.Remove(receiver); + } + + receiver.Provider = null; + } + private void TryFindAndSetProvider(ExtensionCableReceiverComponent receiver, TransformComponent? xform = null) { if (!receiver.Connectable) return; diff --git a/Content.Server/Power/NodeGroups/BaseNetConnectorNodeGroup.cs b/Content.Server/Power/NodeGroups/BaseNetConnectorNodeGroup.cs index 46c7540ec3..e324e3d7fb 100644 --- a/Content.Server/Power/NodeGroups/BaseNetConnectorNodeGroup.cs +++ b/Content.Server/Power/NodeGroups/BaseNetConnectorNodeGroup.cs @@ -13,13 +13,21 @@ namespace Content.Server.Power.NodeGroups public override void LoadNodes(List groupNodes) { base.LoadNodes(groupNodes); + var entManager = IoCManager.Resolve(); foreach (var node in groupNodes) { - var newNetConnectorComponents = IoCManager.Resolve().GetComponents>(node.Owner) - .Where(powerComp => (powerComp.NodeId == null || powerComp.NodeId == node.Name) && - (NodeGroupID) powerComp.Voltage == node.NodeGroupID) - .ToList(); + var newNetConnectorComponents = new List>(); + + foreach (var comp in entManager.GetComponents>(node.Owner)) + { + if ((comp.NodeId == null || + comp.NodeId == node.Name) && + (NodeGroupID) comp.Voltage == node.NodeGroupID) + { + newNetConnectorComponents.Add(comp); + } + } foreach (var netConnector in newNetConnectorComponents) { diff --git a/Content.Server/Shuttles/EntitySystems/DockingSystem.cs b/Content.Server/Shuttles/EntitySystems/DockingSystem.cs index 4df50626a4..d13e5e0051 100644 --- a/Content.Server/Shuttles/EntitySystems/DockingSystem.cs +++ b/Content.Server/Shuttles/EntitySystems/DockingSystem.cs @@ -38,6 +38,7 @@ namespace Content.Server.Shuttles.EntitySystems SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnPowerChange); SubscribeLocalEvent(OnAnchorChange); + SubscribeLocalEvent(OnDockingReAnchor); SubscribeLocalEvent>(OnVerb); SubscribeLocalEvent(OnAutoClose); @@ -256,6 +257,16 @@ namespace Content.Server.Shuttles.EntitySystems } } + private void OnDockingReAnchor(EntityUid uid, DockingComponent component, ref ReAnchorEvent args) + { + if (!component.Docked) return; + + var other = Comp(component.DockedWith!.Value); + + Undock(component); + Dock(component, other); + } + private void OnPowerChange(EntityUid uid, DockingComponent component, PowerChangedEvent args) { // This is because power can change during startup for and undock diff --git a/Content.Server/Shuttles/EntitySystems/ShuttleSystem.cs b/Content.Server/Shuttles/EntitySystems/ShuttleSystem.cs index ca16f8a1ba..bf525fab8e 100644 --- a/Content.Server/Shuttles/EntitySystems/ShuttleSystem.cs +++ b/Content.Server/Shuttles/EntitySystems/ShuttleSystem.cs @@ -1,18 +1,17 @@ -using System.Collections.Generic; using Content.Server.Shuttles.Components; using Content.Shared.CCVar; using JetBrains.Annotations; using Robust.Shared.Configuration; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; using Robust.Shared.Physics; namespace Content.Server.Shuttles.EntitySystems { [UsedImplicitly] - internal sealed class ShuttleSystem : EntitySystem + public sealed class ShuttleSystem : EntitySystem { - public const float TileMassMultiplier = 4f; + [Dependency] private readonly FixtureSystem _fixtures = default!; + + public const float TileMassMultiplier = 0.5f; public float ShuttleMaxLinearSpeed; @@ -74,11 +73,15 @@ namespace Content.Server.Shuttles.EntitySystems // Look this is jank but it's a placeholder until we design it. if (args.NewFixtures.Count == 0) return; + var manager = Comp(args.NewFixtures[0].Body.Owner); + foreach (var fixture in args.NewFixtures) { - fixture.Mass = fixture.Area * TileMassMultiplier; - fixture.Restitution = 0.1f; + _fixtures.SetMass(fixture, fixture.Area * TileMassMultiplier, manager, false); + _fixtures.SetRestitution(fixture, 0.1f, manager, false); } + + _fixtures.FixtureUpdate(manager, args.NewFixtures[0].Body); } private void OnGridInit(GridInitializeEvent ev) diff --git a/Content.Server/Shuttles/EntitySystems/ThrusterSystem.cs b/Content.Server/Shuttles/EntitySystems/ThrusterSystem.cs index b6ed94a53a..55a984131a 100644 --- a/Content.Server/Shuttles/EntitySystems/ThrusterSystem.cs +++ b/Content.Server/Shuttles/EntitySystems/ThrusterSystem.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using Content.Server.Audio; -using Content.Server.Damage.Systems; using Content.Server.Power.Components; using Content.Server.Shuttles.Components; using Content.Shared.Damage; @@ -14,11 +11,7 @@ using Content.Shared.Physics; using Content.Shared.Temperature; using Content.Shared.Shuttles.Components; using Robust.Server.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.Localization; -using Robust.Shared.Log; using Robust.Shared.Map; -using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Physics.Dynamics; @@ -29,6 +22,7 @@ namespace Content.Server.Shuttles.EntitySystems public sealed class ThrusterSystem : EntitySystem { [Robust.Shared.IoC.Dependency] private readonly IMapManager _mapManager = default!; + [Robust.Shared.IoC.Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; [Robust.Shared.IoC.Dependency] private readonly AmbientSoundSystem _ambient = default!; [Robust.Shared.IoC.Dependency] private readonly FixtureSystem _fixtureSystem = default!; [Robust.Shared.IoC.Dependency] private readonly DamageableSystem _damageable = default!; @@ -52,6 +46,7 @@ namespace Content.Server.Shuttles.EntitySystems SubscribeLocalEvent(OnThrusterShutdown); SubscribeLocalEvent(OnPowerChange); SubscribeLocalEvent(OnAnchorChange); + SubscribeLocalEvent(OnThrusterReAnchor); SubscribeLocalEvent(OnRotate); SubscribeLocalEvent(OnIsHotEvent); SubscribeLocalEvent(OnStartCollide); @@ -104,9 +99,12 @@ namespace Content.Server.Shuttles.EntitySystems private void OnTileChange(object? sender, TileChangedEventArgs e) { // If the old tile was space but the new one isn't then disable all adjacent thrusters - if (e.NewTile.IsSpace() || !e.OldTile.IsSpace()) return; + if (e.NewTile.IsSpace(_tileDefManager) || !e.OldTile.IsSpace(_tileDefManager)) return; var tilePos = e.NewTile.GridIndices; + var grid = _mapManager.GetGrid(e.NewTile.GridIndex); + var xformQuery = GetEntityQuery(); + var thrusterQuery = GetEntityQuery(); for (var x = -1; x <= 1; x++) { @@ -115,17 +113,19 @@ namespace Content.Server.Shuttles.EntitySystems if (x != 0 && y != 0) continue; var checkPos = tilePos + new Vector2i(x, y); + var enumerator = grid.GetAnchoredEntitiesEnumerator(checkPos); - foreach (var ent in _mapManager.GetGrid(e.NewTile.GridIndex).GetAnchoredEntities(checkPos)) + while (enumerator.MoveNext(out var ent)) { - if (!EntityManager.TryGetComponent(ent, out ThrusterComponent? thruster) || !thruster.RequireSpace) continue; + if (!thrusterQuery.TryGetComponent(ent.Value, out var thruster) || !thruster.RequireSpace) continue; // Work out if the thruster is facing this direction - var direction = EntityManager.GetComponent(ent).LocalRotation.ToWorldVec(); + var xform = xformQuery.GetComponent(ent.Value); + var direction = xform.LocalRotation.ToWorldVec(); if (new Vector2i((int) direction.X, (int) direction.Y) != new Vector2i(x, y)) continue; - DisableThruster(ent, thruster); + DisableThruster(ent.Value, thruster, xform.GridID); } } } @@ -195,6 +195,14 @@ namespace Content.Server.Shuttles.EntitySystems } } + private void OnThrusterReAnchor(EntityUid uid, ThrusterComponent component, ref ReAnchorEvent args) + { + DisableThruster(uid, component, args.OldGrid); + + if (CanEnable(uid, component)) + EnableThruster(uid, component); + } + private void OnThrusterInit(EntityUid uid, ThrusterComponent component, ComponentInit args) { _ambient.SetAmbience(uid, false); @@ -292,14 +300,20 @@ namespace Content.Server.Shuttles.EntitySystems _ambient.SetAmbience(uid, true); } + public void DisableThruster(EntityUid uid, ThrusterComponent component, TransformComponent? xform = null, Angle? angle = null) + { + if (!Resolve(uid, ref xform)) return; + DisableThruster(uid, component, xform.GridID, xform); + } + /// /// Tries to disable the thruster. /// - public void DisableThruster(EntityUid uid, ThrusterComponent component, TransformComponent? xform = null, Angle? angle = null) + public void DisableThruster(EntityUid uid, ThrusterComponent component, GridId gridId, TransformComponent? xform = null, Angle? angle = null) { if (!component.IsOn || !Resolve(uid, ref xform) || - !_mapManager.TryGetGrid(xform.GridID, out var grid)) return; + !_mapManager.TryGetGrid(gridId, out var grid)) return; component.IsOn = false; @@ -351,7 +365,7 @@ namespace Content.Server.Shuttles.EntitySystems { if (!component.Enabled) return false; - var xform = EntityManager.GetComponent(uid); + var xform = Transform(uid); if (!xform.Anchored || EntityManager.TryGetComponent(uid, out ApcPowerReceiverComponent? receiver) && !receiver.Powered) diff --git a/Content.Shared/Decals/SharedDecalSystem.cs b/Content.Shared/Decals/SharedDecalSystem.cs index 4d8b805686..b693abf325 100644 --- a/Content.Shared/Decals/SharedDecalSystem.cs +++ b/Content.Shared/Decals/SharedDecalSystem.cs @@ -52,8 +52,11 @@ namespace Content.Shared.Decals } } - protected DecalGridComponent.DecalGridChunkCollection DecalGridChunkCollection(GridId gridId) => EntityManager - .GetComponent(MapManager.GetGrid(gridId).GridEntityId).ChunkCollection; + protected DecalGridComponent.DecalGridChunkCollection DecalGridChunkCollection(EntityUid gridEuid) => + Comp(gridEuid).ChunkCollection; + protected DecalGridComponent.DecalGridChunkCollection DecalGridChunkCollection(GridId gridId) => + Comp(MapManager.GetGridEuid(gridId)).ChunkCollection; + protected Dictionary> ChunkCollection(EntityUid gridEuid) => DecalGridChunkCollection(gridEuid).ChunkCollection; protected Dictionary> ChunkCollection(GridId gridId) => DecalGridChunkCollection(gridId).ChunkCollection; protected virtual void DirtyChunk(GridId id, Vector2i chunkIndices) {} diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index 56d3324b59..ace6462c4a 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -164,7 +164,7 @@ namespace Content.Shared.Maps if (!GetWorldTileBox(turf, out var worldBox)) return Enumerable.Empty(); - return lookupSystem.GetEntitiesIntersecting(turf.MapIndex, worldBox, flags); + return lookupSystem.GetEntitiesIntersecting(turf.GridIndex, worldBox, flags); } /// @@ -193,15 +193,18 @@ namespace Content.Shared.Maps /// public static bool IsBlockedTurf(this TileRef turf, bool filterMobs) { - var physics = EntitySystem.Get(); + // TODO: Deprecate this with entitylookup. + var physics = EntitySystem.Get(); if (!GetWorldTileBox(turf, out var worldBox)) return false; - var query = physics.GetCollidingEntities(turf.MapIndex, in worldBox); + var entManager = IoCManager.Resolve(); + var query = physics.GetEntitiesIntersecting(turf.GridIndex, worldBox); - foreach (var body in query) + foreach (var ent in query) { + var body = entManager.GetComponent(ent); if (body.CanCollide && body.Hard && (body.CollisionLayer & (int) CollisionGroup.Impassable) != 0) return true; diff --git a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs index b00c58bf4e..8533aec1c9 100644 --- a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs +++ b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs @@ -26,6 +26,7 @@ namespace Content.Shared.SubFloor SubscribeLocalEvent(OnTileChanged); SubscribeLocalEvent(OnSubFloorStarted); SubscribeLocalEvent(OnSubFloorTerminating); + // Like 80% sure this doesn't need to handle re-anchoring. SubscribeLocalEvent(HandleAnchorChanged); SubscribeLocalEvent(OnInteractionAttempt); } diff --git a/Content.Shared/SubFloor/TrayScannerSystem.cs b/Content.Shared/SubFloor/TrayScannerSystem.cs index 00b7e92a97..c54ca958f2 100644 --- a/Content.Shared/SubFloor/TrayScannerSystem.cs +++ b/Content.Shared/SubFloor/TrayScannerSystem.cs @@ -40,7 +40,7 @@ public sealed class TrayScannerSystem : EntitySystem return; scanner.Enabled = enabled; - scanner.Dirty(); + Dirty(scanner); if (scanner.Enabled) _activeScanners.Add(uid); diff --git a/Content.Shared/Throwing/ThrownItemSystem.cs b/Content.Shared/Throwing/ThrownItemSystem.cs index 12823c9fa6..316b64f8a5 100644 --- a/Content.Shared/Throwing/ThrownItemSystem.cs +++ b/Content.Shared/Throwing/ThrownItemSystem.cs @@ -28,7 +28,7 @@ namespace Content.Shared.Throwing public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(HandleSleep); + SubscribeLocalEvent(OnSleep); SubscribeLocalEvent(HandleCollision); SubscribeLocalEvent(PreventCollision); SubscribeLocalEvent(ThrowItem); @@ -87,7 +87,7 @@ namespace Content.Shared.Throwing } } - private void HandleSleep(EntityUid uid, ThrownItemComponent thrownItem, PhysicsSleepMessage message) + private void OnSleep(EntityUid uid, ThrownItemComponent thrownItem, ref PhysicsSleepEvent @event) { StopThrow(uid, thrownItem); } diff --git a/Resources/engineCommandPerms.yml b/Resources/engineCommandPerms.yml index a1067cf219..0b45ca027b 100644 --- a/Resources/engineCommandPerms.yml +++ b/Resources/engineCommandPerms.yml @@ -67,6 +67,7 @@ - showpos - showray - showchunkbb + - showgridnodes - entfo - sggcell - ldrsc