Enable nullability in Content.Server (#3685)
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
#nullable enable annotations
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Server.GameObjects.Components.Observer;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Server.Mobs;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Server.GameTicking
|
||||
{
|
||||
@@ -75,7 +75,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
var ghost = entityManager.SpawnEntity("MobObserver", position);
|
||||
ghost.Name = mind.CharacterName;
|
||||
ghost.Name = mind.CharacterName ?? string.Empty;
|
||||
|
||||
var ghostComponent = ghost.GetComponent<GhostComponent>();
|
||||
ghostComponent.CanReturnToBody = canReturn;
|
||||
|
||||
@@ -21,6 +21,7 @@ using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameTicking.GamePresets
|
||||
{
|
||||
@@ -106,19 +107,22 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
list.Remove(traitor);
|
||||
Logger.InfoS("preset", "Selected a preferred traitor.");
|
||||
}
|
||||
var mind = traitor.Data.ContentData().Mind;
|
||||
var mind = traitor.Data.ContentData()?.Mind;
|
||||
var antagPrototype = _prototypeManager.Index<AntagPrototype>(TraitorID);
|
||||
var traitorRole = new SuspicionTraitorRole(mind, antagPrototype);
|
||||
mind.AddRole(traitorRole);
|
||||
|
||||
DebugTools.AssertNotNull(mind?.OwnedEntity);
|
||||
|
||||
var traitorRole = new SuspicionTraitorRole(mind!, antagPrototype);
|
||||
mind!.AddRole(traitorRole);
|
||||
traitors.Add(traitorRole);
|
||||
// creadth: we need to create uplink for the antag.
|
||||
// PDA should be in place already, so we just need to
|
||||
// initiate uplink account.
|
||||
var uplinkAccount =
|
||||
new UplinkAccount(mind.OwnedEntity.Uid,
|
||||
new UplinkAccount(mind.OwnedEntity!.Uid,
|
||||
TraitorStartingBalance);
|
||||
var inventory = mind.OwnedEntity.GetComponent<InventoryComponent>();
|
||||
if (!inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent pdaItem))
|
||||
if (!inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent? pdaItem))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -137,9 +141,12 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
|
||||
foreach (var player in list)
|
||||
{
|
||||
var mind = player.Data.ContentData().Mind;
|
||||
var mind = player.Data.ContentData()?.Mind;
|
||||
var antagPrototype = _prototypeManager.Index<AntagPrototype>(InnocentID);
|
||||
mind.AddRole(new SuspicionInnocentRole(mind, antagPrototype));
|
||||
|
||||
DebugTools.AssertNotNull(mind);
|
||||
|
||||
mind!.AddRole(new SuspicionInnocentRole(mind, antagPrototype));
|
||||
}
|
||||
|
||||
foreach (var traitor in traitors)
|
||||
|
||||
@@ -22,6 +22,7 @@ using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameTicking.GamePresets
|
||||
{
|
||||
@@ -107,7 +108,6 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
Logger.InfoS("preset", "Selected a preferred traitor.");
|
||||
}
|
||||
var mind = traitor.Data.ContentData()?.Mind;
|
||||
var traitorRole = new TraitorRole(mind);
|
||||
if (mind == null)
|
||||
{
|
||||
Logger.ErrorS("preset", "Failed getting mind for picked traitor.");
|
||||
@@ -117,9 +117,11 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
// creadth: we need to create uplink for the antag.
|
||||
// PDA should be in place already, so we just need to
|
||||
// initiate uplink account.
|
||||
var uplinkAccount = new UplinkAccount(mind.OwnedEntity.Uid, StartingBalance);
|
||||
DebugTools.AssertNotNull(mind.OwnedEntity);
|
||||
|
||||
var uplinkAccount = new UplinkAccount(mind.OwnedEntity!.Uid, StartingBalance);
|
||||
var inventory = mind.OwnedEntity.GetComponent<InventoryComponent>();
|
||||
if (!inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent pdaItem))
|
||||
if (!inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent? pdaItem))
|
||||
{
|
||||
Logger.ErrorS("preset", "Failed getting pda for picked traitor.");
|
||||
continue;
|
||||
@@ -134,6 +136,8 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
continue;
|
||||
}
|
||||
|
||||
var traitorRole = new TraitorRole(mind);
|
||||
|
||||
mind.AddRole(traitorRole);
|
||||
_traitors.Add(traitorRole);
|
||||
pdaComponent.InitUplinkAccount(uplinkAccount);
|
||||
@@ -185,7 +189,10 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
|
||||
foreach (var traitor in _traitors)
|
||||
{
|
||||
result += "\n"+Loc.GetString("traitor-user-was-a-traitor", ("user", traitor.Mind.Session.Name));
|
||||
if (traitor.Mind.TryGetSession(out var session))
|
||||
{
|
||||
result += "\n" + Loc.GetString("traitor-user-was-a-traitor", ("user", session.Name));
|
||||
}
|
||||
|
||||
var objectives = traitor.Mind.AllObjectives.ToArray();
|
||||
if (objectives.Length == 0)
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameTicking.GameRules;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Server.Interfaces.Chat;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
using Content.Server.GameObjects.Components.PDA;
|
||||
using Content.Server.GameObjects.Components.Markers;
|
||||
using Content.Server.GameObjects.Components.PDA;
|
||||
using Content.Server.GameObjects.Components.TraitorDeathMatch;
|
||||
using Content.Server.GameTicking.GameRules;
|
||||
using Content.Server.Interfaces.Chat;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Server.Mobs;
|
||||
using Content.Server.Mobs.Roles.Traitor;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Shared;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.GameObjects.Components.PDA;
|
||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||
using Content.Shared;
|
||||
using Content.Shared.GameObjects.Components.PDA;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.GameTicking.GamePresets
|
||||
@@ -43,7 +43,7 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
public string BeltPrototypeName => "ClothingBeltJanitorFilled";
|
||||
public string BackpackPrototypeName => "ClothingBackpackFilled";
|
||||
|
||||
private RuleMaxTimeRestart _restarter;
|
||||
private RuleMaxTimeRestart _restarter = default!;
|
||||
private bool _safeToEndRound = false;
|
||||
|
||||
private Dictionary<UplinkAccount, string> _allOriginalNames = new();
|
||||
@@ -60,53 +60,57 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
|
||||
public override void OnSpawnPlayerCompleted(IPlayerSession session, IEntity mob, bool lateJoin)
|
||||
{
|
||||
int startingBalance = _cfg.GetCVar(CCVars.TraitorDeathMatchStartingBalance);
|
||||
var startingBalance = _cfg.GetCVar(CCVars.TraitorDeathMatchStartingBalance);
|
||||
|
||||
// Yup, they're a traitor
|
||||
var mind = session.Data.ContentData()?.Mind;
|
||||
var traitorRole = new TraitorRole(mind);
|
||||
if (mind == null)
|
||||
{
|
||||
Logger.ErrorS("preset", "Failed getting mind for TDM player.");
|
||||
return;
|
||||
}
|
||||
|
||||
var traitorRole = new TraitorRole(mind);
|
||||
mind.AddRole(traitorRole);
|
||||
|
||||
// Delete anything that may contain "dangerous" role-specific items.
|
||||
// (This includes the PDA, as everybody gets the captain PDA in this mode for true-all-access reasons.)
|
||||
var inventory = mind.OwnedEntity.GetComponent<InventoryComponent>();
|
||||
var victimSlots = new[] {EquipmentSlotDefines.Slots.IDCARD, EquipmentSlotDefines.Slots.BELT, EquipmentSlotDefines.Slots.BACKPACK};
|
||||
foreach (var slot in victimSlots)
|
||||
if (inventory.TryGetSlotItem(slot, out ItemComponent vItem))
|
||||
vItem.Owner.Delete();
|
||||
if (mind.OwnedEntity != null && mind.OwnedEntity.TryGetComponent(out InventoryComponent? inventory))
|
||||
{
|
||||
var victimSlots = new[] {EquipmentSlotDefines.Slots.IDCARD, EquipmentSlotDefines.Slots.BELT, EquipmentSlotDefines.Slots.BACKPACK};
|
||||
foreach (var slot in victimSlots)
|
||||
{
|
||||
if (inventory.TryGetSlotItem(slot, out ItemComponent? vItem))
|
||||
vItem.Owner.Delete();
|
||||
}
|
||||
|
||||
// Replace their items:
|
||||
// Replace their items:
|
||||
|
||||
// pda
|
||||
var newPDA = _entityManager.SpawnEntity(PDAPrototypeName, mind.OwnedEntity.Transform.Coordinates);
|
||||
inventory.Equip(EquipmentSlotDefines.Slots.IDCARD, newPDA.GetComponent<ItemComponent>());
|
||||
// pda
|
||||
var newPDA = _entityManager.SpawnEntity(PDAPrototypeName, mind.OwnedEntity.Transform.Coordinates);
|
||||
inventory.Equip(EquipmentSlotDefines.Slots.IDCARD, newPDA.GetComponent<ItemComponent>());
|
||||
|
||||
// belt
|
||||
var newTmp = _entityManager.SpawnEntity(BeltPrototypeName, mind.OwnedEntity.Transform.Coordinates);
|
||||
inventory.Equip(EquipmentSlotDefines.Slots.BELT, newTmp.GetComponent<ItemComponent>());
|
||||
// belt
|
||||
var newTmp = _entityManager.SpawnEntity(BeltPrototypeName, mind.OwnedEntity.Transform.Coordinates);
|
||||
inventory.Equip(EquipmentSlotDefines.Slots.BELT, newTmp.GetComponent<ItemComponent>());
|
||||
|
||||
// backpack
|
||||
newTmp = _entityManager.SpawnEntity(BackpackPrototypeName, mind.OwnedEntity.Transform.Coordinates);
|
||||
inventory.Equip(EquipmentSlotDefines.Slots.BACKPACK, newTmp.GetComponent<ItemComponent>());
|
||||
// backpack
|
||||
newTmp = _entityManager.SpawnEntity(BackpackPrototypeName, mind.OwnedEntity.Transform.Coordinates);
|
||||
inventory.Equip(EquipmentSlotDefines.Slots.BACKPACK, newTmp.GetComponent<ItemComponent>());
|
||||
|
||||
// Like normal traitors, they need access to a traitor account.
|
||||
var uplinkAccount = new UplinkAccount(mind.OwnedEntity.Uid, startingBalance);
|
||||
var pdaComponent = newPDA.GetComponent<PDAComponent>();
|
||||
pdaComponent.InitUplinkAccount(uplinkAccount);
|
||||
_allOriginalNames[uplinkAccount] = mind.OwnedEntity.Name;
|
||||
// Like normal traitors, they need access to a traitor account.
|
||||
var uplinkAccount = new UplinkAccount(mind.OwnedEntity.Uid, startingBalance);
|
||||
var pdaComponent = newPDA.GetComponent<PDAComponent>();
|
||||
pdaComponent.InitUplinkAccount(uplinkAccount);
|
||||
_allOriginalNames[uplinkAccount] = mind.OwnedEntity.Name;
|
||||
|
||||
// The PDA needs to be marked with the correct owner.
|
||||
pdaComponent.SetPDAOwner(mind.OwnedEntity.Name);
|
||||
newPDA.AddComponent<TraitorDeathMatchReliableOwnerTagComponent>().UserId = mind.UserId;
|
||||
// The PDA needs to be marked with the correct owner.
|
||||
pdaComponent.SetPDAOwner(mind.OwnedEntity.Name);
|
||||
newPDA.AddComponent<TraitorDeathMatchReliableOwnerTagComponent>().UserId = mind.UserId;
|
||||
}
|
||||
|
||||
// Finally, it would be preferrable if they spawned as far away from other players as reasonably possible.
|
||||
if (FindAnyIsolatedSpawnLocation(mind, out var bestTarget))
|
||||
if (mind.OwnedEntity != null && FindAnyIsolatedSpawnLocation(mind, out var bestTarget))
|
||||
{
|
||||
mind.OwnedEntity.Transform.Coordinates = bestTarget;
|
||||
}
|
||||
@@ -136,7 +140,7 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
var avoidMeEntity = avoidMeMind.OwnedEntity;
|
||||
if (avoidMeEntity == null)
|
||||
continue;
|
||||
if (avoidMeEntity.TryGetComponent(out IMobStateComponent mobState))
|
||||
if (avoidMeEntity.TryGetComponent(out IMobStateComponent? mobState))
|
||||
{
|
||||
// Does have mob state component; if critical or dead, they don't really matter for spawn checks
|
||||
if (mobState.IsCritical() || mobState.IsDead())
|
||||
@@ -181,12 +185,12 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
public override bool OnGhostAttempt(Mind mind, bool canReturnGlobal)
|
||||
{
|
||||
var entity = mind.OwnedEntity;
|
||||
if ((entity != null) && (entity.TryGetComponent(out IMobStateComponent mobState)))
|
||||
if ((entity != null) && (entity.TryGetComponent(out IMobStateComponent? mobState)))
|
||||
{
|
||||
if (mobState.IsCritical())
|
||||
{
|
||||
// TODO: This is copy/pasted from ghost code. Really, IDamagableComponent needs a method to reliably kill the target.
|
||||
if (entity.TryGetComponent(out IDamageableComponent damageable))
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
//todo: what if they dont breathe lol
|
||||
damageable.ChangeDamage(DamageType.Asphyxiation, 100, true);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Content.Server.GameTicking.GameRules
|
||||
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
private CancellationTokenSource _checkTimerCancel;
|
||||
private CancellationTokenSource? _checkTimerCancel;
|
||||
|
||||
public override void Added()
|
||||
{
|
||||
@@ -59,12 +59,12 @@ namespace Content.Server.GameTicking.GameRules
|
||||
if (!_cfg.GetCVar(CCVars.GameLobbyEnableWin))
|
||||
return;
|
||||
|
||||
IPlayerSession winner = null;
|
||||
IPlayerSession? winner = null;
|
||||
foreach (var playerSession in _playerManager.GetAllPlayers())
|
||||
{
|
||||
var playerEntity = playerSession.AttachedEntity;
|
||||
if (playerEntity == null
|
||||
|| !playerEntity.TryGetComponent(out IMobStateComponent state))
|
||||
|| !playerEntity.TryGetComponent(out IMobStateComponent? state))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ namespace Content.Server.GameTicking.GameRules
|
||||
Timer.Spawn(TimeSpan.FromSeconds(restartDelay), () => _gameTicker.RestartRound());
|
||||
}
|
||||
|
||||
private void PlayerManagerOnPlayerStatusChanged(object sender, SessionStatusEventArgs e)
|
||||
private void PlayerManagerOnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
if (e.NewStatus == SessionStatus.Disconnected)
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Content.Server.GameTicking.GameRules
|
||||
foreach (var playerSession in _playerManager.GetAllPlayers())
|
||||
{
|
||||
if (playerSession.AttachedEntity == null
|
||||
|| !playerSession.AttachedEntity.TryGetComponent(out IMobStateComponent mobState)
|
||||
|| !playerSession.AttachedEntity.TryGetComponent(out IMobStateComponent? mobState)
|
||||
|| !playerSession.AttachedEntity.HasComponent<SuspicionRoleComponent>())
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
@@ -45,7 +46,7 @@ namespace Content.Server.GameTicking
|
||||
.Where(j =>
|
||||
{
|
||||
var (jobId, priority) = j;
|
||||
if (!_prototypeManager.TryIndex(jobId, out JobPrototype job))
|
||||
if (!_prototypeManager.TryIndex(jobId, out JobPrototype? job))
|
||||
{
|
||||
// Job doesn't exist, probably old data?
|
||||
return false;
|
||||
@@ -145,7 +146,7 @@ namespace Content.Server.GameTicking
|
||||
{
|
||||
var available = GetAvailablePositions();
|
||||
|
||||
bool TryPick(JobPriority priority, out string jobId)
|
||||
bool TryPick(JobPriority priority, [NotNullWhen(true)] out string? jobId)
|
||||
{
|
||||
var filtered = profile.JobPriorities
|
||||
.Where(p => p.Value == priority)
|
||||
|
||||
@@ -15,8 +15,6 @@ using Content.Server.GameObjects.Components.Mobs.Speech;
|
||||
using Content.Server.GameObjects.Components.Observer;
|
||||
using Content.Server.GameObjects.Components.PDA;
|
||||
using Content.Server.GameTicking.GamePresets;
|
||||
using Content.Server.Holiday;
|
||||
using Content.Server.Holiday.Interfaces;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Server.Interfaces.Chat;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
@@ -80,7 +78,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
[ViewVariables] private bool _initialized;
|
||||
|
||||
[ViewVariables] private Type _presetType;
|
||||
[ViewVariables] private Type? _presetType;
|
||||
|
||||
[ViewVariables] private TimeSpan _pauseTime;
|
||||
[ViewVariables] private bool _roundStartCountdownHasNotStartedYetDueToNoPlayers;
|
||||
@@ -93,7 +91,7 @@ namespace Content.Server.GameTicking
|
||||
[ViewVariables] private bool LobbyEnabled => _configurationManager.GetCVar(CCVars.GameLobbyEnabled);
|
||||
|
||||
[ViewVariables] private bool _updateOnRoundEnd;
|
||||
private CancellationTokenSource _updateShutdownCts;
|
||||
private CancellationTokenSource? _updateShutdownCts;
|
||||
|
||||
|
||||
[ViewVariables] public bool Paused { get; private set; }
|
||||
@@ -118,24 +116,24 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public GamePreset Preset
|
||||
public GamePreset? Preset
|
||||
{
|
||||
get => _preset == null ? MakeGamePreset(null) : _preset;
|
||||
get => _preset ?? MakeGamePreset(new Dictionary<NetUserId, HumanoidCharacterProfile>());
|
||||
set => _preset = value;
|
||||
}
|
||||
|
||||
public ImmutableDictionary<string, Type> Presets { get; private set; }
|
||||
public ImmutableDictionary<string, Type> Presets { get; private set; } = default!;
|
||||
|
||||
private GamePreset _preset;
|
||||
private GamePreset? _preset;
|
||||
|
||||
public event Action<GameRunLevelChangedEventArgs> OnRunLevelChanged;
|
||||
public event Action<GameRuleAddedEventArgs> OnRuleAdded;
|
||||
public event Action<GameRunLevelChangedEventArgs>? OnRunLevelChanged;
|
||||
public event Action<GameRuleAddedEventArgs>? OnRuleAdded;
|
||||
|
||||
private TimeSpan LobbyDuration =>
|
||||
TimeSpan.FromSeconds(_configurationManager.GetCVar(CCVars.GameLobbyDuration));
|
||||
|
||||
private SoundCollectionPrototype _lobbyCollection = default!;
|
||||
[ViewVariables] public string LobbySong { get; private set; }
|
||||
[ViewVariables] public string LobbySong { get; private set; } = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -356,7 +354,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
private void UpdateLateJoinStatus()
|
||||
{
|
||||
var msg = new MsgTickerLateJoinStatus(null) {Disallowed = DisallowLateJoin};
|
||||
var msg = new MsgTickerLateJoinStatus(null!) {Disallowed = DisallowLateJoin};
|
||||
_netManager.ServerSendToAll(msg);
|
||||
}
|
||||
|
||||
@@ -382,8 +380,8 @@ namespace Content.Server.GameTicking
|
||||
|
||||
//Tell every client the round has ended.
|
||||
var roundEndMessage = _netManager.CreateNetMessage<MsgRoundEndMessage>();
|
||||
roundEndMessage.GamemodeTitle = Preset.ModeTitle;
|
||||
roundEndMessage.RoundEndText = roundEndText + $"\n{Preset.GetRoundEndDescription()}";
|
||||
roundEndMessage.GamemodeTitle = Preset?.ModeTitle ?? string.Empty;
|
||||
roundEndMessage.RoundEndText = roundEndText + $"\n{Preset?.GetRoundEndDescription() ?? string.Empty}";
|
||||
|
||||
//Get the timespan of the round.
|
||||
roundEndMessage.RoundDuration = IoCManager.Resolve<IGameTiming>().RealTime.Subtract(_roundStartTimeSpan);
|
||||
@@ -392,7 +390,8 @@ namespace Content.Server.GameTicking
|
||||
var listOfPlayerInfo = new List<RoundEndPlayerInfo>();
|
||||
foreach (var ply in PlayerManager.GetAllPlayers().OrderBy(p => p.Name))
|
||||
{
|
||||
var mind = ply.ContentData().Mind;
|
||||
var mind = ply.ContentData()?.Mind;
|
||||
|
||||
if (mind != null)
|
||||
{
|
||||
_playersInLobby.TryGetValue(ply, out var status);
|
||||
@@ -400,7 +399,7 @@ namespace Content.Server.GameTicking
|
||||
var playerEndRoundInfo = new RoundEndPlayerInfo()
|
||||
{
|
||||
PlayerOOCName = ply.Name,
|
||||
PlayerICName = mind.CurrentEntity.Name,
|
||||
PlayerICName = mind.CurrentEntity?.Name,
|
||||
Role = antag
|
||||
? mind.AllRoles.First(role => role.Antagonist).Name
|
||||
: mind.AllRoles.FirstOrDefault()?.Name ?? Loc.GetString("Unknown"),
|
||||
@@ -417,8 +416,10 @@ namespace Content.Server.GameTicking
|
||||
|
||||
public void Respawn(IPlayerSession targetPlayer)
|
||||
{
|
||||
targetPlayer.AttachedEntity.TryGetComponent<GhostComponent>(out var ghost);
|
||||
var ghost = targetPlayer.AttachedEntity?.GetComponentOrNull<GhostComponent>();
|
||||
|
||||
targetPlayer.ContentData()?.WipeMind();
|
||||
|
||||
if (ghost?.Deleted == false)
|
||||
ghost.Owner.Delete();
|
||||
|
||||
@@ -437,7 +438,7 @@ namespace Content.Server.GameTicking
|
||||
_netManager.ServerSendToAll(GetStatusSingle(player, PlayerStatus.Observer));
|
||||
}
|
||||
|
||||
public void MakeJoinGame(IPlayerSession player, string jobId = null)
|
||||
public void MakeJoinGame(IPlayerSession player, string? jobId = null)
|
||||
{
|
||||
if (!_playersInLobby.ContainsKey(player)) return;
|
||||
|
||||
@@ -473,7 +474,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
public bool OnGhostAttempt(Mind mind, bool canReturnGlobal)
|
||||
{
|
||||
return Preset.OnGhostAttempt(mind, canReturnGlobal);
|
||||
return Preset?.OnGhostAttempt(mind, canReturnGlobal) ?? false;
|
||||
}
|
||||
|
||||
public T AddGameRule<T>() where T : GameRule, new()
|
||||
@@ -488,14 +489,30 @@ namespace Content.Server.GameTicking
|
||||
return instance;
|
||||
}
|
||||
|
||||
public bool HasGameRule(Type t)
|
||||
public bool HasGameRule(string? name)
|
||||
{
|
||||
if (t == null || !typeof(GameRule).IsAssignableFrom(t))
|
||||
if (name == null)
|
||||
return false;
|
||||
|
||||
foreach (var rule in _gameRules)
|
||||
{
|
||||
if (rule.GetType().IsAssignableFrom(t))
|
||||
if (rule.GetType().Name == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HasGameRule(Type? type)
|
||||
{
|
||||
if (type == null || !typeof(GameRule).IsAssignableFrom(type))
|
||||
return false;
|
||||
|
||||
foreach (var rule in _gameRules)
|
||||
{
|
||||
if (rule.GetType().IsAssignableFrom(type))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -513,7 +530,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
public IEnumerable<GameRule> ActiveGameRules => _gameRules;
|
||||
|
||||
public bool TryGetPreset(string name, [NotNullWhen(true)] out Type type)
|
||||
public bool TryGetPreset(string name, [NotNullWhen(true)] out Type? type)
|
||||
{
|
||||
name = name.ToLowerInvariant();
|
||||
return Presets.TryGetValue(name, out type);
|
||||
@@ -597,12 +614,16 @@ namespace Content.Server.GameTicking
|
||||
return Paused;
|
||||
}
|
||||
|
||||
private IEntity _spawnPlayerMob(Job job, HumanoidCharacterProfile profile, bool lateJoin = true)
|
||||
private IEntity _spawnPlayerMob(Job job, HumanoidCharacterProfile? profile, bool lateJoin = true)
|
||||
{
|
||||
var coordinates = lateJoin ? GetLateJoinSpawnPoint() : GetJobSpawnPoint(job.Prototype.ID);
|
||||
var entity = _entityManager.SpawnEntity(PlayerPrototypeName, coordinates);
|
||||
var startingGear = _prototypeManager.Index<StartingGearPrototype>(job.StartingGear);
|
||||
EquipStartingGear(entity, startingGear, profile);
|
||||
|
||||
if (job.StartingGear != null)
|
||||
{
|
||||
var startingGear = _prototypeManager.Index<StartingGearPrototype>(job.StartingGear);
|
||||
EquipStartingGear(entity, startingGear, profile);
|
||||
}
|
||||
|
||||
if (profile != null)
|
||||
{
|
||||
@@ -613,9 +634,9 @@ namespace Content.Server.GameTicking
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void EquipStartingGear(IEntity entity, StartingGearPrototype startingGear, HumanoidCharacterProfile profile)
|
||||
public void EquipStartingGear(IEntity entity, StartingGearPrototype startingGear, HumanoidCharacterProfile? profile)
|
||||
{
|
||||
if (entity.TryGetComponent(out InventoryComponent inventory))
|
||||
if (entity.TryGetComponent(out InventoryComponent? inventory))
|
||||
{
|
||||
foreach (var slot in AllSlots)
|
||||
{
|
||||
@@ -628,7 +649,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent(out HandsComponent handsComponent))
|
||||
if (entity.TryGetComponent(out HandsComponent? handsComponent))
|
||||
{
|
||||
var inhand = startingGear.Inhand;
|
||||
foreach (var (hand, prototype) in inhand)
|
||||
@@ -669,7 +690,7 @@ namespace Content.Server.GameTicking
|
||||
foreach (var entity in _entityManager.GetEntities(new TypeEntityQuery(typeof(SpawnPointComponent))))
|
||||
{
|
||||
var point = entity.GetComponent<SpawnPointComponent>();
|
||||
if (point.SpawnType == SpawnPointType.Job && point.Job.ID == jobId)
|
||||
if (point.SpawnType == SpawnPointType.Job && point.Job?.ID == jobId)
|
||||
possiblePoints.Add(entity.Transform.Coordinates);
|
||||
}
|
||||
|
||||
@@ -754,7 +775,13 @@ namespace Content.Server.GameTicking
|
||||
{
|
||||
DefaultMap = _mapManager.CreateMap();
|
||||
var startTime = _gameTiming.RealTime;
|
||||
var grid = _mapLoader.LoadBlueprint(DefaultMap, GetMap());
|
||||
var map = GetMap();
|
||||
var grid = _mapLoader.LoadBlueprint(DefaultMap, map);
|
||||
|
||||
if (grid == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No grid found for map {map}");
|
||||
}
|
||||
|
||||
DefaultGridId = grid.Index;
|
||||
_spawnPoint = grid.ToCoordinates();
|
||||
@@ -763,7 +790,7 @@ namespace Content.Server.GameTicking
|
||||
Logger.InfoS("ticker", $"Loaded map in {timeSpan.TotalMilliseconds:N2}ms.");
|
||||
}
|
||||
|
||||
protected override void PlayerStatusChanged(object sender, SessionStatusEventArgs args)
|
||||
protected override void PlayerStatusChanged(object? sender, SessionStatusEventArgs args)
|
||||
{
|
||||
base.PlayerStatusChanged(sender, args);
|
||||
|
||||
@@ -794,7 +821,10 @@ namespace Content.Server.GameTicking
|
||||
_prefsManager.OnClientConnected(session);
|
||||
|
||||
var data = session.ContentData();
|
||||
if (data.Mind == null)
|
||||
|
||||
DebugTools.AssertNotNull(data);
|
||||
|
||||
if (data!.Mind == null)
|
||||
{
|
||||
if (LobbyEnabled)
|
||||
{
|
||||
@@ -871,7 +901,7 @@ namespace Content.Server.GameTicking
|
||||
}, _updateShutdownCts.Token);
|
||||
}
|
||||
|
||||
private void SpawnPlayer(IPlayerSession session, string jobId = null, bool lateJoin = true)
|
||||
private void SpawnPlayer(IPlayerSession session, string? jobId = null, bool lateJoin = true)
|
||||
{
|
||||
var character = GetPlayerProfile(session);
|
||||
|
||||
@@ -881,7 +911,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
private void SpawnPlayer(IPlayerSession session,
|
||||
HumanoidCharacterProfile character,
|
||||
string jobId = null,
|
||||
string? jobId = null,
|
||||
bool lateJoin = true)
|
||||
{
|
||||
if (lateJoin && DisallowLateJoin)
|
||||
@@ -893,17 +923,17 @@ namespace Content.Server.GameTicking
|
||||
_playerJoinGame(session);
|
||||
|
||||
var data = session.ContentData();
|
||||
data.WipeMind();
|
||||
|
||||
DebugTools.AssertNotNull(data);
|
||||
|
||||
data!.WipeMind();
|
||||
data.Mind = new Mind(session.UserId)
|
||||
{
|
||||
CharacterName = character.Name
|
||||
};
|
||||
|
||||
if (jobId == null)
|
||||
{
|
||||
// Pick best job best on prefs.
|
||||
jobId = PickBestAvailableJob(character);
|
||||
}
|
||||
// Pick best job best on prefs.
|
||||
jobId ??= PickBestAvailableJob(character);
|
||||
|
||||
var jobPrototype = _prototypeManager.Index<JobPrototype>(jobId);
|
||||
var job = new Job(data.Mind, jobPrototype);
|
||||
@@ -931,14 +961,14 @@ namespace Content.Server.GameTicking
|
||||
EquipIdCard(mob, character.Name, jobPrototype);
|
||||
jobPrototype.Special?.AfterEquip(mob);
|
||||
|
||||
Preset.OnSpawnPlayerCompleted(session, mob, lateJoin);
|
||||
Preset?.OnSpawnPlayerCompleted(session, mob, lateJoin);
|
||||
}
|
||||
|
||||
private void EquipIdCard(IEntity mob, string characterName, JobPrototype jobPrototype)
|
||||
{
|
||||
var inventory = mob.GetComponent<InventoryComponent>();
|
||||
|
||||
if (!inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent pdaItem))
|
||||
if (!inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent? pdaItem))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -946,7 +976,7 @@ namespace Content.Server.GameTicking
|
||||
var pda = pdaItem.Owner;
|
||||
|
||||
var pdaComponent = pda.GetComponent<PDAComponent>();
|
||||
if (pdaComponent.IdSlotEmpty)
|
||||
if (pdaComponent.ContainedID == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -973,7 +1003,10 @@ namespace Content.Server.GameTicking
|
||||
var name = GetPlayerProfile(session).Name;
|
||||
|
||||
var data = session.ContentData();
|
||||
data.WipeMind();
|
||||
|
||||
DebugTools.AssertNotNull(data);
|
||||
|
||||
data!.WipeMind();
|
||||
data.Mind = new Mind(session.UserId);
|
||||
|
||||
var mob = _spawnObserverMob();
|
||||
@@ -1069,6 +1102,11 @@ namespace Content.Server.GameTicking
|
||||
|
||||
private string GetInfoText()
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var gmTitle = Preset.ModeTitle;
|
||||
var desc = Preset.Description;
|
||||
return Loc.GetString(@"Hi and welcome to [color=white]Space Station 14![/color]
|
||||
|
||||
Reference in New Issue
Block a user