Refactor GameMapManager a bit (nukes mapforced) (#11513)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Closes https://github.com/space-wizards/space-station-14/issues/7192 Closes https://github.com/space-wizards/space-station-14/issues/6537 Closes https://github.com/space-wizards/space-station-14/issues/9579
This commit is contained in:
@@ -43,11 +43,9 @@ public static class PoolManager
|
|||||||
(CCVars.DatabaseSqliteDelay.Name, "0", false),
|
(CCVars.DatabaseSqliteDelay.Name, "0", false),
|
||||||
(CCVars.HolidaysEnabled.Name, "false", false),
|
(CCVars.HolidaysEnabled.Name, "false", false),
|
||||||
(CCVars.GameMap.Name, "Empty", true),
|
(CCVars.GameMap.Name, "Empty", true),
|
||||||
(CCVars.GameMapForced.Name, "true", true),
|
|
||||||
(CCVars.AdminLogsQueueSendDelay.Name, "0", true),
|
(CCVars.AdminLogsQueueSendDelay.Name, "0", true),
|
||||||
(CCVars.NetPVS.Name, "false", true),
|
(CCVars.NetPVS.Name, "false", true),
|
||||||
(CCVars.NPCMaxUpdates.Name, "999999", true),
|
(CCVars.NPCMaxUpdates.Name, "999999", true),
|
||||||
(CCVars.GameMapForced.Name, "true", true),
|
|
||||||
(CCVars.SysWinTickPeriod.Name, "0", true),
|
(CCVars.SysWinTickPeriod.Name, "0", true),
|
||||||
(CCVars.ContactMinimumThreads.Name, "1", true),
|
(CCVars.ContactMinimumThreads.Name, "1", true),
|
||||||
(CCVars.ContactMultithreadThreshold.Name, "999", true),
|
(CCVars.ContactMultithreadThreshold.Name, "999", true),
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
@@ -10,6 +12,8 @@ namespace Content.Server.GameTicking.Commands
|
|||||||
[AdminCommand(AdminFlags.Round)]
|
[AdminCommand(AdminFlags.Round)]
|
||||||
sealed class ForceMapCommand : IConsoleCommand
|
sealed class ForceMapCommand : IConsoleCommand
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||||
|
|
||||||
public string Command => "forcemap";
|
public string Command => "forcemap";
|
||||||
public string Description => Loc.GetString("forcemap-command-description");
|
public string Description => Loc.GetString("forcemap-command-description");
|
||||||
public string Help => Loc.GetString("forcemap-command-help");
|
public string Help => Loc.GetString("forcemap-command-help");
|
||||||
@@ -25,7 +29,7 @@ namespace Content.Server.GameTicking.Commands
|
|||||||
var gameMap = IoCManager.Resolve<IGameMapManager>();
|
var gameMap = IoCManager.Resolve<IGameMapManager>();
|
||||||
var name = args[0];
|
var name = args[0];
|
||||||
|
|
||||||
gameMap.ForceSelectMap(name);
|
_configurationManager.SetCVar(CCVars.GameMap, name);
|
||||||
shell.WriteLine(Loc.GetString("forcemap-command-success", ("map", name)));
|
shell.WriteLine(Loc.GetString("forcemap-command-success", ("map", name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
|
using Content.Server.Station.Systems;
|
||||||
|
using Content.Server.Station.Components;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Players;
|
using Robust.Shared.Players;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Content.Server.GameTicking
|
namespace Content.Server.GameTicking
|
||||||
{
|
{
|
||||||
@@ -39,13 +42,33 @@ namespace Content.Server.GameTicking
|
|||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var playerCount = $"{_playerManager.PlayerCount}";
|
var playerCount = $"{_playerManager.PlayerCount}";
|
||||||
var map = _gameMapManager.GetSelectedMap();
|
|
||||||
var mapName = map?.MapName ?? Loc.GetString("game-ticker-no-map-selected");
|
StringBuilder stationNames = new StringBuilder();
|
||||||
|
if (_stationSystem.Stations.Count != 0)
|
||||||
|
{
|
||||||
|
foreach (EntityUid entUID in _stationSystem.Stations)
|
||||||
|
{
|
||||||
|
StationDataComponent? stationData = null;
|
||||||
|
MetaDataComponent? metaData = null;
|
||||||
|
if (Resolve(entUID, ref stationData, ref metaData, logMissing: true))
|
||||||
|
{
|
||||||
|
if (stationNames.Length > 0)
|
||||||
|
stationNames.Append('\n');
|
||||||
|
|
||||||
|
stationNames.Append(metaData.EntityName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stationNames.Append(Loc.GetString("game-ticker-no-map-selected"));
|
||||||
|
}
|
||||||
|
|
||||||
var gmTitle = Loc.GetString(Preset.ModeTitle);
|
var gmTitle = Loc.GetString(Preset.ModeTitle);
|
||||||
var desc = Loc.GetString(Preset.Description);
|
var desc = Loc.GetString(Preset.Description);
|
||||||
return Loc.GetString("game-ticker-get-info-text",("roundId", RoundId), ("playerCount", playerCount),("mapName", mapName),("gmTitle", gmTitle),("desc", desc));
|
return Loc.GetString("game-ticker-get-info-text",("roundId", RoundId), ("playerCount", playerCount),("mapName", stationNames.ToString()),("gmTitle", gmTitle),("desc", desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
private TickerLobbyReadyEvent GetStatusSingle(ICommonSession player, PlayerGameStatus gameStatus)
|
private TickerLobbyReadyEvent GetStatusSingle(ICommonSession player, PlayerGameStatus gameStatus)
|
||||||
|
|||||||
@@ -81,7 +81,29 @@ namespace Content.Server.GameTicking
|
|||||||
DefaultMap = _mapManager.CreateMap();
|
DefaultMap = _mapManager.CreateMap();
|
||||||
_mapManager.AddUninitializedMap(DefaultMap);
|
_mapManager.AddUninitializedMap(DefaultMap);
|
||||||
var startTime = _gameTiming.RealTime;
|
var startTime = _gameTiming.RealTime;
|
||||||
var maps = new List<GameMapPrototype>() { _gameMapManager.GetSelectedMapChecked(true, true) };
|
|
||||||
|
var maps = new List<GameMapPrototype>();
|
||||||
|
|
||||||
|
// the map might have been force-set by something
|
||||||
|
// (i.e. votemap or forcemap)
|
||||||
|
var mainStationMap = _gameMapManager.GetSelectedMap();
|
||||||
|
if (mainStationMap == null)
|
||||||
|
{
|
||||||
|
// otherwise set the map using the config rules
|
||||||
|
_gameMapManager.SelectMapByConfigRules();
|
||||||
|
mainStationMap = _gameMapManager.GetSelectedMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small chance the above could return no map.
|
||||||
|
// ideally SelectMapByConfigRules will always find a valid map
|
||||||
|
if (mainStationMap != null)
|
||||||
|
{
|
||||||
|
maps.Add(mainStationMap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("invalid config; couldn't select a valid station map!");
|
||||||
|
}
|
||||||
|
|
||||||
// Let game rules dictate what maps we should load.
|
// Let game rules dictate what maps we should load.
|
||||||
RaiseLocalEvent(new LoadingMapsEvent(maps));
|
RaiseLocalEvent(new LoadingMapsEvent(maps));
|
||||||
@@ -149,6 +171,10 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
LoadMaps();
|
LoadMaps();
|
||||||
|
|
||||||
|
// map has been selected so update the lobby info text
|
||||||
|
// applies to players who didn't ready up
|
||||||
|
UpdateInfoText();
|
||||||
|
|
||||||
StartGamePresetRules();
|
StartGamePresetRules();
|
||||||
|
|
||||||
RoundLengthMetric.Set(0);
|
RoundLengthMetric.Set(0);
|
||||||
@@ -423,6 +449,8 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
_roleBanManager.Restart();
|
_roleBanManager.Restart();
|
||||||
|
|
||||||
|
_gameMapManager.ClearSelectedMap();
|
||||||
|
|
||||||
// Clear up any game rules.
|
// Clear up any game rules.
|
||||||
ClearGameRules();
|
ClearGameRules();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Chat.Managers;
|
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -15,29 +15,38 @@ public sealed class GameMapManager : IGameMapManager
|
|||||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
[ViewVariables]
|
|
||||||
private readonly Queue<string> _previousMaps = new();
|
private readonly Queue<string> _previousMaps = new();
|
||||||
[ViewVariables]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
private GameMapPrototype _currentMap = default!;
|
private GameMapPrototype? _configSelectedMap = default;
|
||||||
[ViewVariables]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
private bool _currentMapForced;
|
private GameMapPrototype? _selectedMap = default; // Don't change this value during a round!
|
||||||
[ViewVariables]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
private bool _mapRotationEnabled;
|
private bool _mapRotationEnabled;
|
||||||
[ViewVariables]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
private int _mapQueueDepth = 1;
|
private int _mapQueueDepth = 1;
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
_configurationManager.OnValueChanged(CCVars.GameMap, value =>
|
_configurationManager.OnValueChanged(CCVars.GameMap, value =>
|
||||||
{
|
{
|
||||||
if (TryLookupMap(value, out var map))
|
if (TryLookupMap(value, out GameMapPrototype? map))
|
||||||
_currentMap = map;
|
{
|
||||||
|
_configSelectedMap = map;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
throw new ArgumentException($"Unknown map prototype {value} was selected!");
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
_configSelectedMap = default!;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.ErrorS("mapsel", $"Unknown map prototype {value} was selected!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}, true);
|
}, true);
|
||||||
_configurationManager.OnValueChanged(CCVars.GameMapForced, value => _currentMapForced = value, true);
|
|
||||||
_configurationManager.OnValueChanged(CCVars.GameMapRotation, value => _mapRotationEnabled = value, true);
|
_configurationManager.OnValueChanged(CCVars.GameMapRotation, value => _mapRotationEnabled = value, true);
|
||||||
_configurationManager.OnValueChanged(CCVars.GameMapMemoryDepth, value =>
|
_configurationManager.OnValueChanged(CCVars.GameMapMemoryDepth, value =>
|
||||||
{
|
{
|
||||||
@@ -62,7 +71,6 @@ public sealed class GameMapManager : IGameMapManager
|
|||||||
public IEnumerable<GameMapPrototype> CurrentlyEligibleMaps()
|
public IEnumerable<GameMapPrototype> CurrentlyEligibleMaps()
|
||||||
{
|
{
|
||||||
var maps = AllVotableMaps().Where(IsMapEligible).ToArray();
|
var maps = AllVotableMaps().Where(IsMapEligible).ToArray();
|
||||||
|
|
||||||
return maps.Length == 0 ? AllMaps().Where(x => x.Fallback) : maps;
|
return maps.Length == 0 ? AllMaps().Where(x => x.Fallback) : maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,64 +99,59 @@ public sealed class GameMapManager : IGameMapManager
|
|||||||
return _prototypeManager.EnumeratePrototypes<GameMapPrototype>();
|
return _prototypeManager.EnumeratePrototypes<GameMapPrototype>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TrySelectMap(string gameMap)
|
public GameMapPrototype? GetSelectedMap()
|
||||||
{
|
{
|
||||||
if (!TryLookupMap(gameMap, out var map) || !IsMapEligible(map)) return false;
|
return _configSelectedMap ?? _selectedMap;
|
||||||
|
|
||||||
_currentMap = map;
|
|
||||||
_currentMapForced = false;
|
|
||||||
var ticker = EntitySystem.Get<GameTicking.GameTicker>();
|
|
||||||
ticker.UpdateInfoText();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ForceSelectMap(string gameMap)
|
public void ClearSelectedMap()
|
||||||
|
{
|
||||||
|
_selectedMap = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TrySelectMapIfEligible(string gameMap)
|
||||||
|
{
|
||||||
|
if (!TryLookupMap(gameMap, out var map) || !IsMapEligible(map))
|
||||||
|
return false;
|
||||||
|
_selectedMap = map;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectMap(string gameMap)
|
||||||
{
|
{
|
||||||
if (!TryLookupMap(gameMap, out var map))
|
if (!TryLookupMap(gameMap, out var map))
|
||||||
throw new ArgumentException($"The map \"{gameMap}\" is invalid!");
|
throw new ArgumentException($"The map \"{gameMap}\" is invalid!");
|
||||||
_currentMap = map;
|
_selectedMap = map;
|
||||||
_currentMapForced = true;
|
|
||||||
var ticker = EntitySystem.Get<GameTicking.GameTicker>();
|
|
||||||
ticker.UpdateInfoText();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectRandomMap()
|
public void SelectMapRandom()
|
||||||
{
|
{
|
||||||
var maps = CurrentlyEligibleMaps().ToList();
|
var maps = CurrentlyEligibleMaps().ToList();
|
||||||
_currentMap = _random.Pick(maps);
|
_selectedMap = _random.Pick(maps);
|
||||||
_currentMapForced = false;
|
|
||||||
var ticker = EntitySystem.Get<GameTicking.GameTicker>();
|
|
||||||
ticker.UpdateInfoText();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameMapPrototype GetSelectedMap()
|
public void SelectMapFromRotationQueue(bool markAsPlayed = false)
|
||||||
{
|
{
|
||||||
if (!_mapRotationEnabled || _currentMapForced)
|
var map = GetFirstInRotationQueue();
|
||||||
return _currentMap;
|
|
||||||
return SelectMapInQueue() ?? CurrentlyEligibleMaps().First();
|
|
||||||
}
|
|
||||||
|
|
||||||
public GameMapPrototype GetSelectedMapChecked(bool loud = false, bool markAsPlayed = false)
|
_selectedMap = map;
|
||||||
{
|
|
||||||
if (!_currentMapForced && !IsMapEligible(GetSelectedMap()))
|
|
||||||
{
|
|
||||||
var oldMap = GetSelectedMap().MapName;
|
|
||||||
SelectRandomMap();
|
|
||||||
if (loud)
|
|
||||||
{
|
|
||||||
_chatManager.DispatchServerAnnouncement(
|
|
||||||
Loc.GetString("gamemap-could-not-use-map-error",
|
|
||||||
("oldMap", oldMap), ("newMap", GetSelectedMap().MapName)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var map = GetSelectedMap();
|
|
||||||
|
|
||||||
if (markAsPlayed)
|
if (markAsPlayed)
|
||||||
EnqueueMap(map.ID);
|
EnqueueMap(map.ID);
|
||||||
return map;
|
}
|
||||||
|
|
||||||
|
public void SelectMapByConfigRules()
|
||||||
|
{
|
||||||
|
if (_mapRotationEnabled)
|
||||||
|
{
|
||||||
|
Logger.InfoS("mapsel", "selecting the next map from the rotation queue");
|
||||||
|
SelectMapFromRotationQueue(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.InfoS("mapsel", "selecting a random map");
|
||||||
|
SelectMapRandom();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CheckMapExists(string gameMap)
|
public bool CheckMapExists(string gameMap)
|
||||||
@@ -168,7 +171,7 @@ public sealed class GameMapManager : IGameMapManager
|
|||||||
return _prototypeManager.TryIndex(gameMap, out map);
|
return _prototypeManager.TryIndex(gameMap, out map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetMapQueuePriority(string gameMapProtoName)
|
private int GetMapRotationQueuePriority(string gameMapProtoName)
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
foreach (var map in _previousMaps.Reverse())
|
foreach (var map in _previousMaps.Reverse())
|
||||||
@@ -177,22 +180,28 @@ public sealed class GameMapManager : IGameMapManager
|
|||||||
return i;
|
return i;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _mapQueueDepth;
|
return _mapQueueDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameMapPrototype? SelectMapInQueue()
|
private GameMapPrototype GetFirstInRotationQueue()
|
||||||
{
|
{
|
||||||
Logger.InfoS("mapsel", string.Join(", ", _previousMaps));
|
Logger.InfoS("mapsel", $"map queue: {string.Join(", ", _previousMaps)}");
|
||||||
|
|
||||||
var eligible = CurrentlyEligibleMaps()
|
var eligible = CurrentlyEligibleMaps()
|
||||||
.Select(x => (proto: x, weight: GetMapQueuePriority(x.ID)))
|
.Select(x => (proto: x, weight: GetMapRotationQueuePriority(x.ID)))
|
||||||
.OrderByDescending(x => x.weight).ToArray();
|
.OrderByDescending(x => x.weight)
|
||||||
Logger.InfoS("mapsel", string.Join(", ", eligible.Select(x => (x.proto.ID, x.weight))));
|
.ToArray();
|
||||||
if (eligible.Length is 0)
|
|
||||||
return null;
|
Logger.InfoS("mapsel", $"eligible queue: {string.Join(", ", eligible.Select(x => (x.proto.ID, x.weight)))}");
|
||||||
|
|
||||||
|
// YML "should" be configured with at least one fallback map
|
||||||
|
Debug.Assert(eligible.Length != 0, $"couldn't select a map with {nameof(GetFirstInRotationQueue)}()! No eligible maps and no fallback maps!");
|
||||||
|
|
||||||
var weight = eligible[0].weight;
|
var weight = eligible[0].weight;
|
||||||
return eligible.Where(x => x.Item2 == weight).OrderBy(x => x.proto.ID).First().proto;
|
return eligible.Where(x => x.Item2 == weight)
|
||||||
|
.OrderBy(x => x.proto.ID)
|
||||||
|
.First()
|
||||||
|
.proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnqueueMap(string mapProtoName)
|
private void EnqueueMap(string mapProtoName)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Content.Server.Station;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Content.Server.Maps;
|
namespace Content.Server.Maps;
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ namespace Content.Server.Maps;
|
|||||||
/// Make a new partial for your fancy new feature, it'll save you time later.
|
/// Make a new partial for your fancy new feature, it'll save you time later.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[Prototype("gameMap"), PublicAPI]
|
[Prototype("gameMap"), PublicAPI]
|
||||||
|
[DebuggerDisplay("GameMapPrototype [{ID} - {MapName}]")]
|
||||||
public sealed partial class GameMapPrototype : IPrototype
|
public sealed partial class GameMapPrototype : IPrototype
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|||||||
@@ -26,35 +26,45 @@ public interface IGameMapManager
|
|||||||
IEnumerable<GameMapPrototype> AllMaps();
|
IEnumerable<GameMapPrototype> AllMaps();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to select the given map.
|
/// Gets the currently selected map
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>selected map</returns>
|
||||||
|
GameMapPrototype? GetSelectedMap();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the selected map, if any
|
||||||
|
/// </summary>
|
||||||
|
void ClearSelectedMap();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to select the given map, checking eligibility criteria
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="gameMap">map prototype</param>
|
/// <param name="gameMap">map prototype</param>
|
||||||
/// <returns>success or failure</returns>
|
/// <returns>success or failure</returns>
|
||||||
bool TrySelectMap(string gameMap);
|
bool TrySelectMapIfEligible(string gameMap);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Forces the given map, making sure the game map manager won't reselect if conditions are no longer met at round restart.
|
/// Select the given map regardless of eligibility
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="gameMap">map prototype</param>
|
/// <param name="gameMap">map prototype</param>
|
||||||
/// <returns>success or failure</returns>
|
/// <returns>success or failure</returns>
|
||||||
void ForceSelectMap(string gameMap);
|
void SelectMap(string gameMap);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Selects a random map.
|
/// Selects a random map eligible map
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SelectRandomMap();
|
void SelectMapRandom();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the currently selected map, without double-checking if it can be used.
|
/// Selects the map at the front of the rotation queue
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>selected map</returns>
|
/// <returns>selected map</returns>
|
||||||
GameMapPrototype GetSelectedMap();
|
void SelectMapFromRotationQueue(bool markAsPlayed = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the currently selected map, double-checking if it can be used.
|
/// Selects the map by following rules set in the config
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>selected map</returns>
|
public void SelectMapByConfigRules();
|
||||||
GameMapPrototype GetSelectedMapChecked(bool loud = false, bool markAsPlayed = false);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the given map exists
|
/// Checks if the given map exists
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Content.Server.Voting.Managers
|
|||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(voteType), voteType, null);
|
throw new ArgumentOutOfRangeException(nameof(voteType), voteType, null);
|
||||||
}
|
}
|
||||||
var ticker = EntitySystem.Get<GameTicker>();
|
var ticker = _entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
|
||||||
ticker.UpdateInfoText();
|
ticker.UpdateInfoText();
|
||||||
TimeoutStandardVote(voteType);
|
TimeoutStandardVote(voteType);
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,8 @@ namespace Content.Server.Voting.Managers
|
|||||||
if (total > 0 && votesYes / (float) total >= ratioRequired)
|
if (total > 0 && votesYes / (float) total >= ratioRequired)
|
||||||
{
|
{
|
||||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("ui-vote-restart-succeeded"));
|
_chatManager.DispatchServerAnnouncement(Loc.GetString("ui-vote-restart-succeeded"));
|
||||||
EntitySystem.Get<RoundEndSystem>().EndRound();
|
var roundEnd = _entityManager.EntitySysManager.GetEntitySystem<RoundEndSystem>();
|
||||||
|
roundEnd.EndRound();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -141,8 +142,8 @@ namespace Content.Server.Voting.Managers
|
|||||||
_chatManager.DispatchServerAnnouncement(
|
_chatManager.DispatchServerAnnouncement(
|
||||||
Loc.GetString("ui-vote-gamemode-win", ("winner", Loc.GetString(presets[picked]))));
|
Loc.GetString("ui-vote-gamemode-win", ("winner", Loc.GetString(presets[picked]))));
|
||||||
}
|
}
|
||||||
|
var ticker = _entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
|
||||||
EntitySystem.Get<GameTicker>().SetGamePreset(picked);
|
ticker.SetGamePreset(picked);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +188,18 @@ namespace Content.Server.Voting.Managers
|
|||||||
Loc.GetString("ui-vote-map-win", ("winner", maps[picked])));
|
Loc.GetString("ui-vote-map-win", ("winner", maps[picked])));
|
||||||
}
|
}
|
||||||
|
|
||||||
_gameMapManager.TrySelectMap(picked.ID);
|
var ticker = _entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
|
||||||
|
if (ticker.RunLevel == GameRunLevel.PreRoundLobby)
|
||||||
|
{
|
||||||
|
if (_gameMapManager.TrySelectMapIfEligible(picked.ID))
|
||||||
|
{
|
||||||
|
ticker.UpdateInfoText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_chatManager.DispatchServerAnnouncement(Loc.GetString("ui-vote-map-notlobby"));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace Content.Server.Voting.Managers
|
|||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IGameMapManager _gameMapManager = default!;
|
[Dependency] private readonly IGameMapManager _gameMapManager = default!;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
|
||||||
private int _nextVoteId = 1;
|
private int _nextVoteId = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ namespace Content.Shared.CCVar
|
|||||||
/// Controls the game map prototype to load. SS14 stores these prototypes in Prototypes/Maps.
|
/// Controls the game map prototype to load. SS14 stores these prototypes in Prototypes/Maps.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<string>
|
public static readonly CVarDef<string>
|
||||||
GameMap = CVarDef.Create("game.map", "Saltern", CVar.SERVERONLY);
|
GameMap = CVarDef.Create("game.map", string.Empty, CVar.SERVERONLY);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prototype to use for map pool.
|
/// Prototype to use for map pool.
|
||||||
@@ -196,12 +196,6 @@ namespace Content.Shared.CCVar
|
|||||||
public static readonly CVarDef<string>
|
public static readonly CVarDef<string>
|
||||||
GameMapPool = CVarDef.Create("game.map_pool", "DefaultMapPool", CVar.SERVERONLY);
|
GameMapPool = CVarDef.Create("game.map_pool", "DefaultMapPool", CVar.SERVERONLY);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Controls if the game should obey map criteria or not. Overriden if a map vote or similar occurs.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly CVarDef<bool>
|
|
||||||
GameMapForced = CVarDef.Create("game.mapforced", false, CVar.SERVERONLY);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The depth of the queue used to calculate which map is next in rotation.
|
/// The depth of the queue used to calculate which map is next in rotation.
|
||||||
/// This is how long the game "remembers" that some map was put in play. Default is 16 rounds.
|
/// This is how long the game "remembers" that some map was put in play. Default is 16 rounds.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ game-ticker-get-info-text = Hi and welcome to [color=white]Space Station 14![/co
|
|||||||
The current map is: [color=white]{$mapName}[/color]
|
The current map is: [color=white]{$mapName}[/color]
|
||||||
The current game mode is: [color=white]{$gmTitle}[/color]
|
The current game mode is: [color=white]{$gmTitle}[/color]
|
||||||
>[color=yellow]{$desc}[/color]
|
>[color=yellow]{$desc}[/color]
|
||||||
game-ticker-no-map-selected = [color=red]No map selected![/color]
|
game-ticker-no-map-selected = [color=yellow]Map not yet selected![/color]
|
||||||
game-ticker-player-no-jobs-available-when-joining = When attempting to join to the game, no jobs were available.
|
game-ticker-player-no-jobs-available-when-joining = When attempting to join to the game, no jobs were available.
|
||||||
|
|
||||||
# Displayed in chat to admins when a player joins
|
# Displayed in chat to admins when a player joins
|
||||||
|
|||||||
@@ -17,3 +17,4 @@ ui-vote-gamemode-win = { $winner } won the gamemode vote!
|
|||||||
ui-vote-map-title = Next map
|
ui-vote-map-title = Next map
|
||||||
ui-vote-map-tie = Tie for map vote! Picking... { $picked }
|
ui-vote-map-tie = Tie for map vote! Picking... { $picked }
|
||||||
ui-vote-map-win = { $winner } won the map vote!
|
ui-vote-map-win = { $winner } won the map vote!
|
||||||
|
ui-vote-map-notlobby = Voting for maps is only valid in the pre-round lobby!
|
||||||
Reference in New Issue
Block a user