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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user