using Content.Shared.GameTicking; using Robust.Shared.Map; namespace Content.Server.Tabletop { public sealed partial class TabletopSystem { /// /// Separation between tabletops in the tabletop map. /// private const int TabletopSeparation = 100; /// /// Map where all tabletops reside. /// public MapId TabletopMap { get; private set; } = MapId.Nullspace; /// /// The number of tabletops created in the map. /// Used for calculating the position of the next one. /// private int _tabletops = 0; /// /// Despite the name, this method is only used to subscribe to events. /// private void InitializeMap() { SubscribeLocalEvent(OnRoundRestart); } /// /// Gets the next available position for a tabletop, and increments the tabletop count. /// /// private Vector2 GetNextTabletopPosition() { return UlamSpiral(_tabletops++) * TabletopSeparation; } /// /// Ensures that the tabletop map exists. Creates it if it doesn't. /// private void EnsureTabletopMap() { if (TabletopMap != MapId.Nullspace && _mapManager.MapExists(TabletopMap)) return; TabletopMap = _mapManager.CreateMap(); _tabletops = 0; var mapComp = EntityManager.GetComponent(_mapManager.GetMapEntityId(TabletopMap)); // Lighting is always disabled in tabletop world. mapComp.LightingEnabled = false; mapComp.Dirty(); } /// /// Algorithm for mapping scalars to 2D positions in the same pattern as an Ulam Spiral. /// /// Scalar to map to a 2D position. /// The mapped 2D position for the scalar. private Vector2i UlamSpiral(int n) { var k = (int)MathF.Ceiling(MathF.Sqrt(n) - 1) / 2; var t = 2 * k + 1; var m = (int)MathF.Pow(t, 2); t--; if (n >= m - t) return new Vector2i(k - (m - n), -k); m -= t; if (n >= m - t) return new Vector2i(-k, -k + (m - n)); m -= t; if (n >= m - t) return new Vector2i(-k + (m - n), k); return new Vector2i(k, k - (m - n - t)); } private void OnRoundRestart(RoundRestartCleanupEvent _) { if (TabletopMap == MapId.Nullspace || !_mapManager.MapExists(TabletopMap)) return; // This will usually *not* be the case, but better make sure. _mapManager.DeleteMap(TabletopMap); // Reset tabletop count. _tabletops = 0; } } }