StationSystem/jobs/partial spawning refactor (#7580)

* Partial work on StationSystem refactor.

* WIP station jobs API.

* forgor to fire off grid events.

* Partial implementation of StationSpawningSystem

* whoops infinite loop.

* Spawners should work now.

* it compiles.

* tfw

* Vestigial code cleanup.

* fix station deletion.

* attempt to make tests go brr

* add latejoin spawnpoints to test maps.

* make sure the station still exists while destructing spawners.

* forgot an exists check.

* destruction order check.

* hopefully fix final test.

* fail-safe radstorm.

* Deep-clean job code further. This is bugged!!!!!

* Fix job bug. (init order moment)

* whooo cleanup

* New job selection algorithm that tries to distribute fairly across stations.

* small nitpicks

* Give the heads their weights to replace the head field.

* make overflow assign take a station list.

* moment

* Fixes and test #1 of many.

* please fix nullspace

* AssignJobs should no longer even consider showing up on a trace.

* add comment.

* Introduce station configs, praying i didn't miss something.

* in one small change stations are now fully serializable.

* Further doc comments.

* whoops.

* Solve bug where assignjobs didn't account for roundstart.

* Fix spawning, improve the API.
Caught an oversight in stationsystem that should've broke everything but didn't, whoops.

* Goodbye JobController.

* minor fix..

* fix test fail, remove debug logs.

* quick serialization fixes.

* fixes..

* sus

* partialing

* Update Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs

Co-authored-by: Kara <lunarautomaton6@gmail.com>

* Use dirtying to avoid rebuilding the list 2,100 times.

* add a bajillion more lines of docs (mostly in AssignJobs so i don't ever forget how it works)

* Update Content.IntegrationTests/Tests/Station/StationJobsTest.cs

Co-authored-by: Kara <lunarautomaton6@gmail.com>

* Add the Mysteriously Missing Captain Check.

* Put maprender back the way it belongs.

* I love addressing reviews.

* Update Content.Server/Station/Systems/StationJobsSystem.cs

Co-authored-by: Kara <lunarautomaton6@gmail.com>

* doc cleanup.

* Fix bureaucratic error, add job slot tests.

* zero cost abstractions when

* cri

* saner error.

* Fix spawning failing certain tests due to gameticker not handling falliability correctly.
Can't fix this until I refactor the rest of spawning code.

* submodule gaming

* Packedenger.

* Documentation consistency.

Co-authored-by: Kara <lunarautomaton6@gmail.com>
This commit is contained in:
Moony
2022-05-10 13:43:30 -05:00
committed by GitHub
parent d234a79d28
commit 36181334b5
65 changed files with 2564 additions and 1368 deletions

View File

@@ -1,8 +1,6 @@
using System.Linq;
using Content.Server.Station;
using Content.Shared.Roles;
using Content.Server.Station.Systems;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.StationEvents.Events;
@@ -11,8 +9,7 @@ namespace Content.Server.StationEvents.Events;
public sealed class BureaucraticError : StationEvent
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override string? StartAnnouncement =>
public override string StartAnnouncement =>
Loc.GetString("station-event-bureaucratic-error-announcement");
public override string Name => "BureaucraticError";
@@ -27,20 +24,22 @@ public sealed class BureaucraticError : StationEvent
public override void Startup()
{
base.Startup();
var chosenStation = _random.Pick(EntitySystem.Get<StationSystem>().StationInfo.Values.ToList());
var jobList = chosenStation.JobList.Keys.Where(x => !_prototypeManager.Index<JobPrototype>(x).IsHead).ToList();
var stationSystem = EntitySystem.Get<StationSystem>();
var stationJobsSystem = EntitySystem.Get<StationJobsSystem>();
var chosenStation = _random.Pick(stationSystem.Stations.ToList());
var jobList = stationJobsSystem.GetJobs(chosenStation).Keys.ToList();
// Low chance to completely change up the late-join landscape by closing all positions except infinite slots.
// Lower chance than the /tg/ equivalent of this event.
if (_random.Prob(0.25f))
{
var chosenJob = _random.PickAndTake(jobList);
chosenStation.AdjustJobAmount(chosenJob, -1); // INFINITE chaos.
stationJobsSystem.MakeJobUnlimited(chosenStation, chosenJob); // INFINITE chaos.
foreach (var job in jobList)
{
if (chosenStation.JobList[job] == -1)
if (stationJobsSystem.IsJobUnlimited(chosenStation, job))
continue;
chosenStation.AdjustJobAmount(job, 0);
stationJobsSystem.TrySetJobSlot(chosenStation, job, 0);
}
}
else
@@ -49,11 +48,10 @@ public sealed class BureaucraticError : StationEvent
for (var i = 0; i < _random.Next((int)(jobList.Count * 0.20), (int)(jobList.Count * 0.30)); i++)
{
var chosenJob = _random.PickAndTake(jobList);
if (chosenStation.JobList[chosenJob] == -1)
if (stationJobsSystem.IsJobUnlimited(chosenStation, chosenJob))
continue;
var adj = Math.Max(chosenStation.JobList[chosenJob] + _random.Next(-3, 6), 0);
chosenStation.AdjustJobAmount(chosenJob, adj);
stationJobsSystem.TryAdjustJobSlot(chosenStation, chosenJob, _random.Next(-3, 6));
}
}
}

View File

@@ -1,13 +1,8 @@
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Sound;
using Content.Shared.Station;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Player;
using Robust.Shared.Random;
@@ -60,7 +55,7 @@ namespace Content.Server.StationEvents.Events
// Event variables
private StationId _targetStation;
private EntityUid _targetStation;
private EntityUid _targetGrid;

View File

@@ -1,16 +1,12 @@
using System.Linq;
using Content.Server.Radiation;
using Content.Server.Station;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Coordinates;
using Content.Shared.Sound;
using Content.Shared.Station;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.StationEvents.Events
{
@@ -20,8 +16,11 @@ namespace Content.Server.StationEvents.Events
// Based on Goonstation style radiation storm with some TG elements (announcer, etc.)
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
private StationSystem _stationSystem = default!;
public override string Name => "RadiationStorm";
public override string StartAnnouncement => Loc.GetString("station-event-radiation-storm-start-announcement");
protected override string EndAnnouncement => Loc.GetString("station-event-radiation-storm-end-announcement");
@@ -32,7 +31,7 @@ namespace Content.Server.StationEvents.Events
private float _timeUntilPulse;
private const float MinPulseDelay = 0.2f;
private const float MaxPulseDelay = 0.8f;
private StationId _target = StationId.Invalid;
private EntityUid _target = EntityUid.Invalid;
private void ResetTimeUntilPulse()
{
@@ -47,14 +46,17 @@ namespace Content.Server.StationEvents.Events
public override void Startup()
{
_entityManager.EntitySysManager.Resolve(ref _stationSystem);
ResetTimeUntilPulse();
_target = _robustRandom.Pick(_entityManager.EntityQuery<StationComponent>().ToArray()).Station;
base.Startup();
}
public override void Shutdown()
{
base.Shutdown();
if (_stationSystem.Stations.Count == 0)
{
Running = false;
return;
}
_target = _robustRandom.Pick(_stationSystem.Stations);
base.Startup();
}
public override void Update(float frameTime)
@@ -62,6 +64,11 @@ namespace Content.Server.StationEvents.Events
base.Update(frameTime);
if (!Started || !Running) return;
if (_target.Valid == false)
{
Running = false;
return;
}
_timeUntilPulse -= frameTime;
@@ -69,10 +76,14 @@ namespace Content.Server.StationEvents.Events
{
var mapManager = IoCManager.Resolve<IMapManager>();
// Account for split stations by just randomly picking a piece of it.
var possibleTargets = _entityManager.EntityQuery<StationComponent>()
.Where(x => x.Station == _target).ToArray();
StationComponent tempQualifier = _robustRandom.Pick(possibleTargets);
var stationEnt = (tempQualifier).Owner;
var possibleTargets = _entityManager.GetComponent<StationDataComponent>(_target).Grids;
if (possibleTargets.Count == 0)
{
Running = false;
return;
}
var stationEnt = _robustRandom.Pick(possibleTargets);
if (!_entityManager.TryGetComponent<IMapGridComponent>(stationEnt, out var grid))
return;

View File

@@ -2,15 +2,12 @@ using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Chat.Managers;
using Content.Server.Station;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Database;
using Content.Shared.Sound;
using Content.Shared.Station;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Player;
using Robust.Shared.Random;
@@ -189,20 +186,24 @@ namespace Content.Server.StationEvents.Events
}
public static bool TryFindRandomTile(out Vector2i tile, out StationId targetStation, out EntityUid targetGrid, out EntityCoordinates targetCoords, IRobustRandom? robustRandom = null, IEntityManager? entityManager = null)
public static bool TryFindRandomTile(out Vector2i tile, out EntityUid targetStation, out EntityUid targetGrid, out EntityCoordinates targetCoords, IRobustRandom? robustRandom = null, IEntityManager? entityManager = null, IMapManager? mapManager = null, StationSystem? stationSystem = null)
{
tile = default;
robustRandom ??= IoCManager.Resolve<IRobustRandom>();
entityManager ??= IoCManager.Resolve<IEntityManager>();
IoCManager.Resolve(ref robustRandom, ref entityManager, ref mapManager);
entityManager.EntitySysManager.Resolve(ref stationSystem);
targetCoords = EntityCoordinates.Invalid;
targetStation = robustRandom.Pick(entityManager.EntityQuery<StationComponent>().ToArray()).Station;
var t = targetStation; // thanks C#
var possibleTargets = entityManager.EntityQuery<StationComponent>()
.Where(x => x.Station == t).ToArray();
targetGrid = robustRandom.Pick(possibleTargets).Owner;
targetStation = robustRandom.Pick(stationSystem.Stations);
var possibleTargets = entityManager.GetComponent<StationDataComponent>(targetStation).Grids;
if (possibleTargets.Count == 0)
{
targetGrid = EntityUid.Invalid;
return false;
}
if (!entityManager.TryGetComponent<IMapGridComponent>(targetGrid!, out var gridComp))
targetGrid = robustRandom.Pick(possibleTargets);
if (!entityManager.TryGetComponent<IMapGridComponent>(targetGrid, out var gridComp))
return false;
var grid = gridComp.Grid;