-
Notifications
You must be signed in to change notification settings - Fork 188
hotfix 23.01.2026 #1431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hotfix 23.01.2026 #1431
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,31 @@ | ||
| using System; | ||
| using System; | ||
| using System.Linq; | ||
| using System.Numerics; | ||
| using Content.Server._Lavaland.Procedural.Components; | ||
| using Content.Server.Atmos; | ||
| using Content.Server.Atmos.Components; | ||
| using Content.Server.Atmos.EntitySystems; | ||
| using Content.Server.Light.Components; | ||
| using Content.Shared._Lavaland.Procedural.Components; | ||
| using Content.Shared._Lavaland.Procedural.Prototypes; | ||
| using Content.Shared.Atmos; | ||
| using Content.Shared.Atmos.Components; | ||
| using Content.Shared.Light.Components; | ||
| using Content.Shared.Light.EntitySystems; | ||
| using Content.Shared.Maps; | ||
| using Robust.Server.Physics; | ||
| using Robust.Shared.Map; | ||
| using Robust.Shared.Map.Components; | ||
| using Robust.Shared.Random; | ||
| using Robust.Shared.Utility; | ||
|
|
||
| namespace Content.Server._Lavaland.Procedural.Systems; | ||
|
|
||
| public sealed partial class LavalandPlanetSystem | ||
| { | ||
| [Dependency] private readonly GridFixtureSystem _gridFixture = default!; | ||
| [Dependency] private readonly ITileDefinitionManager _tileDef = default!; | ||
| [Dependency] private readonly SharedRoofSystem _roofSystem = default!; | ||
|
|
||
| private bool LoadGridRuin( | ||
| LavalandGridRuinPrototype ruin, | ||
|
|
@@ -130,27 +140,41 @@ private bool LoadGridRuin( | |
| // Get the rotation of the target grid | ||
| var rotation = Transform(spawned.Value).LocalRotation; | ||
|
|
||
| // Replace empty tiles in spawned grid with tiles from the same position in lavaland grid | ||
| foreach (var tile in _map.GetAllTiles(spawned.Value, spawnedGrid, false)) | ||
| var tilesToRoof = new HashSet<Vector2i>(); | ||
| Entity<MapGridComponent, RoofComponent> spawnedRoof = (spawned.Value, spawnedGrid, EnsureComp<RoofComponent>(spawned.Value)); | ||
| Entity<MapGridComponent?, RoofComponent?> roofMap = (sourceGridUid, sourceGrid, EnsureComp<RoofComponent>(sourceGridUid)); | ||
|
|
||
| var matrix = Matrix3Helpers.CreateTransform(offset, rotation); | ||
|
|
||
| { | ||
| if (tile.Tile == Tile.Empty) | ||
| var enumerator = _map.GetAllTilesEnumerator(spawned.Value, spawnedGrid); | ||
| while (enumerator.MoveNext(out var tileRef)) | ||
| { | ||
| // Get world position of this tile | ||
| var tileWorldPos = _map.GridTileToWorldPos(spawned.Value, spawnedGrid, tile.GridIndices); | ||
| var offsetTile = Vector2.Transform(new Vector2(tileRef.Value.GridIndices.X, tileRef.Value.GridIndices.Y) + sourceGrid.TileSizeHalfVector, matrix) | ||
| .Floored(); | ||
| if (_roofSystem.IsRooved(spawnedRoof, tileRef.Value.GridIndices)) | ||
| { | ||
| _roofSystem.SetRoof(roofMap, offsetTile, true); | ||
| tilesToRoof.Add(offsetTile); | ||
| } | ||
|
|
||
| // Convert to local coordinates in lavaland grid | ||
| var lavalandTileIndices = _map.WorldToTile(sourceGridUid, sourceGrid, tileWorldPos); | ||
| if(tileRef.Value.Tile != Tile.Empty) | ||
| continue; | ||
|
|
||
| // Get tile from lavaland grid at this position | ||
| if (_map.TryGetTileRef(sourceGridUid, sourceGrid, lavalandTileIndices, out var lavalandTile) && | ||
| if (_map.TryGetTileRef(sourceGridUid, sourceGrid, offsetTile, out var lavalandTile) && | ||
| !lavalandTile.Tile.IsEmpty) | ||
| { | ||
| _map.SetTile(spawned.Value, spawnedGrid, tile.GridIndices, lavalandTile.Tile); | ||
| _map.SetTile(spawned.Value, spawnedGrid, offsetTile, lavalandTile.Tile); | ||
| } | ||
|
Comment on lines
+164
to
168
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Find the file and examine the full context around the flagged lines
fd "LavalandPlanetSystem" --type f -x head -n 200 {} \; 2>/dev/null | head -50Repository: Rxup/space-station-14 Length of output: 1823 🏁 Script executed: # Search for SetTile usage patterns with spawned
rg -n -B2 -A3 "\.SetTile\(" --type=cs -g "*LavalandPlanetSystem*"Repository: Rxup/space-station-14 Length of output: 799 🏁 Script executed: # Check Grid.Merge patterns to understand coordinate conventions
rg -n -B2 -A2 "Grid\.Merge|_gridFixture\.Merge" --type=cs | head -40Repository: Rxup/space-station-14 Length of output: 1150 🏁 Script executed: # Find the matrix transformation context to understand source→spawned mapping
rg -n -B5 "Matrix3x2.*transform|offsetTile.*=" --type=cs -g "*LavalandPlanetSystem*" | head -60Repository: Rxup/space-station-14 Length of output: 915 🏁 Script executed: # Get the full context of the loop around lines 145-175
sed -n '130,180p' "Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.cs"Repository: Rxup/space-station-14 Length of output: 2734 🏁 Script executed: # Also check what the matrix represents - look for where it's created
rg -n -B10 "var matrix" --type=cs -g "*LavalandPlanetSystem.Grid.cs*"Repository: Rxup/space-station-14 Length of output: 1634 🏁 Script executed: # Double-check by looking at SetTile signature and how Merge uses the matrix
rg -n "public.*SetTile" --type=cs | head -5Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Verify the matrix direction - check if it's meant to be spawned->source or source->spawned
rg -n "CreateTransform" --type=cs | head -10Repository: Rxup/space-station-14 Length of output: 1666 🏁 Script executed: # Get the actual implementation of SetTile to confirm it takes Vector2i as coordinates
rg -n -A3 "void SetTile.*Vector2i" --type=cs | head -20Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Check if there are similar patterns elsewhere in the codebase that might validate the coordinate handling
rg -n -B5 -A5 "GetAllTilesEnumerator.*while.*tileRef" --type=cs | head -60Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Search for SetTile method signature
rg -n "SetTile" --type=cs -A2 | grep -E "(public|void|SetTile)" | head -20Repository: Rxup/space-station-14 Length of output: 2864 🏁 Script executed: # Look at the actual SharedMapSystem to understand SetTile
fd "SharedMapSystem" --type=f -x cat {} \; | grep -A5 "SetTile" | head -30Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Let me check the loop logic more carefully - maybe offsetTile should actually be inverted before SetTile
rg -n -B20 "SetTile.*spawned" --type=cs -g "*LavalandPlanetSystem*" | tail -40Repository: Rxup/space-station-14 Length of output: 2911 Использованы неправильные координаты для SetTile на spawned grid. В строке 167 Следует использовать _map.SetTile(spawned.Value, spawnedGrid, tileRef.Value.GridIndices, lavalandTile.Tile);Текущая реализация приведёт к тому, что плитки будут установлены на неправильные координаты. Примечание: 🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
|
|
||
| _gridFixture.Merge(sourceGridUid, spawned.Value, offset, rotation); | ||
| _gridFixture.Merge(sourceGridUid, spawned.Value, matrix); | ||
|
|
||
| foreach (var vector2I in tilesToRoof) | ||
| { | ||
| _roofSystem.SetRoof(roofMap, vector2I, true); | ||
| } | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Content.Server._Lavaland.Procedural.Components; | ||
| using Content.Server.Light.EntitySystems; | ||
| using Content.Server.Temperature.Systems; | ||
| using Content.Server.Weather; | ||
| using Content.Shared._Lavaland.Procedural.Components; | ||
|
|
@@ -9,9 +10,12 @@ | |
| using Content.Shared.Damage.Components; | ||
| using Content.Shared.Damage.Systems; | ||
| using Content.Shared.Humanoid; | ||
| using Content.Shared.Light.Components; | ||
| using Content.Shared.Popups; | ||
| using Robust.Shared.CPUJob.JobQueues; | ||
| using Robust.Shared.CPUJob.JobQueues.Queues; | ||
| using Robust.Shared.Map; | ||
| using Robust.Shared.Map.Components; | ||
| using Robust.Shared.Prototypes; | ||
| using Robust.Shared.Random; | ||
|
|
||
|
|
@@ -25,6 +29,10 @@ public sealed class LavalandWeatherSystem : EntitySystem | |
| [Dependency] private readonly IPrototypeManager _proto = default!; | ||
| [Dependency] private readonly TemperatureSystem _temperature = default!; | ||
| [Dependency] private readonly DamageableSystem _damage = default!; | ||
| [Dependency] private readonly RoofSystem _roof = default!; | ||
| [Dependency] private readonly IMapManager _mapManager = default!; | ||
| [Dependency] private readonly SharedTransformSystem _transform = default!; | ||
| [Dependency] private readonly SharedMapSystem _mapSystem = default!; | ||
|
|
||
| private const double LavalandWeatherJobTime = 0.005; | ||
| private readonly JobQueue _lavalandWeatherJobQueue = new(LavalandWeatherJobTime); | ||
|
|
@@ -52,6 +60,16 @@ private void ProcessLavalandDamage(Entity<DamageableComponent> entity, Entity<La | |
| if (xform.GridUid != lavaland.Owner) | ||
| return; | ||
|
|
||
|
|
||
| if ( | ||
| _mapSystem.TryGetTileRef(lavaland.Owner, Comp<MapGridComponent>(lavaland.Owner), xform.Coordinates, out var tile) && | ||
| _roof.IsRooved( | ||
| (lavaland.Owner, Comp<MapGridComponent>(lavaland.Owner), Comp<RoofComponent>(lavaland.Owner)), | ||
| tile.GridIndices)) | ||
| { | ||
| return; | ||
| } | ||
|
Comment on lines
+64
to
+71
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Дублирующийся вызов Comp и потенциальный NullReferenceException.
🐛 Предлагаемое исправление- if (
- _mapSystem.TryGetTileRef(lavaland.Owner, Comp<MapGridComponent>(lavaland.Owner), xform.Coordinates, out var tile) &&
- _roof.IsRooved(
- (lavaland.Owner, Comp<MapGridComponent>(lavaland.Owner), Comp<RoofComponent>(lavaland.Owner)),
- tile.GridIndices))
- {
- return;
- }
+ if (!TryComp<MapGridComponent>(lavaland.Owner, out var gridComp) ||
+ !TryComp<RoofComponent>(lavaland.Owner, out var roofComp))
+ return;
+
+ if (_mapSystem.TryGetTileRef(lavaland.Owner, gridComp, xform.Coordinates, out var tile) &&
+ _roof.IsRooved((lavaland.Owner, gridComp, roofComp), tile.GridIndices))
+ {
+ return;
+ }🤖 Prompt for AI Agents |
||
|
|
||
| var proto = _proto.Index(lavaland.Comp.CurrentWeather); | ||
| _temperature.ChangeHeat(entity, proto.TemperatureChange, ignoreHeatResistance: true); | ||
| _damage.ChangeDamage(entity.AsNullable(), proto.Damage); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: Rxup/space-station-14
Length of output: 3274
🏁 Script executed:
Repository: Rxup/space-station-14
Length of output: 47
🏁 Script executed:
Repository: Rxup/space-station-14
Length of output: 47
🏁 Script executed:
Repository: Rxup/space-station-14
Length of output: 157
Ненужная аллокация Queue и неиспользуемый запрос TransformComponent
Метод
Update()выполняется каждый UpdateTime интервал, и на каждой итерации создается новаяQueue. Это вызывает давление на сборщик мусора. Очередь следует переиспользовать как поле класса черезClear().Также
TransformComponentзапрашивается в query (строка 431), но никогда не используется (out _).Анализ показывает, что двухфазная обработка, похоже, не требуется, так как операции внутри цикла не добавляют/удаляют FlammableComponent — они лишь изменяют состояние компонента и добавляют другие типы компонентов (IgnitionSourceComponent).
🔧 Предлагаемое исправление
Добавьте поле класса:
private readonly Dictionary<Entity<FlammableComponent>, float> _fireEvents = new(); +private readonly Queue<(EntityUid, FlammableComponent)> _flammableQueue = new();Затем обновите метод Update:
🤖 Prompt for AI Agents