Add doors to the station map (#23639)

* Add doors to the navmap

* tweaksies

* gah

* draw primitive

* draw primitive? at least take me out to dinner first!

* Update Content.Client/Pinpointer/UI/NavMapControl.cs

* casualties

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Nemanja
2024-01-11 08:14:20 -05:00
committed by GitHub
parent 801f141c6a
commit 1886941da6
12 changed files with 140 additions and 18 deletions

View File

@@ -33,6 +33,9 @@ public sealed class NavMapSystem : SharedNavMapSystem
component.Beacons.Clear(); component.Beacons.Clear();
component.Beacons.AddRange(state.Beacons); component.Beacons.AddRange(state.Beacons);
component.Airlocks.Clear();
component.Airlocks.AddRange(state.Airlocks);
} }
} }

View File

@@ -25,7 +25,7 @@ namespace Content.Client.Pinpointer.UI;
public partial class NavMapControl : MapGridControl public partial class NavMapControl : MapGridControl
{ {
[Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly IEntityManager _entManager = default!;
private readonly SharedTransformSystem _transformSystem = default!; private readonly SharedTransformSystem _transformSystem;
public EntityUid? Owner; public EntityUid? Owner;
public EntityUid? MapUid; public EntityUid? MapUid;
@@ -37,7 +37,7 @@ public partial class NavMapControl : MapGridControl
// Tracked data // Tracked data
public Dictionary<EntityCoordinates, (bool Visible, Color Color)> TrackedCoordinates = new(); public Dictionary<EntityCoordinates, (bool Visible, Color Color)> TrackedCoordinates = new();
public Dictionary<NetEntity, NavMapBlip> TrackedEntities = new(); public Dictionary<NetEntity, NavMapBlip> TrackedEntities = new();
public Dictionary<Vector2i, List<NavMapLine>> TileGrid = default!; public Dictionary<Vector2i, List<NavMapLine>>? TileGrid = default!;
// Default colors // Default colors
public Color WallColor = new(102, 217, 102); public Color WallColor = new(102, 217, 102);
@@ -207,7 +207,6 @@ public partial class NavMapControl : MapGridControl
// Find closest tracked entity in range // Find closest tracked entity in range
var closestEntity = NetEntity.Invalid; var closestEntity = NetEntity.Invalid;
var closestCoords = new EntityCoordinates();
var closestDistance = float.PositiveInfinity; var closestDistance = float.PositiveInfinity;
foreach ((var currentEntity, var blip) in TrackedEntities) foreach ((var currentEntity, var blip) in TrackedEntities)
@@ -221,7 +220,6 @@ public partial class NavMapControl : MapGridControl
continue; continue;
closestEntity = currentEntity; closestEntity = currentEntity;
closestCoords = blip.Coordinates;
closestDistance = currentDistance; closestDistance = currentDistance;
} }
@@ -234,8 +232,7 @@ public partial class NavMapControl : MapGridControl
else if (args.Function == EngineKeyFunctions.UIRightClick) else if (args.Function == EngineKeyFunctions.UIRightClick)
{ {
// Clear current selection with right click // Clear current selection with right click
if (TrackedEntitySelectedAction != null) TrackedEntitySelectedAction?.Invoke(null);
TrackedEntitySelectedAction.Invoke(null);
} }
} }
@@ -260,7 +257,7 @@ public partial class NavMapControl : MapGridControl
{ {
base.Draw(handle); base.Draw(handle);
// Get the components necessary for drawing the navmap // Get the components necessary for drawing the navmap
_entManager.TryGetComponent(MapUid, out _navMap); _entManager.TryGetComponent(MapUid, out _navMap);
_entManager.TryGetComponent(MapUid, out _grid); _entManager.TryGetComponent(MapUid, out _grid);
_entManager.TryGetComponent(MapUid, out _xform); _entManager.TryGetComponent(MapUid, out _xform);
@@ -318,7 +315,7 @@ public partial class NavMapControl : MapGridControl
var area = new Box2(-WorldRange, -WorldRange, WorldRange + 1f, WorldRange + 1f).Translated(offset); var area = new Box2(-WorldRange, -WorldRange, WorldRange + 1f, WorldRange + 1f).Translated(offset);
// Drawing lines can be rather expensive due to the number of neighbors that need to be checked in order // Drawing lines can be rather expensive due to the number of neighbors that need to be checked in order
// to figure out where they should be drawn. However, we don't *need* to do check these every frame. // to figure out where they should be drawn. However, we don't *need* to do check these every frame.
// Instead, lets periodically update where to draw each line and then store these points in a list. // Instead, lets periodically update where to draw each line and then store these points in a list.
// Then we can just run through the list each frame and draw the lines without any extra computation. // Then we can just run through the list each frame and draw the lines without any extra computation.
@@ -360,6 +357,41 @@ public partial class NavMapControl : MapGridControl
} }
} }
var airlockBuffer = Vector2.One * (MinimapScale / 2.25f) * 0.75f;
var airlockLines = new ValueList<Vector2>();
var foobarVec = new Vector2(1, -1);
foreach (var airlock in _navMap.Airlocks)
{
var position = airlock.Position - offset;
position = Scale(position with { Y = -position.Y });
airlockLines.Add(position + airlockBuffer);
airlockLines.Add(position - airlockBuffer * foobarVec);
airlockLines.Add(position + airlockBuffer);
airlockLines.Add(position + airlockBuffer * foobarVec);
airlockLines.Add(position - airlockBuffer);
airlockLines.Add(position + airlockBuffer * foobarVec);
airlockLines.Add(position - airlockBuffer);
airlockLines.Add(position - airlockBuffer * foobarVec);
airlockLines.Add(position + airlockBuffer * -Vector2.UnitY);
airlockLines.Add(position - airlockBuffer * -Vector2.UnitY);
}
if (airlockLines.Count > 0)
{
if (!_sRGBLookUp.TryGetValue(WallColor, out var sRGB))
{
sRGB = Color.ToSrgb(WallColor);
_sRGBLookUp[WallColor] = sRGB;
}
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, airlockLines.Span, sRGB);
}
if (PostWallDrawingAction != null) if (PostWallDrawingAction != null)
PostWallDrawingAction.Invoke(handle); PostWallDrawingAction.Invoke(handle);

View File

@@ -5,6 +5,7 @@ using Content.Shared.Database;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Pinpointer; using Content.Shared.Pinpointer;
using Content.Shared.Tag; using Content.Shared.Tag;
using Robust.Server.GameObjects;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Map.Components; using Robust.Shared.Map.Components;
using Robust.Shared.Physics; using Robust.Shared.Physics;
@@ -20,6 +21,7 @@ public sealed class NavMapSystem : SharedNavMapSystem
[Dependency] private readonly IAdminLogManager _adminLog = default!; [Dependency] private readonly IAdminLogManager _adminLog = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly TagSystem _tags = default!; [Dependency] private readonly TagSystem _tags = default!;
[Dependency] private readonly MapSystem _map = default!;
private EntityQuery<PhysicsComponent> _physicsQuery; private EntityQuery<PhysicsComponent> _physicsQuery;
private EntityQuery<TagComponent> _tagQuery; private EntityQuery<TagComponent> _tagQuery;
@@ -41,6 +43,9 @@ public sealed class NavMapSystem : SharedNavMapSystem
SubscribeLocalEvent<NavMapBeaconComponent, ComponentStartup>(OnNavMapBeaconStartup); SubscribeLocalEvent<NavMapBeaconComponent, ComponentStartup>(OnNavMapBeaconStartup);
SubscribeLocalEvent<NavMapBeaconComponent, AnchorStateChangedEvent>(OnNavMapBeaconAnchor); SubscribeLocalEvent<NavMapBeaconComponent, AnchorStateChangedEvent>(OnNavMapBeaconAnchor);
SubscribeLocalEvent<NavMapDoorComponent, ComponentStartup>(OnNavMapDoorStartup);
SubscribeLocalEvent<NavMapDoorComponent, AnchorStateChangedEvent>(OnNavMapDoorAnchor);
SubscribeLocalEvent<ConfigurableNavMapBeaconComponent, NavMapBeaconConfigureBuiMessage>(OnConfigureMessage); SubscribeLocalEvent<ConfigurableNavMapBeaconComponent, NavMapBeaconConfigureBuiMessage>(OnConfigureMessage);
SubscribeLocalEvent<ConfigurableNavMapBeaconComponent, MapInitEvent>(OnConfigurableMapInit); SubscribeLocalEvent<ConfigurableNavMapBeaconComponent, MapInitEvent>(OnConfigurableMapInit);
SubscribeLocalEvent<ConfigurableNavMapBeaconComponent, ExaminedEvent>(OnConfigurableExamined); SubscribeLocalEvent<ConfigurableNavMapBeaconComponent, ExaminedEvent>(OnConfigurableExamined);
@@ -63,6 +68,16 @@ public sealed class NavMapSystem : SharedNavMapSystem
RefreshNavGrid(uid); RefreshNavGrid(uid);
} }
private void OnNavMapDoorStartup(Entity<NavMapDoorComponent> ent, ref ComponentStartup args)
{
RefreshNavGrid(ent);
}
private void OnNavMapDoorAnchor(Entity<NavMapDoorComponent> ent, ref AnchorStateChangedEvent args)
{
RefreshNavGrid(ent);
}
private void OnConfigureMessage(Entity<ConfigurableNavMapBeaconComponent> ent, ref NavMapBeaconConfigureBuiMessage args) private void OnConfigureMessage(Entity<ConfigurableNavMapBeaconComponent> ent, ref NavMapBeaconConfigureBuiMessage args)
{ {
if (args.Session.AttachedEntity is not { } user) if (args.Session.AttachedEntity is not { } user)
@@ -190,6 +205,9 @@ public sealed class NavMapSystem : SharedNavMapSystem
private void OnGetState(EntityUid uid, NavMapComponent component, ref ComponentGetState args) private void OnGetState(EntityUid uid, NavMapComponent component, ref ComponentGetState args)
{ {
if (!TryComp<MapGridComponent>(uid, out var mapGrid))
return;
var data = new Dictionary<Vector2i, int>(component.Chunks.Count); var data = new Dictionary<Vector2i, int>(component.Chunks.Count);
foreach (var (index, chunk) in component.Chunks) foreach (var (index, chunk) in component.Chunks)
{ {
@@ -222,11 +240,45 @@ public sealed class NavMapSystem : SharedNavMapSystem
beacons.Add(new NavMapBeacon(beacon.Color, name, xform.LocalPosition)); beacons.Add(new NavMapBeacon(beacon.Color, name, xform.LocalPosition));
} }
var airlockQuery = EntityQueryEnumerator<NavMapDoorComponent, TransformComponent>();
var airlocks = new List<NavMapAirlock>();
while (airlockQuery.MoveNext(out _, out _, out var xform))
{
if (xform.GridUid != uid || !xform.Anchored)
continue;
var pos = _map.TileIndicesFor(uid, mapGrid, xform.Coordinates);
var enumerator = _map.GetAnchoredEntitiesEnumerator(uid, mapGrid, pos);
var wallPresent = false;
while (enumerator.MoveNext(out var ent))
{
if (!_physicsQuery.TryGetComponent(ent, out var body) ||
!body.CanCollide ||
!body.Hard ||
body.BodyType != BodyType.Static ||
!_tags.HasTag(ent.Value, "Wall", _tagQuery) &&
!_tags.HasTag(ent.Value, "Window", _tagQuery))
{
continue;
}
wallPresent = true;
break;
}
if (wallPresent)
continue;
airlocks.Add(new NavMapAirlock(xform.LocalPosition));
}
// TODO: Diffs // TODO: Diffs
args.State = new NavMapComponentState() args.State = new NavMapComponentState()
{ {
TileData = data, TileData = data,
Beacons = beacons, Beacons = beacons,
Airlocks = airlocks
}; };
} }
@@ -286,8 +338,8 @@ public sealed class NavMapSystem : SharedNavMapSystem
!body.CanCollide || !body.CanCollide ||
!body.Hard || !body.Hard ||
body.BodyType != BodyType.Static || body.BodyType != BodyType.Static ||
(!_tags.HasTag(ent.Value, "Wall", _tagQuery) && !_tags.HasTag(ent.Value, "Wall", _tagQuery) &&
!_tags.HasTag(ent.Value, "Window", _tagQuery))) !_tags.HasTag(ent.Value, "Window", _tagQuery))
{ {
continue; continue;
} }

View File

@@ -16,6 +16,8 @@ public sealed partial class NavMapComponent : Component
public readonly Dictionary<Vector2i, NavMapChunk> Chunks = new(); public readonly Dictionary<Vector2i, NavMapChunk> Chunks = new();
[ViewVariables] public readonly List<SharedNavMapSystem.NavMapBeacon> Beacons = new(); [ViewVariables] public readonly List<SharedNavMapSystem.NavMapBeacon> Beacons = new();
[ViewVariables] public readonly List<SharedNavMapSystem.NavMapAirlock> Airlocks = new();
} }
public sealed class NavMapChunk public sealed class NavMapChunk

View File

@@ -0,0 +1,13 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Pinpointer;
/// <summary>
/// This is used for objects which appear as doors on the navmap.
/// </summary>
[RegisterComponent, NetworkedComponent]
[Access(typeof(SharedNavMapSystem))]
public sealed partial class NavMapDoorComponent : Component
{
}

View File

@@ -37,8 +37,13 @@ public abstract class SharedNavMapSystem : EntitySystem
public Dictionary<Vector2i, int> TileData = new(); public Dictionary<Vector2i, int> TileData = new();
public List<NavMapBeacon> Beacons = new(); public List<NavMapBeacon> Beacons = new();
public List<NavMapAirlock> Airlocks = new();
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]
public readonly record struct NavMapBeacon(Color Color, string Text, Vector2 Position); public readonly record struct NavMapBeacon(Color Color, string Text, Vector2 Position);
[Serializable, NetSerializable]
public readonly record struct NavMapAirlock(Vector2 Position);
} }

View File

@@ -64,6 +64,7 @@
- type: Weldable - type: Weldable
time: 3 time: 3
- type: Airlock - type: Airlock
- type: NavMapDoor
- type: DoorBolt - type: DoorBolt
- type: Appearance - type: Appearance
- type: WiresVisuals - type: WiresVisuals

View File

@@ -57,6 +57,7 @@
- type: Weldable - type: Weldable
time: 10 time: 10
- type: Airlock - type: Airlock
- type: NavMapDoor
- type: DoorBolt - type: DoorBolt
- type: AccessReader - type: AccessReader
- type: Appearance - type: Appearance

View File

@@ -57,10 +57,17 @@
mode: NoSprite mode: NoSprite
- type: Occluder - type: Occluder
- type: entity
parent: BaseMaterialDoor
id: BaseMaterialDoorNavMap
abstract: true
components:
- type: NavMapDoor
- type: entity - type: entity
id: MetalDoor id: MetalDoor
name: metal door name: metal door
parent: BaseMaterialDoor parent: BaseMaterialDoorNavMap
components: components:
- type: Construction - type: Construction
graph: DoorGraph graph: DoorGraph
@@ -69,7 +76,7 @@
- type: entity - type: entity
id: WoodDoor id: WoodDoor
name: wooden door name: wooden door
parent: BaseMaterialDoor parent: BaseMaterialDoorNavMap
description: A door, where will it lead? description: A door, where will it lead?
components: components:
- type: Sprite - type: Sprite
@@ -106,7 +113,7 @@
- type: entity - type: entity
id: PaperDoor id: PaperDoor
name: paper door name: paper door
parent: WoodDoor parent: BaseMaterialDoorNavMap
description: A door, where will it lead? description: A door, where will it lead?
components: components:
- type: Sprite - type: Sprite
@@ -129,7 +136,7 @@
- type: entity - type: entity
id: PlasmaDoor id: PlasmaDoor
name: plasma door name: plasma door
parent: BaseMaterialDoor parent: BaseMaterialDoorNavMap
description: A door, where will it lead? description: A door, where will it lead?
components: components:
- type: Sprite - type: Sprite
@@ -155,7 +162,7 @@
- type: entity - type: entity
id: GoldDoor id: GoldDoor
name: gold door name: gold door
parent: BaseMaterialDoor parent: BaseMaterialDoorNavMap
description: A door, where will it lead? description: A door, where will it lead?
components: components:
- type: Sprite - type: Sprite
@@ -170,7 +177,7 @@
- type: entity - type: entity
id: SilverDoor id: SilverDoor
name: silver door name: silver door
parent: BaseMaterialDoor parent: BaseMaterialDoorNavMap
description: A door, where will it lead? description: A door, where will it lead?
components: components:
- type: Sprite - type: Sprite
@@ -185,7 +192,7 @@
- type: entity - type: entity
id: BananiumDoor id: BananiumDoor
name: bananium door name: bananium door
parent: BaseMaterialDoor parent: BaseMaterialDoorNavMap
description: A door, where will it lead? description: A door, where will it lead?
components: components:
- type: Sprite - type: Sprite
@@ -205,7 +212,7 @@
- type: entity - type: entity
id: WebDoor id: WebDoor
name: web door name: web door
parent: BaseMaterialDoor parent: BaseMaterialDoorNavMap
description: A door, leading to the lands of the spiders... or a spaced room. description: A door, leading to the lands of the spiders... or a spaced room.
components: components:
- type: Sprite - type: Sprite

View File

@@ -57,6 +57,10 @@
- type: ContainerFill - type: ContainerFill
containers: containers:
battery-container: [ PowerCellMedium ] battery-container: [ PowerCellMedium ]
- type: Tag
tags:
- Structure
- Wall
- type: ContainerContainer - type: ContainerContainer
containers: containers:
battery-container: !type:Container battery-container: !type:Container

View File

@@ -32,6 +32,7 @@
- type: ContainerContainer - type: ContainerContainer
containers: containers:
board: !type:Container board: !type:Container
- type: NavMapDoor
- type: Door - type: Door
openDrawDepth: BlastDoors openDrawDepth: BlastDoors
closedDrawDepth: BlastDoors closedDrawDepth: BlastDoors

View File

@@ -112,6 +112,7 @@
openUnlitVisible: true openUnlitVisible: true
# needed so that windoors will close regardless of whether there are people in it; it doesn't crush after all # needed so that windoors will close regardless of whether there are people in it; it doesn't crush after all
safety: false safety: false
- type: NavMapDoor
- type: DoorBolt - type: DoorBolt
- type: Electrified - type: Electrified
enabled: false enabled: false