mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Misc grid state changes (#5597)
This commit is contained in:
@@ -26,6 +26,8 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
protected override void OnAppearanceGetState(EntityUid uid, AppearanceComponent component, ref ComponentGetState args)
|
||||
{
|
||||
// TODO Game State
|
||||
// Force the client to serialize & de-serialize implicitly generated component states.
|
||||
var clone = CloneAppearanceData(component.AppearanceData);
|
||||
args.State = new AppearanceComponentState(clone);
|
||||
}
|
||||
|
||||
@@ -153,7 +153,6 @@ namespace Robust.Shared.GameObjects
|
||||
newFixtures.Add(($"grid_chunk-{bounds.Left}-{bounds.Bottom}", newFixture));
|
||||
}
|
||||
|
||||
var toRemove = new ValueList<(string Id, Fixture Fixture)>();
|
||||
// Check if we even need to issue an eventbus event
|
||||
var updated = false;
|
||||
|
||||
@@ -167,6 +166,13 @@ namespace Robust.Shared.GameObjects
|
||||
for (var i = newFixtures.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var fixture = newFixtures[i].Fixture;
|
||||
|
||||
// TODO GRIDS
|
||||
// Fix this
|
||||
// This **only** works if we assume the density is always the default (PhysicsConstants.DefaultDensity).
|
||||
// Hence, this always fails in SS14 because ShuttleSystem.OnGridFixtureChange changes the density.
|
||||
// So it constantly creats & destroys fixtures unnecessarily
|
||||
// AAAAA
|
||||
if (!oldFixture.Equals(fixture))
|
||||
continue;
|
||||
|
||||
@@ -175,21 +181,16 @@ namespace Robust.Shared.GameObjects
|
||||
break;
|
||||
}
|
||||
|
||||
if (existing)
|
||||
continue;
|
||||
|
||||
// Doesn't align with any new fixtures so delete
|
||||
if (existing) continue;
|
||||
|
||||
toRemove.Add((oldId, oldFixture));
|
||||
chunk.Fixtures.Remove(oldId);
|
||||
_fixtures.DestroyFixture(uid, oldId, oldFixture, false, body: body, manager: manager, xform: xform);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
foreach (var (id, fixture) in toRemove.Span)
|
||||
{
|
||||
// TODO add a DestroyFixture() override that takes in a list.
|
||||
// reduced broadphase lookups
|
||||
chunk.Fixtures.Remove(id);
|
||||
_fixtures.DestroyFixture(uid, id, fixture, false, body: body, manager: manager, xform: xform);
|
||||
}
|
||||
|
||||
if (newFixtures.Count > 0 || toRemove.Count > 0)
|
||||
if (newFixtures.Count > 0)
|
||||
{
|
||||
updated = true;
|
||||
}
|
||||
@@ -200,10 +201,11 @@ namespace Robust.Shared.GameObjects
|
||||
chunk.Fixtures.Add(id);
|
||||
var existingFixture = _fixtures.GetFixtureOrNull(uid, id, manager: manager);
|
||||
// Check if it's the same (otherwise remove anyway).
|
||||
// TODO GRIDS
|
||||
// wasn't this already checked?
|
||||
if (existingFixture?.Shape is PolygonShape poly &&
|
||||
poly.EqualsApprox((PolygonShape) fixture.Shape))
|
||||
{
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -245,13 +245,10 @@ public abstract partial class SharedMapSystem
|
||||
|
||||
private void OnGridHandleState(EntityUid uid, MapGridComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
HashSet<MapChunk> modifiedChunks;
|
||||
|
||||
switch (args.Current)
|
||||
{
|
||||
case MapGridComponentDeltaState delta:
|
||||
{
|
||||
modifiedChunks = new();
|
||||
DebugTools.Assert(component.ChunkSize == delta.ChunkSize || component.Chunks.Count == 0,
|
||||
"Can't modify chunk size of an existing grid.");
|
||||
|
||||
@@ -261,7 +258,7 @@ public abstract partial class SharedMapSystem
|
||||
|
||||
foreach (var (index, chunkData) in delta.ChunkData)
|
||||
{
|
||||
ApplyChunkData(uid, component, index, chunkData, modifiedChunks);
|
||||
ApplyChunkData(uid, component, index, chunkData);
|
||||
}
|
||||
|
||||
component.LastTileModifiedTick = delta.LastTileModifiedTick;
|
||||
@@ -269,7 +266,6 @@ public abstract partial class SharedMapSystem
|
||||
}
|
||||
case MapGridComponentState state:
|
||||
{
|
||||
modifiedChunks = new();
|
||||
DebugTools.Assert(component.ChunkSize == state.ChunkSize || component.Chunks.Count == 0,
|
||||
"Can't modify chunk size of an existing grid.");
|
||||
|
||||
@@ -279,12 +275,13 @@ public abstract partial class SharedMapSystem
|
||||
foreach (var index in component.Chunks.Keys)
|
||||
{
|
||||
if (!state.FullGridData.ContainsKey(index))
|
||||
ApplyChunkData(uid, component, index, ChunkDatum.Empty, modifiedChunks);
|
||||
ApplyChunkData(uid, component, index, ChunkDatum.Empty);
|
||||
}
|
||||
|
||||
foreach (var (index, data) in state.FullGridData)
|
||||
{
|
||||
ApplyChunkData(uid, component, index, new(data), modifiedChunks);
|
||||
DebugTools.Assert(!data.IsDeleted());
|
||||
ApplyChunkData(uid, component, index, data);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -309,10 +306,8 @@ public abstract partial class SharedMapSystem
|
||||
EntityUid uid,
|
||||
MapGridComponent component,
|
||||
Vector2i index,
|
||||
ChunkDatum data,
|
||||
HashSet<MapChunk> modifiedChunks)
|
||||
ChunkDatum data)
|
||||
{
|
||||
bool shapeChanged = false;
|
||||
var counter = 0;
|
||||
|
||||
if (data.IsDeleted())
|
||||
@@ -326,7 +321,7 @@ public abstract partial class SharedMapSystem
|
||||
{
|
||||
for (ushort y = 0; y < component.ChunkSize; y++)
|
||||
{
|
||||
if (!deletedChunk.TrySetTile(x, y, Tile.Empty, out var oldTile, out var chunkShapeChanged))
|
||||
if (!deletedChunk.TrySetTile(x, y, Tile.Empty, out var oldTile, out _))
|
||||
continue;
|
||||
|
||||
var gridIndices = deletedChunk.ChunkTileToGridTile((x, y));
|
||||
@@ -336,9 +331,6 @@ public abstract partial class SharedMapSystem
|
||||
}
|
||||
|
||||
component.Chunks.Remove(index);
|
||||
|
||||
// TODO is this required?
|
||||
modifiedChunks.Add(deletedChunk);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -351,30 +343,26 @@ public abstract partial class SharedMapSystem
|
||||
for (ushort y = 0; y < component.ChunkSize; y++)
|
||||
{
|
||||
var tile = data.TileData[counter++];
|
||||
if (!chunk.TrySetTile(x, y, tile, out var oldTile, out var tileShapeChanged))
|
||||
if (!chunk.TrySetTile(x, y, tile, out var oldTile, out _))
|
||||
continue;
|
||||
|
||||
shapeChanged |= tileShapeChanged;
|
||||
var gridIndices = chunk.ChunkTileToGridTile((x, y));
|
||||
var newTileRef = new TileRef(uid, gridIndices, tile);
|
||||
_mapInternal.RaiseOnTileChanged(newTileRef, oldTile, index);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.Fixtures != null && !chunk.Fixtures.SetEquals(data.Fixtures))
|
||||
// These should never refer to the same object
|
||||
DebugTools.AssertNotEqual(chunk.Fixtures, data.Fixtures);
|
||||
|
||||
if (!chunk.Fixtures.SetEquals(data.Fixtures))
|
||||
{
|
||||
chunk.Fixtures.Clear();
|
||||
|
||||
if (data.Fixtures != null)
|
||||
chunk.Fixtures.UnionWith(data.Fixtures);
|
||||
chunk.Fixtures.UnionWith(data.Fixtures);
|
||||
}
|
||||
|
||||
chunk.CachedBounds = data.CachedBounds!.Value;
|
||||
chunk.SuppressCollisionRegeneration = false;
|
||||
if (shapeChanged)
|
||||
{
|
||||
modifiedChunks.Add(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGridGetState(EntityUid uid, MapGridComponent component, ref ComponentGetState args)
|
||||
@@ -429,7 +417,15 @@ public abstract partial class SharedMapSystem
|
||||
tileBuffer[x * component.ChunkSize + y] = chunk.GetTile((ushort)x, (ushort)y);
|
||||
}
|
||||
}
|
||||
chunkData.Add(index, ChunkDatum.CreateModified(tileBuffer, chunk.Fixtures, chunk.CachedBounds));
|
||||
|
||||
// The client needs to clone the fixture set instead of storing a reference.
|
||||
// TODO Game State
|
||||
// Force the client to serialize & de-serialize implicitly generated component states.
|
||||
var fixtures = chunk.Fixtures;
|
||||
if (_netManager.IsClient)
|
||||
fixtures = new(fixtures);
|
||||
|
||||
chunkData.Add(index, ChunkDatum.CreateModified(tileBuffer, fixtures, chunk.CachedBounds));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,7 +462,15 @@ public abstract partial class SharedMapSystem
|
||||
tileBuffer[x * component.ChunkSize + y] = chunk.GetTile((ushort)x, (ushort)y);
|
||||
}
|
||||
}
|
||||
chunkData.Add(index, ChunkDatum.CreateModified(tileBuffer, chunk.Fixtures, chunk.CachedBounds));
|
||||
|
||||
// The client needs to clone the fixture set instead of storing a reference.
|
||||
// TODO Game State
|
||||
// Force the client to serialize & de-serialize implicitly generated component states.
|
||||
var fixtures = chunk.Fixtures;
|
||||
if (_netManager.IsClient)
|
||||
fixtures = new(fixtures);
|
||||
|
||||
chunkData.Add(index, ChunkDatum.CreateModified(tileBuffer, fixtures, chunk.CachedBounds));
|
||||
}
|
||||
|
||||
args.State = new MapGridComponentState(component.ChunkSize, chunkData, component.LastTileModifiedTick);
|
||||
@@ -644,10 +648,12 @@ public abstract partial class SharedMapSystem
|
||||
|
||||
foreach (var id in mapChunk.Fixtures)
|
||||
{
|
||||
mapChunk.Fixtures.Remove(id);
|
||||
_fixtures.DestroyFixture(uid, id, false, manager: manager, body: body, xform: xform);
|
||||
}
|
||||
|
||||
RemoveChunk(uid, grid, mapChunk.Indices);
|
||||
DebugTools.AssertEqual(mapChunk.Fixtures.Count, 0);
|
||||
removedChunks.Add(mapChunk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,12 +322,14 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
}
|
||||
case 1 << 2:
|
||||
{
|
||||
var state = new UserInterfaceStatesDeltaState()
|
||||
{
|
||||
States = new Dictionary<Enum, BoundUserInterfaceState>(ent.Comp.States),
|
||||
};
|
||||
var states = ent.Comp.States;
|
||||
|
||||
args.State = state;
|
||||
// TODO Game State
|
||||
// Force the client to serialize & de-serialize implicitly generated component states.
|
||||
if (_netManager.IsClient)
|
||||
states = new(states);
|
||||
|
||||
args.State = new UserInterfaceStatesDeltaState {States = states};
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -336,6 +338,8 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
var actors = new Dictionary<Enum, List<NetEntity>>();
|
||||
var dataCopy = new Dictionary<Enum, InterfaceData>(ent.Comp.Interfaces.Count);
|
||||
|
||||
// TODO Game State
|
||||
// Force the client to serialize & de-serialize implicitly generated component states.
|
||||
foreach (var (weh, a) in ent.Comp.Interfaces)
|
||||
{
|
||||
dataCopy[weh] = new InterfaceData(a);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Robust.Shared.GameStates
|
||||
[Serializable, NetSerializable]
|
||||
public readonly struct ChunkDatum
|
||||
{
|
||||
public static readonly ChunkDatum Empty = new ChunkDatum();
|
||||
public static readonly ChunkDatum Empty = new();
|
||||
|
||||
public readonly HashSet<string>? Fixtures;
|
||||
|
||||
@@ -21,28 +21,12 @@ namespace Robust.Shared.GameStates
|
||||
|
||||
public readonly Box2i? CachedBounds;
|
||||
|
||||
[MemberNotNullWhen(false, nameof(TileData))]
|
||||
[MemberNotNullWhen(false, nameof(TileData), nameof(Fixtures))]
|
||||
public bool IsDeleted()
|
||||
{
|
||||
return TileData == null;
|
||||
}
|
||||
|
||||
internal ChunkDatum(ChunkDatum data)
|
||||
{
|
||||
if (data.TileData != null)
|
||||
{
|
||||
TileData = new Tile[data.TileData.Length];
|
||||
data.TileData.CopyTo(TileData, 0);
|
||||
}
|
||||
|
||||
if (data.Fixtures != null)
|
||||
{
|
||||
Fixtures = new HashSet<string>(data.Fixtures);
|
||||
}
|
||||
|
||||
CachedBounds = data.CachedBounds;
|
||||
}
|
||||
|
||||
private ChunkDatum(Tile[] tileData, HashSet<string> fixtures, Box2i cachedBounds)
|
||||
{
|
||||
TileData = tileData;
|
||||
|
||||
@@ -319,7 +319,7 @@ namespace Robust.Shared.Map.Components
|
||||
if (data.IsDeleted())
|
||||
state.FullGridData.Remove(index);
|
||||
else
|
||||
state.FullGridData[index] = new(data);
|
||||
state.FullGridData[index] = data;
|
||||
}
|
||||
|
||||
state.LastTileModifiedTick = LastTileModifiedTick;
|
||||
@@ -327,14 +327,10 @@ namespace Robust.Shared.Map.Components
|
||||
|
||||
public MapGridComponentState CreateNewFullState(MapGridComponentState state)
|
||||
{
|
||||
var fullGridData = new Dictionary<Vector2i, ChunkDatum>(state.FullGridData.Count);
|
||||
if (ChunkData == null)
|
||||
return new(ChunkSize, state.FullGridData, state.LastTileModifiedTick);
|
||||
|
||||
foreach (var (key, value) in state.FullGridData)
|
||||
{
|
||||
fullGridData[key] = new(value);
|
||||
}
|
||||
|
||||
var newState = new MapGridComponentState(ChunkSize, fullGridData, LastTileModifiedTick);
|
||||
var newState = new MapGridComponentState(ChunkSize, state.FullGridData.ShallowClone(), LastTileModifiedTick);
|
||||
ApplyToFullState(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ using Robust.Shared.Collections;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Physics.Systems
|
||||
@@ -21,6 +23,7 @@ namespace Robust.Shared.Physics.Systems
|
||||
{
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
private EntityQuery<PhysicsMapComponent> _mapQuery;
|
||||
private EntityQuery<PhysicsComponent> _physicsQuery;
|
||||
private EntityQuery<FixturesComponent> _fixtureQuery;
|
||||
@@ -180,6 +183,18 @@ namespace Robust.Shared.Physics.Systems
|
||||
return;
|
||||
}
|
||||
|
||||
// Temporary debug block for trying to help catch a bug where grid fixtures disappear without the chunk's
|
||||
// fixture set being updated
|
||||
#if DEBUG
|
||||
if (TryComp(uid, out MapGridComponent? grid) && !_timing.ApplyingState)
|
||||
{
|
||||
foreach (var chunk in grid.Chunks.Values)
|
||||
{
|
||||
DebugTools.Assert(!chunk.Fixtures.Contains(fixtureId), $"A grid fixture is being deleted without first removing it from the chunk. Please report this bug.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach (var contact in fixture.Contacts.Values.ToArray())
|
||||
{
|
||||
_physics.DestroyContact(contact);
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics.Components;
|
||||
|
||||
namespace Robust.Shared.Physics.Systems;
|
||||
|
||||
public abstract partial class SharedPhysicsSystem
|
||||
{
|
||||
private void InitializeFixturesChange()
|
||||
{
|
||||
SubscribeLocalEvent<FixturesChangeComponent, ComponentStartup>(OnChangeStartup);
|
||||
SubscribeLocalEvent<FixturesChangeComponent, ComponentShutdown>(OnChangeShutdown);
|
||||
}
|
||||
|
||||
private void OnChangeStartup(Entity<FixturesChangeComponent> ent, ref ComponentStartup args)
|
||||
{
|
||||
foreach (var (id, fixture) in ent.Comp.Fixtures)
|
||||
{
|
||||
_fixtures.TryCreateFixture(ent.Owner,
|
||||
fixture.Shape,
|
||||
id,
|
||||
fixture.Density,
|
||||
fixture.Hard,
|
||||
fixture.CollisionLayer,
|
||||
fixture.CollisionMask,
|
||||
fixture.Friction,
|
||||
fixture.Restitution);
|
||||
}
|
||||
|
||||
// TODO: Fixture creation should be handling this.
|
||||
WakeBody(ent.Owner);
|
||||
}
|
||||
|
||||
private void OnChangeShutdown(Entity<FixturesChangeComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
foreach (var id in ent.Comp.Fixtures.Keys)
|
||||
{
|
||||
_fixtures.DestroyFixture(ent.Owner, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user