Skip to content

Commit

Permalink
New event: Approaching unknown shuttle (space-wizards#24490)
Browse files Browse the repository at this point in the history
* setup codebase

* Add first shuttle

* tak

* sync striker

* sync 2

* pipipi

* Preloaded roundstart shuttles!

* Make it abstract "PreloaderGrid" not "PreloaderShuttle"

* to do

* added china cuisin shuttle

* fixes

* add disaster evacpod

* remove enemy

* final shuttles

* weight 5 -> 10

* move data to component

* remove autotrailer touching

* doc, respath

* fix frozen positioning

* fixes + cvar

* finally

* fix evacpod

* remove blacklistrules

* remove `UnknownShuttleSpawnRule`, refactor `LoadMapRule` to support preloaded grids

* use tryload

* cleanup

* fixes

* use preloadedgrid for loneops

* weight unknown shuttles differently (preliminal)

* leftover

* cleanup and raffling

* partial review

* singleton gridpreloader no station coupling

* fix grid atmoses

* `roleLoadout` support for `LoadoutComponent`, fix missing gear

* weighting changes

* init logic fix

---------

Co-authored-by: Kara <[email protected]>
  • Loading branch information
TheShuEd and mirrorcult authored May 10, 2024
1 parent d061aa4 commit e522bbf
Show file tree
Hide file tree
Showing 30 changed files with 8,252 additions and 47 deletions.
1 change: 1 addition & 0 deletions Content.IntegrationTests/PoolManager.Cvars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ private static readonly (string cvar, string value)[] TestCvars =
(CVars.ThreadParallelCount.Name, "1"),
(CCVars.GameRoleTimers.Name, "false"),
(CCVars.GridFill.Name, "false"),
(CCVars.PreloadGrids.Name, "false"),
(CCVars.ArrivalsShuttles.Name, "false"),
(CCVars.EmergencyShuttleEnabled.Name, "false"),
(CCVars.ProcgenPreload.Name, "false"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Content.Server.Maps;
using Content.Shared.GridPreloader.Prototypes;
using Content.Shared.Storage;
using Content.Shared.Whitelist;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
Expand All @@ -16,11 +18,14 @@ public sealed partial class LoadMapRuleComponent : Component
public MapId? Map;

[DataField]
public ProtoId<GameMapPrototype>? GameMap ;
public ProtoId<GameMapPrototype>? GameMap;

[DataField]
public ResPath? MapPath;

[DataField]
public ProtoId<PreloadedGridPrototype>? PreloadedGrid;

[DataField]
public List<EntityUid> MapGrids = new();

Expand Down
34 changes: 31 additions & 3 deletions Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
using Content.Server.Antag;
using Content.Server.GameTicking.Components;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.GridPreloader;
using Content.Server.Spawners.Components;
using Robust.Server.GameObjects;
using Robust.Server.Maps;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;

namespace Content.Server.GameTicking.Rules;

public sealed class LoadMapRuleSystem : GameRuleSystem<LoadMapRuleComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly GridPreloaderSystem _gridPreloader = default!;

public override void Initialize()
{
Expand Down Expand Up @@ -41,7 +46,9 @@ protected override void Added(EntityUid uid, LoadMapRuleComponent comp, GameRule
if (comp.Map != null)
return;

_map.CreateMap(out var mapId);
// grid preloading needs map to init after moving it
var mapUid = comp.PreloadedGrid != null ? _map.CreateMap(out var mapId, false) : _map.CreateMap(out mapId);
_metaData.SetEntityName(mapUid, $"LoadMapRule destination for rule {ToPrettyString(uid)}");
comp.Map = mapId;

if (comp.GameMap != null)
Expand All @@ -51,8 +58,29 @@ protected override void Added(EntityUid uid, LoadMapRuleComponent comp, GameRule
}
else if (comp.MapPath != null)
{
if (_mapLoader.TryLoad(comp.Map.Value, comp.MapPath.Value.ToString(), out var roots, new MapLoadOptions { LoadMap = true }))
comp.MapGrids.AddRange(roots);
if (!_mapLoader.TryLoad(comp.Map.Value,
comp.MapPath.Value.ToString(),
out var roots,
new MapLoadOptions { LoadMap = true }))
{
_mapManager.DeleteMap(mapId);
return;
}

comp.MapGrids.AddRange(roots);
}
else if (comp.PreloadedGrid != null)
{
// TODO: If there are no preloaded grids left, any rule announcements will still go off!
if (!_gridPreloader.TryGetPreloadedGrid(comp.PreloadedGrid.Value, out var loadedShuttle))
{
_mapManager.DeleteMap(mapId);
return;
}

_transform.SetParent(loadedShuttle.Value, mapUid);
comp.MapGrids.Add(loadedShuttle.Value);
_map.InitializeMap(mapId);
}
else
{
Expand Down
16 changes: 16 additions & 0 deletions Content.Server/GridPreloader/GridPreloaderComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Content.Shared.GridPreloader.Prototypes;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;

namespace Content.Server.GridPreloader;

/// <summary>
/// Component storing data about preloaded grids and their location
/// Goes on the map entity
/// </summary>
[RegisterComponent, Access(typeof(GridPreloaderSystem))]
public sealed partial class GridPreloaderComponent : Component
{
[DataField]
public Dictionary<ProtoId<PreloadedGridPrototype>, List<EntityUid>> PreloadedGrids = new();
}
147 changes: 147 additions & 0 deletions Content.Server/GridPreloader/GridPreloaderSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.CCVar;
using Content.Shared.GridPreloader.Prototypes;
using Content.Shared.GridPreloader.Systems;
using Robust.Server.GameObjects;
using Robust.Server.Maps;
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;

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!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
SubscribeLocalEvent<PostGameMapLoad>(OnPostGameMapLoad);
}

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 (!_cfg.GetCVar(CCVars.PreloadGrids))
return;

var mapUid = _map.CreateMap(out var mapId, false);
var preloader = EnsureComp<GridPreloaderComponent>(mapUid);
_meta.SetEntityName(mapUid, "GridPreloader Map");
_map.SetPaused(mapId, true);

var globalXOffset = 0f;
foreach (var proto in _prototype.EnumeratePrototypes<PreloadedGridPrototype>())
{
for (var i = 0; i < proto.Copies; i++)
{
var options = new MapLoadOptions
{
LoadMap = false,
};

if (!_mapLoader.TryLoad(mapId, proto.Path.ToString(), out var roots, options))
continue;

// only supports loading maps with one grid.
if (roots.Count != 1)
continue;

var gridUid = roots[0];

// gets grid + also confirms that the root we loaded is actually a grid
if (!TryComp<MapGridComponent>(gridUid, out var mapGrid))
continue;

if (!TryComp<PhysicsComponent>(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);
}
}
}

/// <summary>
/// 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)
/// </summary>
/// <returns></returns>
public Entity<GridPreloaderComponent>? GetPreloaderEntity()
{
var query = AllEntityQuery<GridPreloaderComponent>();
while (query.MoveNext(out var uid, out var comp))
{
return (uid, comp);
}

return null;
}

/// <summary>
/// An attempt to get a certain preloaded shuttle. If there are no more such shuttles left, returns null
/// </summary>
[PublicAPI]
public bool TryGetPreloadedGrid(ProtoId<PreloadedGridPrototype> 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;
}
}
22 changes: 1 addition & 21 deletions Content.Server/Station/Systems/StationSpawningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,27 +200,7 @@ public EntityUid SpawnPlayerMob(
loadout.SetDefault(_prototypeManager);
}

// Order loadout selections by the order they appear on the prototype.
foreach (var group in loadout.SelectedLoadouts.OrderBy(x => roleProto.Groups.FindIndex(e => e == x.Key)))
{
foreach (var items in group.Value)
{
if (!_prototypeManager.TryIndex(items.Prototype, out var loadoutProto))
{
Log.Error($"Unable to find loadout prototype for {items.Prototype}");
continue;
}

if (!_prototypeManager.TryIndex(loadoutProto.Equipment, out var startingGear))
{
Log.Error($"Unable to find starting gear {loadoutProto.Equipment} for loadout {loadoutProto}");
continue;
}

// Handle any extra data here.
EquipStartingGear(entity.Value, startingGear, raiseEvent: false);
}
}
EquipRoleLoadout(entity.Value, loadout, roleProto);
}

var gearEquippedEv = new StartingGearEquippedEvent(entity.Value);
Expand Down
26 changes: 13 additions & 13 deletions Content.Server/StationEvents/Components/StationEventComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Robust.Shared.Audio;
using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Server.StationEvents.Components;
Expand All @@ -15,49 +15,49 @@ public sealed partial class StationEventComponent : Component
public const float WeightHigh = 15.0f;
public const float WeightVeryHigh = 20.0f;

[DataField("weight")]
[DataField]
public float Weight = WeightNormal;

[DataField("startAnnouncement")]
[DataField]
public string? StartAnnouncement;

[DataField("endAnnouncement")]
[DataField]
public string? EndAnnouncement;

[DataField("startAudio")]
[DataField]
public SoundSpecifier? StartAudio;

[DataField("endAudio")]
[DataField]
public SoundSpecifier? EndAudio;

/// <summary>
/// In minutes, when is the first round time this event can start
/// </summary>
[DataField("earliestStart")]
[DataField]
public int EarliestStart = 5;

/// <summary>
/// In minutes, the amount of time before the same event can occur again
/// </summary>
[DataField("reoccurrenceDelay")]
[DataField]
public int ReoccurrenceDelay = 30;

/// <summary>
/// How long after being added does the event start
/// </summary>
[DataField("startDelay")]
[DataField]
public TimeSpan StartDelay = TimeSpan.Zero;

/// <summary>
/// How long the event lasts.
/// </summary>
[DataField("duration")]
[DataField]
public TimeSpan? Duration = TimeSpan.FromSeconds(1);

/// <summary>
/// The max amount of time the event lasts.
/// </summary>
[DataField("maxDuration")]
[DataField]
public TimeSpan? MaxDuration;

/// <summary>
Expand All @@ -66,13 +66,13 @@ public sealed partial class StationEventComponent : Component
/// <remarks>
/// To avoid running deadly events with low-pop
/// </remarks>
[DataField("minimumPlayers")]
[DataField]
public int MinimumPlayers;

/// <summary>
/// How many times this even can occur in a single round
/// </summary>
[DataField("maxOccurrences")]
[DataField]
public int? MaxOccurrences;

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/StationEvents/Events/StationEventSystem.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Chat.Systems;
using Content.Server.GameTicking.Components;
Expand Down Expand Up @@ -42,6 +43,7 @@ protected override void Added(EntityUid uid, T component, GameRuleComponent game
if (!TryComp<StationEventComponent>(uid, out var stationEvent))
return;


AdminLogManager.Add(LogType.EventAnnounced, $"Event added / announced: {ToPrettyString(uid)}");

if (stationEvent.StartAnnouncement != null)
Expand Down
Loading

0 comments on commit e522bbf

Please sign in to comment.