Refactor how jobs are handed out (#5422)

* Completely refactor how job spawning works

* Remove remains of old system.

* Squash the final bug, cleanup.

* Attempt to fix tests

* Adjusts packed's round-start crew roster, re-enables a bunch of old roles.
Also adds the Central Command Official as a proper role.

* pretty up ui

* refactor StationSystem into the correct folder & namespace.

* remove a log, make sure the lobby gets updated if a new map is spontaneously added.

* re-add accidentally removed log

* We do a little logging

* we do a little resolving

* we do a little documenting

* Renamed OverflowJob to FallbackOverflowJob
Allows stations to configure their own roundstart overflow job list.

* narrator: it did not compile

* oops

* support having no overflow jobs

* filescope for consistency

* small fixes

* Bumps a few role counts for Packed, namely engis

* log moment

* E

* Update Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml

Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>

* Update Content.Server/Maps/GameMapPrototype.cs

Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>

* factored job logic, cleanup.

* e

* Address reviews

* Remove the concept of a "default" grid.
It has no future in our new multi-station world

* why was clickable using that in the first place

* fix bad evil bug that almost slipped through
also adds chemist

* rms obsolete things from chemist

* Adds a sanity fallback

* address reviews

* adds ability to set name

* fuck

* cleanup joingame
This commit is contained in:
Moony
2021-11-26 03:02:46 -06:00
committed by GitHub
parent dfb329d5db
commit ec68226e99
53 changed files with 1148 additions and 705 deletions

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Content.Server.Access.Components;
using Content.Server.Access.Systems;
using Content.Server.CharacterAppearance.Components;
using Content.Server.Ghost;
using Content.Server.Ghost.Components;
using Content.Server.Hands.Components;
@@ -14,12 +14,15 @@ using Content.Server.Players;
using Content.Server.Roles;
using Content.Server.Spawners.Components;
using Content.Server.Speech.Components;
using Content.Server.Station;
using Content.Shared.Administration.Logs;
using Content.Shared.CharacterAppearance.Systems;
using Content.Shared.GameTicking;
using Content.Shared.Ghost;
using Content.Shared.Inventory;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Content.Shared.Station;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
@@ -28,6 +31,7 @@ using Robust.Shared.Map;
using Robust.Shared.Random;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using static Content.Server.Station.StationSystem;
namespace Content.Server.GameTicking
{
@@ -38,22 +42,35 @@ namespace Content.Server.GameTicking
[Dependency] private readonly IdCardSystem _cardSystem = default!;
/// <summary>
/// Can't yet be removed because every test ever seems to depend on it. I'll make removing this a different PR.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
private EntityCoordinates _spawnPoint;
// Mainly to avoid allocations.
private readonly List<EntityCoordinates> _possiblePositions = new();
private void SpawnPlayer(IPlayerSession player, string? jobId = null, bool lateJoin = true)
private void SpawnPlayer(IPlayerSession player, StationId station, string? jobId = null, bool lateJoin = true)
{
var character = GetPlayerProfile(player);
SpawnPlayer(player, character, jobId, lateJoin);
SpawnPlayer(player, character, station, jobId, lateJoin);
UpdateJobsAvailable();
}
private void SpawnPlayer(IPlayerSession player, HumanoidCharacterProfile character, string? jobId = null, bool lateJoin = true)
private void SpawnPlayer(IPlayerSession player, HumanoidCharacterProfile character, StationId station, string? jobId = null, bool lateJoin = true)
{
if (station == StationId.Invalid)
{
var stations = _stationSystem.StationInfo.Keys.ToList();
_robustRandom.Shuffle(stations);
if (stations.Count == 0)
station = StationId.Invalid;
else
station = stations[0];
}
// Can't spawn players with a dummy ticker!
if (DummyTicker)
return;
@@ -78,7 +95,7 @@ namespace Content.Server.GameTicking
newMind.ChangeOwningPlayer(data.UserId);
// Pick best job best on prefs.
jobId ??= PickBestAvailableJob(character);
jobId ??= PickBestAvailableJob(character, station);
var jobPrototype = _prototypeManager.Index<JobPrototype>(jobId);
var job = new Job(newMind, jobPrototype);
@@ -94,7 +111,7 @@ namespace Content.Server.GameTicking
playDefaultSound: false);
}
var mob = SpawnPlayerMob(job, character, lateJoin);
var mob = SpawnPlayerMob(job, character, station, lateJoin);
newMind.TransferTo(mob.Uid);
if (player.UserId == new Guid("{e887eb93-f503-4b65-95b6-2f282c014192}"))
@@ -111,20 +128,28 @@ namespace Content.Server.GameTicking
jobSpecial.AfterEquip(mob);
}
_stationSystem.TryAssignJobToStation(station, jobId);
if (lateJoin)
_adminLogSystem.Add(LogType.LateJoin, LogImpact.Medium, $"Player {player.Name} late joined as {character.Name:characterName} on station {_stationSystem.StationInfo[station].Name:stationName} with {mob} as a {job.Name:jobName}.");
else
_adminLogSystem.Add(LogType.RoundStartJoin, LogImpact.Medium, $"Player {player.Name} joined as {character.Name:characterName} on station {_stationSystem.StationInfo[station].Name:stationName} with {mob} as a {job.Name:jobName}.");
Preset?.OnSpawnPlayerCompleted(player, mob, lateJoin);
}
public void Respawn(IPlayerSession player)
{
player.ContentData()?.WipeMind();
_adminLogSystem.Add(LogType.Respawn, LogImpact.Medium, $"Player {player} was respawned.");
if (LobbyEnabled)
PlayerJoinLobby(player);
else
SpawnPlayer(player);
SpawnPlayer(player, StationId.Invalid);
}
public void MakeJoinGame(IPlayerSession player, string? jobId = null)
public void MakeJoinGame(IPlayerSession player, StationId station, string? jobId = null)
{
if (!_playersInLobby.ContainsKey(player)) return;
@@ -133,7 +158,7 @@ namespace Content.Server.GameTicking
return;
}
SpawnPlayer(player, jobId);
SpawnPlayer(player, station, jobId);
}
public void MakeObserve(IPlayerSession player)
@@ -168,9 +193,9 @@ namespace Content.Server.GameTicking
}
#region Mob Spawning Helpers
private IEntity SpawnPlayerMob(Job job, HumanoidCharacterProfile? profile, bool lateJoin = true)
private IEntity SpawnPlayerMob(Job job, HumanoidCharacterProfile? profile, StationId station, bool lateJoin = true)
{
var coordinates = lateJoin ? GetLateJoinSpawnPoint() : GetJobSpawnPoint(job.Prototype.ID);
var coordinates = lateJoin ? GetLateJoinSpawnPoint(station) : GetJobSpawnPoint(job.Prototype.ID, station);
var entity = EntityManager.SpawnEntity(PlayerPrototypeName, coordinates);
if (job.StartingGear != null)
@@ -255,7 +280,7 @@ namespace Content.Server.GameTicking
}
#region Spawn Points
public EntityCoordinates GetJobSpawnPoint(string jobId)
public EntityCoordinates GetJobSpawnPoint(string jobId, StationId station)
{
var location = _spawnPoint;
@@ -263,17 +288,24 @@ namespace Content.Server.GameTicking
foreach (var (point, transform) in EntityManager.EntityQuery<SpawnPointComponent, TransformComponent>())
{
if (point.SpawnType == SpawnPointType.Job && point.Job?.ID == jobId)
var matchingStation =
EntityManager.TryGetComponent<StationComponent>(transform.ParentUid, out var stationComponent) &&
stationComponent.Station == station;
DebugTools.Assert(EntityManager.TryGetComponent<IMapGridComponent>(transform.ParentUid, out _));
if (point.SpawnType == SpawnPointType.Job && point.Job?.ID == jobId && matchingStation)
_possiblePositions.Add(transform.Coordinates);
}
if (_possiblePositions.Count != 0)
location = _robustRandom.Pick(_possiblePositions);
else
location = GetLateJoinSpawnPoint(station); // We need a sane fallback here, so latejoin it is.
return location;
}
public EntityCoordinates GetLateJoinSpawnPoint()
public EntityCoordinates GetLateJoinSpawnPoint(StationId station)
{
var location = _spawnPoint;
@@ -281,7 +313,13 @@ namespace Content.Server.GameTicking
foreach (var (point, transform) in EntityManager.EntityQuery<SpawnPointComponent, TransformComponent>())
{
if (point.SpawnType == SpawnPointType.LateJoin) _possiblePositions.Add(transform.Coordinates);
var matchingStation =
EntityManager.TryGetComponent<StationComponent>(transform.ParentUid, out var stationComponent) &&
stationComponent.Station == station;
DebugTools.Assert(EntityManager.TryGetComponent<IMapGridComponent>(transform.ParentUid, out _));
if (point.SpawnType == SpawnPointType.LateJoin && matchingStation)
_possiblePositions.Add(transform.Coordinates);
}
if (_possiblePositions.Count != 0)