diff --git a/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs b/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs index 184c1cf313..9adf3092c0 100644 --- a/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs +++ b/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs @@ -225,7 +225,7 @@ public sealed class GatewayGeneratorSystem : EntitySystem var layer = lootLayers[layerIdx]; lootLayers.RemoveSwap(layerIdx); - _biome.AddMarkerLayer(biomeComp, layer.Id); + _biome.AddMarkerLayer(ent.Owner, biomeComp, layer.Id); } // - Mobs @@ -237,7 +237,7 @@ public sealed class GatewayGeneratorSystem : EntitySystem var layer = mobLayers[layerIdx]; mobLayers.RemoveSwap(layerIdx); - _biome.AddMarkerLayer(biomeComp, layer.Id); + _biome.AddMarkerLayer(ent.Owner, biomeComp, layer.Id); } } } diff --git a/Content.Server/Parallax/BiomeSystem.Commands.cs b/Content.Server/Parallax/BiomeSystem.Commands.cs index 0360c1deb7..607345a00d 100644 --- a/Content.Server/Parallax/BiomeSystem.Commands.cs +++ b/Content.Server/Parallax/BiomeSystem.Commands.cs @@ -29,14 +29,15 @@ public sealed partial class BiomeSystem int.TryParse(args[0], out var mapInt); var mapId = new MapId(mapInt); + var mapUid = _mapManager.GetMapEntityId(mapId); if (_mapManager.MapExists(mapId) || - !TryComp(_mapManager.GetMapEntityId(mapId), out var biome)) + !TryComp(mapUid, out var biome)) { return; } - ClearTemplate(biome); + ClearTemplate(mapUid, biome); } private CompletionResult BiomeClearCallbackHelper(IConsoleShell shell, string[] args) @@ -63,8 +64,9 @@ public sealed partial class BiomeSystem } var mapId = new MapId(mapInt); + var mapUid = _mapManager.GetMapEntityId(mapId); - if (!_mapManager.MapExists(mapId) || !TryComp(_mapManager.GetMapEntityId(mapId), out var biome)) + if (!_mapManager.MapExists(mapId) || !TryComp(mapUid, out var biome)) { return; } @@ -81,7 +83,7 @@ public sealed partial class BiomeSystem int.TryParse(args[3], out offset); } - AddTemplate(biome, args[2], template, offset); + AddTemplate(mapUid, biome, args[2], template, offset); } private CompletionResult AddLayerCallbackHelp(IConsoleShell shell, string[] args) diff --git a/Content.Server/Parallax/BiomeSystem.cs b/Content.Server/Parallax/BiomeSystem.cs index 8f6e0730b9..daf21d77dd 100644 --- a/Content.Server/Parallax/BiomeSystem.cs +++ b/Content.Server/Parallax/BiomeSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Decals; using Content.Server.Ghost.Roles.Components; using Content.Server.Shuttles.Events; +using Content.Server.Shuttles.Systems; using Content.Shared.Atmos; using Content.Shared.Decals; using Content.Shared.Gravity; @@ -21,6 +22,9 @@ using Robust.Shared.Console; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Noise; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Systems; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -41,8 +45,12 @@ public sealed partial class BiomeSystem : SharedBiomeSystem [Dependency] private readonly AtmosphereSystem _atmos = default!; [Dependency] private readonly DecalSystem _decals = default!; [Dependency] private readonly SharedMapSystem _mapSystem = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly ShuttleSystem _shuttles = default!; + private EntityQuery _biomeQuery; + private EntityQuery _fixturesQuery; private EntityQuery _xformQuery; private readonly HashSet _handledEntities = new(); @@ -69,6 +77,8 @@ public sealed partial class BiomeSystem : SharedBiomeSystem { base.Initialize(); Log.Level = LogLevel.Debug; + _biomeQuery = GetEntityQuery(); + _fixturesQuery = GetEntityQuery(); _xformQuery = GetEntityQuery(); SubscribeLocalEvent(OnBiomeMapInit); SubscribeLocalEvent(OnFTLStarted); @@ -92,12 +102,12 @@ public sealed partial class BiomeSystem : SharedBiomeSystem var query = AllEntityQuery(); - while (query.MoveNext(out var biome)) + while (query.MoveNext(out var uid, out var biome)) { if (biome.Template == null || !reloads.Modified.TryGetValue(biome.Template, out var proto)) continue; - SetTemplate(biome, (BiomeTemplatePrototype) proto); + SetTemplate(uid, biome, (BiomeTemplatePrototype) proto); } } @@ -110,29 +120,64 @@ public sealed partial class BiomeSystem : SharedBiomeSystem private void OnBiomeMapInit(EntityUid uid, BiomeComponent component, MapInitEvent args) { - if (component.Seed != -1) - return; + if (component.Seed == -1) + { + SetSeed(uid, component, _random.Next()); + } - SetSeed(component, _random.Next()); + var xform = Transform(uid); + var mapId = xform.MapID; + + if (mapId != MapId.Nullspace && TryComp(uid, out MapGridComponent? mapGrid)) + { + var setTiles = new List<(Vector2i Index, Tile tile)>(); + + foreach (var grid in _mapManager.GetAllMapGrids(mapId)) + { + var gridUid = grid.Owner; + + if (!_fixturesQuery.TryGetComponent(gridUid, out var fixtures)) + continue; + + // Don't want shuttles flying around now do we. + _shuttles.Disable(gridUid); + var pTransform = _physics.GetPhysicsTransform(gridUid); + + foreach (var fixture in fixtures.Fixtures.Values) + { + for (var i = 0; i < fixture.Shape.ChildCount; i++) + { + var aabb = fixture.Shape.ComputeAABB(pTransform, i); + + setTiles.Clear(); + ReserveTiles(uid, aabb, setTiles); + } + } + } + } } - public void SetSeed(BiomeComponent component, int seed) + public void SetSeed(EntityUid uid, BiomeComponent component, int seed, bool dirty = true) { component.Seed = seed; - Dirty(component); + + if (dirty) + Dirty(uid, component); } - public void ClearTemplate(BiomeComponent component) + public void ClearTemplate(EntityUid uid, BiomeComponent component, bool dirty = true) { component.Layers.Clear(); component.Template = null; - Dirty(component); + + if (dirty) + Dirty(uid, component); } /// /// Sets the and refreshes layers. /// - public void SetTemplate(BiomeComponent component, BiomeTemplatePrototype template) + public void SetTemplate(EntityUid uid, BiomeComponent component, BiomeTemplatePrototype template, bool dirty = true) { component.Layers.Clear(); component.Template = template.ID; @@ -142,13 +187,14 @@ public sealed partial class BiomeSystem : SharedBiomeSystem component.Layers.Add(layer); } - Dirty(component); + if (dirty) + Dirty(uid, component); } /// /// Adds the specified layer at the specified marker if it exists. /// - public void AddLayer(BiomeComponent component, string id, IBiomeLayer addedLayer, int seedOffset = 0) + public void AddLayer(EntityUid uid, BiomeComponent component, string id, IBiomeLayer addedLayer, int seedOffset = 0) { for (var i = 0; i < component.Layers.Count; i++) { @@ -162,25 +208,19 @@ public sealed partial class BiomeSystem : SharedBiomeSystem break; } - Dirty(component); + Dirty(uid, component); } - public void AddMarkerLayer(BiomeComponent component, string marker) + public void AddMarkerLayer(EntityUid uid, BiomeComponent component, string marker) { - if (!ProtoManager.HasIndex(marker)) - { - // TODO: Log when we get a sawmill - return; - } - component.MarkerLayers.Add(marker); - Dirty(component); + Dirty(uid, component); } /// /// Adds the specified template at the specified marker if it exists, withour overriding every layer. /// - public void AddTemplate(BiomeComponent component, string id, BiomeTemplatePrototype template, int seedOffset = 0) + public void AddTemplate(EntityUid uid, BiomeComponent component, string id, BiomeTemplatePrototype template, int seedOffset = 0) { for (var i = 0; i < component.Layers.Count; i++) { @@ -199,7 +239,7 @@ public sealed partial class BiomeSystem : SharedBiomeSystem break; } - Dirty(component); + Dirty(uid, component); } private void OnFTLStarted(ref FTLStartedEvent ev) @@ -258,7 +298,7 @@ public sealed partial class BiomeSystem : SharedBiomeSystem foreach (var layer in markers) { - var proto = ProtoManager.Index(layer); + var proto = ProtoManager.Index(layer); var enumerator = new ChunkIndicesEnumerator(area, proto.Size); while (enumerator.MoveNext(out var chunk)) @@ -273,8 +313,6 @@ public sealed partial class BiomeSystem : SharedBiomeSystem public override void Update(float frameTime) { base.Update(frameTime); - var biomeQuery = GetEntityQuery(); - var xformQuery = GetEntityQuery(); var biomes = AllEntityQuery(); while (biomes.MoveNext(out var biome)) @@ -286,17 +324,16 @@ public sealed partial class BiomeSystem : SharedBiomeSystem // Get chunks in range foreach (var pSession in Filter.GetAllPlayers(_playerManager)) { - - if (xformQuery.TryGetComponent(pSession.AttachedEntity, out var xform) && + if (_xformQuery.TryGetComponent(pSession.AttachedEntity, out var xform) && _handledEntities.Add(pSession.AttachedEntity.Value) && - biomeQuery.TryGetComponent(xform.MapUid, out var biome)) + _biomeQuery.TryGetComponent(xform.MapUid, out var biome)) { - var worldPos = _transform.GetWorldPosition(xform, xformQuery); + var worldPos = _transform.GetWorldPosition(xform); AddChunksInRange(biome, worldPos); foreach (var layer in biome.MarkerLayers) { - var layerProto = ProtoManager.Index(layer); + var layerProto = ProtoManager.Index(layer); AddMarkerChunksInRange(biome, worldPos, layerProto); } } @@ -304,18 +341,18 @@ public sealed partial class BiomeSystem : SharedBiomeSystem foreach (var viewer in pSession.ViewSubscriptions) { if (!_handledEntities.Add(viewer) || - !xformQuery.TryGetComponent(viewer, out xform) || - !biomeQuery.TryGetComponent(xform.MapUid, out biome)) + !_xformQuery.TryGetComponent(viewer, out xform) || + !_biomeQuery.TryGetComponent(xform.MapUid, out biome)) { continue; } - var worldPos = _transform.GetWorldPosition(xform, xformQuery); + var worldPos = _transform.GetWorldPosition(xform); AddChunksInRange(biome, worldPos); foreach (var layer in biome.MarkerLayers) { - var layerProto = ProtoManager.Index(layer); + var layerProto = ProtoManager.Index(layer); AddMarkerChunksInRange(biome, worldPos, layerProto); } } @@ -326,7 +363,7 @@ public sealed partial class BiomeSystem : SharedBiomeSystem while (loadBiomes.MoveNext(out var gridUid, out var biome, out var grid)) { // Load new chunks - LoadChunks(biome, gridUid, grid, biome.Seed, xformQuery); + LoadChunks(biome, gridUid, grid, biome.Seed, _xformQuery); // Unload old chunks UnloadChunks(biome, gridUid, grid, biome.Seed); } @@ -867,10 +904,12 @@ public sealed partial class BiomeSystem : SharedBiomeSystem if (!Resolve(mapUid, ref metadata)) return; - var biome = EnsureComp(mapUid); + EnsureComp(mapUid); + var biome = (BiomeComponent) EntityManager.ComponentFactory.GetComponent(typeof(BiomeComponent)); seed ??= _random.Next(); - SetSeed(biome, seed.Value); - SetTemplate(biome, biomeTemplate); + SetSeed(mapUid, biome, seed.Value, false); + SetTemplate(mapUid, biome, biomeTemplate, false); + AddComp(mapUid, biome, true); Dirty(mapUid, biome, metadata); var gravity = EnsureComp(mapUid); @@ -902,7 +941,41 @@ public sealed partial class BiomeSystem : SharedBiomeSystem }; _atmos.SetMapAtmosphere(mapUid, false, mixture, atmos); + } - EnsureComp(mapUid); + /// + /// Sets the specified tiles as relevant and marks them as modified. + /// + public void ReserveTiles(EntityUid mapUid, Box2 bounds, List<(Vector2i Index, Tile Tile)> tiles, BiomeComponent? biome = null, MapGridComponent? mapGrid = null) + { + if (!Resolve(mapUid, ref biome, ref mapGrid, false)) + return; + + foreach (var tileSet in _mapSystem.GetLocalTilesIntersecting(mapUid, mapGrid, bounds, false)) + { + Vector2i chunkOrigin; + HashSet modified; + + // Existing, ignore + if (_mapSystem.TryGetTileRef(mapUid, mapGrid, tileSet.GridIndices, out var existingRef) && !existingRef.Tile.IsEmpty) + { + chunkOrigin = SharedMapSystem.GetChunkIndices(tileSet.GridIndices, ChunkSize) * ChunkSize; + modified = biome.ModifiedTiles.GetOrNew(chunkOrigin); + modified.Add(tileSet.GridIndices); + continue; + } + + if (!TryGetBiomeTile(tileSet.GridIndices, biome.Layers, biome.Seed, mapGrid, out var tile)) + { + continue; + } + + chunkOrigin = SharedMapSystem.GetChunkIndices(tileSet.GridIndices, ChunkSize) * ChunkSize; + modified = biome.ModifiedTiles.GetOrNew(chunkOrigin); + modified.Add(tileSet.GridIndices); + tiles.Add((tileSet.GridIndices, tile.Value)); + } + + _mapSystem.SetTiles(mapUid, mapGrid, tiles); } } diff --git a/Content.Server/Salvage/SpawnSalvageMissionJob.cs b/Content.Server/Salvage/SpawnSalvageMissionJob.cs index c1e4822879..eb370aa112 100644 --- a/Content.Server/Salvage/SpawnSalvageMissionJob.cs +++ b/Content.Server/Salvage/SpawnSalvageMissionJob.cs @@ -106,14 +106,14 @@ public sealed class SpawnSalvageMissionJob : Job { var biome = _entManager.AddComponent(mapUid); var biomeSystem = _entManager.System(); - biomeSystem.SetTemplate(biome, _prototypeManager.Index(missionBiome.BiomePrototype)); - biomeSystem.SetSeed(biome, mission.Seed); - _entManager.Dirty(biome); + biomeSystem.SetTemplate(mapUid, biome, _prototypeManager.Index(missionBiome.BiomePrototype)); + biomeSystem.SetSeed(mapUid, biome, mission.Seed); + _entManager.Dirty(mapUid, biome); // Gravity var gravity = _entManager.EnsureComponent(mapUid); gravity.Enabled = true; - _entManager.Dirty(gravity, metadata); + _entManager.Dirty(mapUid, gravity, metadata); // Atmos var air = _prototypeManager.Index(mission.Air); @@ -310,7 +310,7 @@ public sealed class SpawnSalvageMissionJob : Job { if (_entManager.TryGetComponent(gridUid, out var biome)) { - _biome.AddMarkerLayer(biome, biomeLoot.Prototype); + _biome.AddMarkerLayer(gridUid, biome, biomeLoot.Prototype); } } break; @@ -318,7 +318,7 @@ public sealed class SpawnSalvageMissionJob : Job { if (_entManager.TryGetComponent(gridUid, out var biome)) { - _biome.AddTemplate(biome, "Loot", _prototypeManager.Index(biomeLoot.Prototype), i); + _biome.AddTemplate(gridUid, biome, "Loot", _prototypeManager.Index(biomeLoot.Prototype), i); } } break; diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs index fead51ed7c..15f1da5c28 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs @@ -274,7 +274,7 @@ public sealed partial class ShuttleSystem if (TryComp(uid, out body)) { if (shuttle != null) - Enable(uid, body, shuttle); + Enable(uid, component: body, shuttle: shuttle); _physics.SetLinearVelocity(uid, new Vector2(0f, 20f), body: body); _physics.SetAngularVelocity(uid, 0f, body: body); _physics.SetLinearDamping(body, 0f); @@ -365,11 +365,11 @@ public sealed partial class ShuttleSystem // to event ordering and awake body shenanigans (at least for now). if (HasComp(xform.MapUid)) { - Disable(uid, body); + Disable(uid, component: body); } else if (shuttle != null) { - Enable(uid, body, shuttle); + Enable(uid, component: body, shuttle: shuttle); } } @@ -701,6 +701,7 @@ public sealed partial class ShuttleSystem var transform = _physics.GetPhysicsTransform(uid, xform, _xformQuery); var aabbs = new List(manager.Fixtures.Count); var immune = new HashSet(); + var tileSet = new List<(Vector2i, Tile)>(); foreach (var fixture in manager.Fixtures.Values) { @@ -712,6 +713,10 @@ public sealed partial class ShuttleSystem aabb = aabb.Enlarged(0.2f); aabbs.Add(aabb); + // Handle clearing biome stuff as relevant. + tileSet.Clear(); + _biomes.ReserveTiles(xform.MapUid.Value, aabb, tileSet); + foreach (var ent in _lookup.GetEntitiesIntersecting(xform.MapUid.Value, aabb, LookupFlags.Uncontained)) { if (ent == uid || immune.Contains(ent)) diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.cs index 97bfdc1756..3e941e67b4 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.cs @@ -1,5 +1,6 @@ using Content.Server.Body.Systems; using Content.Server.Doors.Systems; +using Content.Server.Parallax; using Content.Server.Shuttles.Components; using Content.Server.Station.Systems; using Content.Server.Stunnable; @@ -28,6 +29,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem [Dependency] private readonly IMapManager _mapManager = 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 DockingSystem _dockSystem = default!; [Dependency] private readonly DoorSystem _doors = default!; @@ -37,6 +39,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem [Dependency] private readonly MapLoaderSystem _loader = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedMapSystem _maps = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly ShuttleConsoleSystem _console = default!; @@ -115,7 +118,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem if (component.Enabled) { - Enable(uid, physicsComponent, component); + Enable(uid, component: physicsComponent, shuttle: component); } } @@ -128,17 +131,18 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem if (component.Enabled) { - Enable(uid, physicsComponent, component); + Enable(uid, component: physicsComponent, shuttle: component); } else { - Disable(uid, physicsComponent); + Disable(uid, component: physicsComponent); } } - private void Enable(EntityUid uid, PhysicsComponent component, ShuttleComponent shuttle) + public void Enable(EntityUid uid, FixturesComponent? manager = null, PhysicsComponent? component = null, ShuttleComponent? shuttle = null) { - FixturesComponent? manager = null; + if (!Resolve(uid, ref manager, ref component, ref shuttle, false)) + return; _physics.SetBodyType(uid, BodyType.Dynamic, manager: manager, body: component); _physics.SetBodyStatus(component, BodyStatus.InAir); @@ -147,9 +151,10 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem _physics.SetAngularDamping(component, shuttle.AngularDamping); } - private void Disable(EntityUid uid, PhysicsComponent component) + public void Disable(EntityUid uid, FixturesComponent? manager = null, PhysicsComponent? component = null) { - FixturesComponent? manager = null; + if (!Resolve(uid, ref manager, ref component, false)) + return; _physics.SetBodyType(uid, BodyType.Static, manager: manager, body: component); _physics.SetBodyStatus(component, BodyStatus.OnGround); @@ -162,11 +167,6 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem if (EntityManager.GetComponent(uid).EntityLifeStage >= EntityLifeStage.Terminating) return; - if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent)) - { - return; - } - - Disable(uid, physicsComponent); + Disable(uid); } }