using System.Diagnostics.CodeAnalysis; using Content.Shared.CCVar; using Content.Shared.GridPreloader.Prototypes; using Content.Shared.GridPreloader.Systems; using Robust.Server.GameObjects; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; using Robust.Shared.Prototypes; using System.Numerics; using Content.Server.GameTicking; using Content.Shared.GameTicking; using JetBrains.Annotations; using Robust.Shared.EntitySerialization.Systems; namespace Content.Server.GridPreloader; public sealed class GridPreloaderSystem : SharedGridPreloaderSystem { [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly MapSystem _map = default!; [Dependency] private readonly MapLoaderSystem _mapLoader = default!; [Dependency] private readonly MetaDataSystem _meta = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; /// /// Whether the preloading CVar is set or not. /// public bool PreloadingEnabled; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnRoundRestart); SubscribeLocalEvent(OnPostGameMapLoad); Subs.CVar(_cfg, CCVars.PreloadGrids, value => PreloadingEnabled = value, true); } private void OnRoundRestart(RoundRestartCleanupEvent ev) { var ent = GetPreloaderEntity(); if (ent == null) return; Del(ent.Value.Owner); } private void OnPostGameMapLoad(PostGameMapLoad ev) { EnsurePreloadedGridMap(); } private void EnsurePreloadedGridMap() { // Already have a preloader? if (GetPreloaderEntity() != null) return; if (!PreloadingEnabled) return; var mapUid = _map.CreateMap(out var mapId, false); var preloader = EnsureComp(mapUid); _meta.SetEntityName(mapUid, "GridPreloader Map"); _map.SetPaused(mapId, true); var globalXOffset = 0f; foreach (var proto in _prototype.EnumeratePrototypes()) { for (var i = 0; i < proto.Copies; i++) { if (!_mapLoader.TryLoadGrid(mapId, proto.Path, out var grid)) { Log.Error($"Failed to preload grid prototype {proto.ID}"); continue; } var (gridUid, mapGrid) = grid.Value; if (!TryComp(gridUid, out var physics)) continue; // Position Calculating globalXOffset += mapGrid.LocalAABB.Width / 2; var coords = new Vector2(-physics.LocalCenter.X + globalXOffset, -physics.LocalCenter.Y); _transform.SetCoordinates(gridUid, new EntityCoordinates(mapUid, coords)); globalXOffset += (mapGrid.LocalAABB.Width / 2) + 1; // Add to list if (!preloader.PreloadedGrids.ContainsKey(proto.ID)) preloader.PreloadedGrids[proto.ID] = new(); preloader.PreloadedGrids[proto.ID].Add(gridUid); } } } /// /// Should be a singleton no matter station count, so we can assume 1 /// (better support for singleton component in engine at some point i guess) /// /// public Entity? GetPreloaderEntity() { var query = AllEntityQuery(); while (query.MoveNext(out var uid, out var comp)) { return (uid, comp); } return null; } /// /// An attempt to get a certain preloaded shuttle. If there are no more such shuttles left, returns null /// [PublicAPI] public bool TryGetPreloadedGrid(ProtoId proto, [NotNullWhen(true)] out EntityUid? preloadedGrid, GridPreloaderComponent? preloader = null) { preloadedGrid = null; if (preloader == null) { preloader = GetPreloaderEntity(); if (preloader == null) return false; } if (!preloader.PreloadedGrids.TryGetValue(proto, out var list) || list.Count <= 0) return false; preloadedGrid = list[0]; list.RemoveAt(0); if (list.Count == 0) preloader.PreloadedGrids.Remove(proto); return true; } }