]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add navmap beacons (#19388)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Sat, 16 Sep 2023 08:11:47 +0000 (18:11 +1000)
committerGitHub <noreply@github.com>
Sat, 16 Sep 2023 08:11:47 +0000 (18:11 +1000)
Content.Client/Pinpointer/NavMapSystem.cs
Content.Client/Pinpointer/UI/NavMapControl.cs
Content.Server/Pinpointer/NavMapSystem.cs
Content.Shared/Pinpointer/NavMapBeaconComponent.cs [new file with mode: 0644]
Content.Shared/Pinpointer/NavMapComponent.cs
Content.Shared/Pinpointer/SharedNavMapSystem.cs
Resources/Prototypes/Entities/Markers/warp_point.yml

index 6556aeaf99cf3b647295c3e9a7045f70c2f4e9a6..35b0a32b56aaa1eca037685532c04f1c52a7c5d7 100644 (file)
@@ -29,6 +29,9 @@ public sealed class NavMapSystem : SharedNavMapSystem
                 TileData = data,
             });
         }
+
+        component.Beacons.Clear();
+        component.Beacons.AddRange(state.Beacons);
     }
 }
 
index bd61587e8bdd86814915ca1534468df3f1be0d1e..04d8cc76f9b2331948a7057a659680b2569c1847 100644 (file)
@@ -2,7 +2,9 @@ using System.Numerics;
 using Content.Client.Stylesheets;
 using Content.Client.UserInterface.Controls;
 using Content.Shared.Pinpointer;
+using Robust.Client.GameObjects;
 using Robust.Client.Graphics;
+using Robust.Client.ResourceManagement;
 using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 using Robust.Shared.Input;
@@ -20,18 +22,19 @@ namespace Content.Client.Pinpointer.UI;
 public sealed class NavMapControl : MapGridControl
 {
     [Dependency] private readonly IEntityManager _entManager = default!;
+    private SharedTransformSystem _transform;
 
     public EntityUid? MapUid;
 
-
     public Dictionary<EntityCoordinates, (bool Visible, Color Color)> TrackedCoordinates = new();
 
     private Vector2 _offset;
     private bool _draggin;
-
     private bool _recentering = false;
-
-    private float _recenterMinimum = 0.05f;
+    private readonly float _recenterMinimum = 0.05f;
+    private readonly Font _font;
+    private static readonly Color TileColor = new(30, 67, 30);
+    private static readonly Color BeaconColor = Color.FromSrgb(TileColor.WithAlpha(0.8f));
 
     // TODO: https://github.com/space-wizards/RobustToolbox/issues/3818
     private readonly Label _zoom = new()
@@ -52,6 +55,11 @@ public sealed class NavMapControl : MapGridControl
     public NavMapControl() : base(8f, 128f, 48f)
     {
         IoCManager.InjectDependencies(this);
+
+        _transform = _entManager.System<SharedTransformSystem>();
+        var cache = IoCManager.Resolve<IResourceCache>();
+        _font = new VectorFont(cache.GetResource<FontResource>("/EngineFonts/NotoSans/NotoSans-Regular.ttf"), 16);
+
         RectClipContent = true;
         HorizontalExpand = true;
         VerticalExpand = true;
@@ -175,7 +183,6 @@ public sealed class NavMapControl : MapGridControl
         }
 
         var offset = _offset;
-        var tileColor = new Color(30, 67, 30);
         var lineColor = new Color(102, 217, 102);
 
         if (_entManager.TryGetComponent<PhysicsComponent>(MapUid, out var physics))
@@ -200,7 +207,7 @@ public sealed class NavMapControl : MapGridControl
                     verts[i] = Scale(new Vector2(vert.X, -vert.Y));
                 }
 
-                handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts[..poly.VertexCount], tileColor);
+                handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts[..poly.VertexCount], TileColor);
             }
         }
 
@@ -333,6 +340,24 @@ public sealed class NavMapControl : MapGridControl
                 }
             }
         }
+
+        // Beacons
+        var labelOffset = new Vector2(0.5f, 0.5f) * MinimapScale;
+        var rectBuffer = new Vector2(5f, 3f);
+
+        foreach (var beacon in navMap.Beacons)
+        {
+            var position = beacon.Position - offset;
+
+            position = Scale(position with { Y = -position.Y });
+
+            handle.DrawCircle(position, MinimapScale / 2f, beacon.Color);
+            var textDimensions = handle.GetDimensions(_font, beacon.Text, 1f);
+
+            var labelPosition = position + labelOffset;
+            handle.DrawRect(new UIBox2(labelPosition, labelPosition + textDimensions + rectBuffer * 2), BeaconColor);
+            handle.DrawString(_font, labelPosition + rectBuffer, beacon.Text, beacon.Color);
+        }
     }
 
     private Vector2 Scale(Vector2 position)
index dae3c1ca6641c98657ed7539e8a35855e3d878ba..140f016558b66d1ab942921d17f215e8eeda796e 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Server.Station.Components;
 using Content.Server.Station.Systems;
+using Content.Server.Warps;
 using Content.Shared.Pinpointer;
 using Content.Shared.Tag;
 using Robust.Shared.GameStates;
@@ -16,40 +17,87 @@ public sealed class NavMapSystem : SharedNavMapSystem
 {
     [Dependency] private readonly TagSystem _tags = default!;
 
+    private EntityQuery<PhysicsComponent> _physicsQuery;
+    private EntityQuery<TagComponent> _tagQuery;
+
     public override void Initialize()
     {
         base.Initialize();
+
+        _physicsQuery = GetEntityQuery<PhysicsComponent>();
+        _tagQuery = GetEntityQuery<TagComponent>();
+
         SubscribeLocalEvent<AnchorStateChangedEvent>(OnAnchorChange);
         SubscribeLocalEvent<ReAnchorEvent>(OnReAnchor);
+        SubscribeLocalEvent<StationGridAddedEvent>(OnStationInit);
+        SubscribeLocalEvent<NavMapComponent, ComponentStartup>(OnNavMapStartup);
         SubscribeLocalEvent<NavMapComponent, ComponentGetState>(OnGetState);
         SubscribeLocalEvent<NavMapComponent, GridSplitEvent>(OnNavMapSplit);
-        SubscribeLocalEvent<StationGridAddedEvent>(OnStationInit);
+
+        SubscribeLocalEvent<NavMapBeaconComponent, ComponentStartup>(OnNavMapBeaconStartup);
+        SubscribeLocalEvent<NavMapBeaconComponent, AnchorStateChangedEvent>(OnNavMapBeaconAnchor);
     }
 
     private void OnStationInit(StationGridAddedEvent ev)
     {
         var comp = EnsureComp<NavMapComponent>(ev.GridId);
-        var physicsQuery = GetEntityQuery<PhysicsComponent>();
-        var tagQuery = GetEntityQuery<TagComponent>();
-        RefreshGrid(comp, Comp<MapGridComponent>(ev.GridId), physicsQuery, tagQuery);
+        RefreshGrid(comp, Comp<MapGridComponent>(ev.GridId));
+    }
+
+    private void OnNavMapBeaconStartup(EntityUid uid, NavMapBeaconComponent component, ComponentStartup args)
+    {
+        RefreshNavGrid(uid);
+    }
+
+    private void OnNavMapBeaconAnchor(EntityUid uid, NavMapBeaconComponent component, ref AnchorStateChangedEvent args)
+    {
+        RefreshNavGrid(uid);
+    }
+
+    /// <summary>
+    /// Refreshes the grid for the corresponding beacon.
+    /// </summary>
+    /// <param name="uid"></param>
+    private void RefreshNavGrid(EntityUid uid)
+    {
+        var xform = Transform(uid);
+
+        if (!CanBeacon(uid, xform) || !TryComp<NavMapComponent>(xform.GridUid, out var navMap))
+            return;
+
+        Dirty(xform.GridUid.Value, navMap);
+    }
+
+    private bool CanBeacon(EntityUid uid, TransformComponent? xform = null)
+    {
+        if (!Resolve(uid, ref xform))
+            return false;
+
+        return xform.GridUid != null && xform.Anchored;
+    }
+
+    private void OnNavMapStartup(EntityUid uid, NavMapComponent component, ComponentStartup args)
+    {
+        if (!TryComp<MapGridComponent>(uid, out var grid))
+            return;
+
+        RefreshGrid(component, grid);
     }
 
     private void OnNavMapSplit(EntityUid uid, NavMapComponent component, ref GridSplitEvent args)
     {
-        var physicsQuery = GetEntityQuery<PhysicsComponent>();
-        var tagQuery = GetEntityQuery<TagComponent>();
         var gridQuery = GetEntityQuery<MapGridComponent>();
 
         foreach (var grid in args.NewGrids)
         {
             var newComp = EnsureComp<NavMapComponent>(grid);
-            RefreshGrid(newComp, gridQuery.GetComponent(grid), physicsQuery, tagQuery);
+            RefreshGrid(newComp, gridQuery.GetComponent(grid));
         }
 
-        RefreshGrid(component, gridQuery.GetComponent(uid), physicsQuery, tagQuery);
+        RefreshGrid(component, gridQuery.GetComponent(uid));
     }
 
-    private void RefreshGrid(NavMapComponent component, MapGridComponent grid, EntityQuery<PhysicsComponent> physicsQuery, EntityQuery<TagComponent> tagQuery)
+    private void RefreshGrid(NavMapComponent component, MapGridComponent grid)
     {
         component.Chunks.Clear();
 
@@ -65,7 +113,7 @@ public sealed class NavMapSystem : SharedNavMapSystem
                 component.Chunks[chunkOrigin] = chunk;
             }
 
-            RefreshTile(grid, component, chunk, tile.Value.GridIndices, physicsQuery, tagQuery);
+            RefreshTile(grid, component, chunk, tile.Value.GridIndices);
         }
     }
 
@@ -77,10 +125,37 @@ public sealed class NavMapSystem : SharedNavMapSystem
             data.Add(index, chunk.TileData);
         }
 
+        var beaconQuery = AllEntityQuery<NavMapBeaconComponent, TransformComponent>();
+        var beacons = new List<NavMapBeacon>();
+
+        while (beaconQuery.MoveNext(out var beaconUid, out var beacon, out var xform))
+        {
+            if (xform.GridUid != uid || !CanBeacon(beaconUid, xform))
+                continue;
+
+            // TODO: Make warp points use metadata name instead.
+            string? name = beacon.Text;
+
+            if (name == null)
+            {
+                if (TryComp<WarpPointComponent>(beaconUid, out var warpPoint) && warpPoint.Location != null)
+                {
+                    name = warpPoint.Location;
+                }
+                else
+                {
+                    name = MetaData(beaconUid).EntityName;
+                }
+            }
+
+            beacons.Add(new NavMapBeacon(beacon.Color, name, xform.LocalPosition));
+        }
+
         // TODO: Diffs
         args.State = new NavMapComponentState()
         {
             TileData = data,
+            Beacons = beacons,
         };
     }
 
@@ -93,9 +168,7 @@ public sealed class NavMapSystem : SharedNavMapSystem
 
             if (navMap.Chunks.TryGetValue(chunkOrigin, out var chunk))
             {
-                var physicsQuery = GetEntityQuery<PhysicsComponent>();
-                var tagQuery = GetEntityQuery<TagComponent>();
-                RefreshTile(oldGrid, navMap, chunk, ev.TilePos, physicsQuery, tagQuery);
+                RefreshTile(oldGrid, navMap, chunk, ev.TilePos);
             }
         }
 
@@ -115,8 +188,6 @@ public sealed class NavMapSystem : SharedNavMapSystem
 
         var tile = grid.LocalToTile(xform.Coordinates);
         var chunkOrigin = SharedMapSystem.GetChunkIndices(tile, ChunkSize);
-        var physicsQuery = GetEntityQuery<PhysicsComponent>();
-        var tagQuery = GetEntityQuery<TagComponent>();
 
         if (!navMap.Chunks.TryGetValue(chunkOrigin, out var chunk))
         {
@@ -124,12 +195,10 @@ public sealed class NavMapSystem : SharedNavMapSystem
             navMap.Chunks[chunkOrigin] = chunk;
         }
 
-        RefreshTile(grid, navMap, chunk, tile, physicsQuery, tagQuery);
+        RefreshTile(grid, navMap, chunk, tile);
     }
 
-    private void RefreshTile(MapGridComponent grid, NavMapComponent component, NavMapChunk chunk, Vector2i tile,
-        EntityQuery<PhysicsComponent> physicsQuery,
-        EntityQuery<TagComponent> tagQuery)
+    private void RefreshTile(MapGridComponent grid, NavMapComponent component, NavMapChunk chunk, Vector2i tile)
     {
         var relative = SharedMapSystem.GetChunkRelative(tile, ChunkSize);
 
@@ -143,12 +212,12 @@ public sealed class NavMapSystem : SharedNavMapSystem
 
         while (enumerator.MoveNext(out var ent))
         {
-            if (!physicsQuery.TryGetComponent(ent, out var body) ||
+            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)))
+                (!_tags.HasTag(ent.Value, "Wall", _tagQuery) &&
+                 !_tags.HasTag(ent.Value, "Window", _tagQuery)))
             {
                 continue;
             }
diff --git a/Content.Shared/Pinpointer/NavMapBeaconComponent.cs b/Content.Shared/Pinpointer/NavMapBeaconComponent.cs
new file mode 100644 (file)
index 0000000..dfe958d
--- /dev/null
@@ -0,0 +1,19 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Pinpointer;
+
+/// <summary>
+/// Will show a marker on a NavMap.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class NavMapBeaconComponent : Component
+{
+    /// <summary>
+    /// Defaults to entity name if nothing found.
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite), DataField("text"), AutoNetworkedField]
+    public string? Text;
+
+    [ViewVariables(VVAccess.ReadWrite), DataField("color"), AutoNetworkedField]
+    public Color Color = Color.Orange;
+}
index 3291114b5d16c916b14126e4570f68535894821e..86a0beef18a55b13f2aa12ba7e8f9624ff125c5e 100644 (file)
@@ -9,8 +9,14 @@ namespace Content.Shared.Pinpointer;
 [RegisterComponent, NetworkedComponent]
 public sealed partial class NavMapComponent : Component
 {
+    /*
+     * Don't need DataFields as this can be reconstructed
+     */
+
     [ViewVariables]
     public readonly Dictionary<Vector2i, NavMapChunk> Chunks = new();
+
+    [ViewVariables] public readonly List<SharedNavMapSystem.NavMapBeacon> Beacons = new();
 }
 
 public sealed class NavMapChunk
index 3601ae9dfa2543655edf905741c504c921b2a697..3f01934a24e3a5c1de5304a4dd8116ae13eb4bf3 100644 (file)
@@ -1,3 +1,4 @@
+using System.Numerics;
 using Robust.Shared.Serialization;
 using Robust.Shared.Utility;
 
@@ -34,12 +35,10 @@ public abstract class SharedNavMapSystem : EntitySystem
     protected sealed class NavMapComponentState : ComponentState
     {
         public Dictionary<Vector2i, int> TileData = new();
+
+        public List<NavMapBeacon> Beacons = new();
     }
 
     [Serializable, NetSerializable]
-    protected sealed class NavMapDiffComponentState : ComponentState
-    {
-        public Dictionary<Vector2i, int> TileData = new();
-        public List<Vector2i> RemovedChunks = new();
-    }
+    public readonly record struct NavMapBeacon(Color Color, string Text, Vector2 Position);
 }
index 54c532d684fb795b030eb7628f4b4f6c7d6f1a0c..22ec3ccc6fcf8726b3350bb213e01590e38a661b 100644 (file)
@@ -7,6 +7,16 @@
   - type: Sprite
     state: pink
 
+- type: entity
+  id: WarpPointBeacon
+  parent: MarkerBase
+  name: warp point (beacon)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+
 - type: entity
   parent: WarpPoint
   id: WarpPointBombing
     - state: pink
     - sprite: Objects/Weapons/Bombs/spidercharge.rsi
       state: icon
+
+# Departments
+- type: entity
+  id: WarpPointBeaconBar
+  parent: MarkerBase
+  name: warp point (bar)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: bar
+      color: "#791500"
+
+- type: entity
+  id: WarpPointBeaconCargo
+  parent: MarkerBase
+  name: warp point (cargo)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: cargo
+      color: "#A46106"
+
+- type: entity
+  id: WarpPointBeaconCommand
+  parent: MarkerBase
+  name: warp point (command)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: command
+      color: "#334E6D"
+
+- type: entity
+  id: WarpPointBeaconEngineering
+  parent: MarkerBase
+  name: warp point (engineering)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: engineering
+      color: "#EFB341"
+
+- type: entity
+  id: WarpPointBeaconMedical
+  parent: MarkerBase
+  name: warp point (medical)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: medical
+      color: "#52B4E9"
+
+- type: entity
+  id: WarpPointBeaconNeutral
+  parent: MarkerBase
+  name: warp point (neutral)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: neutral
+      color: "#D4D4D4"
+
+- type: entity
+  id: WarpPointBeaconScience
+  parent: MarkerBase
+  name: warp point (science)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: science
+      color: "#D381C9"
+
+- type: entity
+  id: WarpPointBeaconService
+  parent: MarkerBase
+  name: warp point (service)
+  components:
+    - type: WarpPoint
+    - type: Sprite
+      state: pink
+    - type: NavMapBeacon
+      text: service
+      color: "#9FED58"