Makes map vote and roundstart smart about player count. (#5418)
* Makes map vote and roundstart smart about player count. No more Saltern with 30 players, or Knight Ship with 50. * a typo * Address reviews. * Localized.
This commit is contained in:
@@ -89,6 +89,7 @@ namespace Content.Client.Entry
|
|||||||
prototypes.RegisterIgnore("objective");
|
prototypes.RegisterIgnore("objective");
|
||||||
prototypes.RegisterIgnore("holiday");
|
prototypes.RegisterIgnore("holiday");
|
||||||
prototypes.RegisterIgnore("aiFaction");
|
prototypes.RegisterIgnore("aiFaction");
|
||||||
|
prototypes.RegisterIgnore("gameMap");
|
||||||
prototypes.RegisterIgnore("behaviorSet");
|
prototypes.RegisterIgnore("behaviorSet");
|
||||||
prototypes.RegisterIgnore("advertisementsPack");
|
prototypes.RegisterIgnore("advertisementsPack");
|
||||||
prototypes.RegisterIgnore("metabolizerType");
|
prototypes.RegisterIgnore("metabolizerType");
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ namespace Content.IntegrationTests
|
|||||||
(CCVars.HolidaysEnabled.Name, "false", false),
|
(CCVars.HolidaysEnabled.Name, "false", false),
|
||||||
|
|
||||||
// Avoid loading a large map by default for integration tests if none has been specified.
|
// Avoid loading a large map by default for integration tests if none has been specified.
|
||||||
(CCVars.GameMap.Name, "Maps/Test/empty.yml", true)
|
(CCVars.GameMap.Name, "empty", true),
|
||||||
|
|
||||||
|
// Makes sure IGameMapManager actually listens.
|
||||||
|
(CCVars.GameMapForced.Name, "true", true)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void SetServerTestCvars(IntegrationOptions options)
|
private static void SetServerTestCvars(IntegrationOptions options)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Content.IntegrationTests.Tests.Commands
|
|||||||
{
|
{
|
||||||
CVarOverrides =
|
CVarOverrides =
|
||||||
{
|
{
|
||||||
[CCVars.GameMap.Name] = "Maps/saltern.yml"
|
[CCVars.GameMap.Name] = "saltern"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Content.Server.EUI;
|
|||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Holiday.Interfaces;
|
using Content.Server.Holiday.Interfaces;
|
||||||
using Content.Server.IoC;
|
using Content.Server.IoC;
|
||||||
|
using Content.Server.Maps;
|
||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
using Content.Server.Sandbox;
|
using Content.Server.Sandbox;
|
||||||
@@ -91,6 +92,7 @@ namespace Content.Server.Entry
|
|||||||
IoCManager.Resolve<IAfkManager>().Initialize();
|
IoCManager.Resolve<IAfkManager>().Initialize();
|
||||||
_euiManager.Initialize();
|
_euiManager.Initialize();
|
||||||
|
|
||||||
|
IoCManager.Resolve<IGameMapManager>().Initialize();
|
||||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GameTicker>().PostInitialize();
|
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GameTicker>().PostInitialize();
|
||||||
IoCManager.Resolve<IBqlQueryManager>().DoAutoRegistrations();
|
IoCManager.Resolve<IBqlQueryManager>().DoAutoRegistrations();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
|
using Content.Server.Maps;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -24,10 +25,10 @@ namespace Content.Server.GameTicking.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg = IoCManager.Resolve<IConfigurationManager>();
|
var gameMap = IoCManager.Resolve<IGameMapManager>();
|
||||||
var name = args[0];
|
var name = args[0];
|
||||||
|
|
||||||
cfg.SetCVar(CCVars.GameMap, name);
|
gameMap.ForceSelectMap(name);
|
||||||
shell.WriteLine(Loc.GetString("forcemap-command-success", ("map", name)));
|
shell.WriteLine(Loc.GetString("forcemap-command-success", ("map", name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ namespace Content.Server.GameTicking
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool DummyTicker { get; private set; } = false;
|
public bool DummyTicker { get; private set; } = false;
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public string ChosenMap { get; private set; } = string.Empty;
|
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public TimeSpan LobbyDuration { get; private set; } = TimeSpan.Zero;
|
public TimeSpan LobbyDuration { get; private set; } = TimeSpan.Zero;
|
||||||
|
|
||||||
@@ -34,7 +31,6 @@ namespace Content.Server.GameTicking
|
|||||||
{
|
{
|
||||||
_configurationManager.OnValueChanged(CCVars.GameLobbyEnabled, value => LobbyEnabled = value, true);
|
_configurationManager.OnValueChanged(CCVars.GameLobbyEnabled, value => LobbyEnabled = value, true);
|
||||||
_configurationManager.OnValueChanged(CCVars.GameDummyTicker, value => DummyTicker = value, true);
|
_configurationManager.OnValueChanged(CCVars.GameDummyTicker, value => DummyTicker = value, true);
|
||||||
_configurationManager.OnValueChanged(CCVars.GameMap, value => ChosenMap = value, true);
|
|
||||||
_configurationManager.OnValueChanged(CCVars.GameLobbyDuration, value => LobbyDuration = TimeSpan.FromSeconds(value), true);
|
_configurationManager.OnValueChanged(CCVars.GameLobbyDuration, value => LobbyDuration = TimeSpan.FromSeconds(value), true);
|
||||||
_configurationManager.OnValueChanged(CCVars.GameDisallowLateJoins,
|
_configurationManager.OnValueChanged(CCVars.GameDisallowLateJoins,
|
||||||
value => { DisallowLateJoin = value; UpdateLateJoinStatus(); UpdateJobsAvailable(); }, true);
|
value => { DisallowLateJoin = value; UpdateLateJoinStatus(); UpdateJobsAvailable(); }, true);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace Content.Server.GameTicking
|
|||||||
{
|
{
|
||||||
DefaultMap = _mapManager.CreateMap();
|
DefaultMap = _mapManager.CreateMap();
|
||||||
var startTime = _gameTiming.RealTime;
|
var startTime = _gameTiming.RealTime;
|
||||||
var map = ChosenMap;
|
var map = _gameMapManager.GetSelectedMapChecked(true).MapPath;
|
||||||
var grid = _mapLoader.LoadBlueprint(DefaultMap, map);
|
var grid = _mapLoader.LoadBlueprint(DefaultMap, map);
|
||||||
|
|
||||||
if (grid == null)
|
if (grid == null)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Maps;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
@@ -85,5 +86,6 @@ namespace Content.Server.GameTicking
|
|||||||
[Dependency] private readonly IBaseServer _baseServer = default!;
|
[Dependency] private readonly IBaseServer _baseServer = default!;
|
||||||
[Dependency] private readonly IWatchdogApi _watchdogApi = default!;
|
[Dependency] private readonly IWatchdogApi _watchdogApi = default!;
|
||||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||||
|
[Dependency] private readonly IGameMapManager _gameMapManager = default!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Content.Server.DeviceNetwork;
|
|||||||
using Content.Server.EUI;
|
using Content.Server.EUI;
|
||||||
using Content.Server.Holiday;
|
using Content.Server.Holiday;
|
||||||
using Content.Server.Holiday.Interfaces;
|
using Content.Server.Holiday.Interfaces;
|
||||||
|
using Content.Server.Maps;
|
||||||
using Content.Server.Module;
|
using Content.Server.Module;
|
||||||
using Content.Server.MoMMI;
|
using Content.Server.MoMMI;
|
||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
@@ -52,6 +53,7 @@ namespace Content.Server.IoC
|
|||||||
IoCManager.Register<INpcBehaviorManager, NpcBehaviorManager>();
|
IoCManager.Register<INpcBehaviorManager, NpcBehaviorManager>();
|
||||||
IoCManager.Register<IPlayerLocator, PlayerLocator>();
|
IoCManager.Register<IPlayerLocator, PlayerLocator>();
|
||||||
IoCManager.Register<IAfkManager, AfkManager>();
|
IoCManager.Register<IAfkManager, AfkManager>();
|
||||||
|
IoCManager.Register<IGameMapManager, GameMapManager>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
120
Content.Server/Maps/GameMapManager.cs
Normal file
120
Content.Server/Maps/GameMapManager.cs
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.Maps
|
||||||
|
{
|
||||||
|
public class GameMapManager : IGameMapManager
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||||
|
|
||||||
|
private GameMapPrototype _currentMap = default!;
|
||||||
|
private bool _currentMapForced;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_configurationManager.OnValueChanged(CCVars.GameMap, value =>
|
||||||
|
{
|
||||||
|
if (TryLookupMap(value, out var map))
|
||||||
|
_currentMap = map;
|
||||||
|
else
|
||||||
|
throw new ArgumentException($"Unknown map prototype {value} was selected!");
|
||||||
|
}, true);
|
||||||
|
_configurationManager.OnValueChanged(CCVars.GameMapForced, value => _currentMapForced = value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<GameMapPrototype> CurrentlyEligibleMaps()
|
||||||
|
{
|
||||||
|
var maps = AllVotableMaps().Where(IsMapEligible).ToArray();
|
||||||
|
|
||||||
|
return maps.Length == 0 ? AllMaps().Where(x => x.Fallback) : maps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<GameMapPrototype> AllVotableMaps()
|
||||||
|
{
|
||||||
|
return _prototypeManager.EnumeratePrototypes<GameMapPrototype>().Where(x => x.Votable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<GameMapPrototype> AllMaps()
|
||||||
|
{
|
||||||
|
return _prototypeManager.EnumeratePrototypes<GameMapPrototype>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TrySelectMap(string gameMap)
|
||||||
|
{
|
||||||
|
if (!TryLookupMap(gameMap, out var map) || !IsMapEligible(map)) return false;
|
||||||
|
|
||||||
|
_currentMap = map;
|
||||||
|
_currentMapForced = false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForceSelectMap(string gameMap)
|
||||||
|
{
|
||||||
|
if (!TryLookupMap(gameMap, out var map))
|
||||||
|
throw new ArgumentException($"The map \"{gameMap}\" is invalid!");
|
||||||
|
_currentMap = map;
|
||||||
|
_currentMapForced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectRandomMap()
|
||||||
|
{
|
||||||
|
var maps = CurrentlyEligibleMaps().ToList();
|
||||||
|
_random.Shuffle(maps);
|
||||||
|
_currentMap = maps[0];
|
||||||
|
_currentMapForced = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameMapPrototype GetSelectedMap()
|
||||||
|
{
|
||||||
|
return _currentMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameMapPrototype GetSelectedMapChecked(bool loud = false)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetSelectedMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckMapExists(string gameMap)
|
||||||
|
{
|
||||||
|
return TryLookupMap(gameMap, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsMapEligible(GameMapPrototype map)
|
||||||
|
{
|
||||||
|
return map.MaxPlayers >= _playerManager.PlayerCount && map.MinPlayers <= _playerManager.PlayerCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryLookupMap(string gameMap, [NotNullWhen(true)] out GameMapPrototype? map)
|
||||||
|
{
|
||||||
|
return _prototypeManager.TryIndex(gameMap, out map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Content.Server/Maps/GameMapPrototype.cs
Normal file
53
Content.Server/Maps/GameMapPrototype.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Server.Maps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Prototype data for a game map.
|
||||||
|
/// </summary>
|
||||||
|
[Prototype("gameMap")]
|
||||||
|
public class GameMapPrototype : IPrototype
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[ViewVariables, DataField("id", required: true)]
|
||||||
|
public string ID { get; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum players for the given map.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("minPlayers", required: true)]
|
||||||
|
public uint MinPlayers { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum players for the given map.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("maxPlayers")]
|
||||||
|
public uint MaxPlayers { get; } = uint.MaxValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the given map.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("mapName", required: true)]
|
||||||
|
public string MapName { get; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Relative directory path to the given map, i.e. `Maps/saltern.yml`
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("mapPath", required: true)]
|
||||||
|
public string MapPath { get; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls if the map can be used as a fallback if no maps are eligible.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("fallback")]
|
||||||
|
public bool Fallback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls if the map can be voted for.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("votable")]
|
||||||
|
public bool Votable { get; } = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
Content.Server/Maps/IGameMapManager.cs
Normal file
68
Content.Server/Maps/IGameMapManager.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Content.Server.Maps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manages which station map will be used for the next round.
|
||||||
|
/// </summary>
|
||||||
|
public interface IGameMapManager
|
||||||
|
{
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all maps eligible to be played right now.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>enumerator of map prototypes</returns>
|
||||||
|
IEnumerable<GameMapPrototype> CurrentlyEligibleMaps();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all maps that can be voted for.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>enumerator of map prototypes</returns>
|
||||||
|
IEnumerable<GameMapPrototype> AllVotableMaps();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all maps.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>enumerator of map prototypes</returns>
|
||||||
|
IEnumerable<GameMapPrototype> AllMaps();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to select the given map.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gameMap">map prototype</param>
|
||||||
|
/// <returns>success or failure</returns>
|
||||||
|
bool TrySelectMap(string gameMap);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Forces the given map, making sure the game map manager won't reselect if conditions are no longer met at round restart.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gameMap">map prototype</param>
|
||||||
|
/// <returns>success or failure</returns>
|
||||||
|
void ForceSelectMap(string gameMap);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selects a random map.
|
||||||
|
/// </summary>
|
||||||
|
void SelectRandomMap();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the currently selected map, without double-checking if it can be used.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>selected map</returns>
|
||||||
|
GameMapPrototype GetSelectedMap();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the currently selected map, double-checking if it can be used.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>selected map</returns>
|
||||||
|
GameMapPrototype GetSelectedMapChecked(bool loud = false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the given map exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gameMap">name of the map</param>
|
||||||
|
/// <returns>existence</returns>
|
||||||
|
bool CheckMapExists(string gameMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
|
using Content.Server.Maps;
|
||||||
using Content.Server.RoundEnd;
|
using Content.Server.RoundEnd;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Voting;
|
using Content.Shared.Voting;
|
||||||
@@ -146,11 +148,7 @@ namespace Content.Server.Voting.Managers
|
|||||||
|
|
||||||
private void CreateMapVote(IPlayerSession? initiator)
|
private void CreateMapVote(IPlayerSession? initiator)
|
||||||
{
|
{
|
||||||
var maps = new Dictionary<string, string>
|
var maps = _gameMapManager.CurrentlyEligibleMaps().ToDictionary(map => map, map => map.MapName);
|
||||||
{
|
|
||||||
["Maps/saltern.yml"] = "Saltern",
|
|
||||||
["Maps/packedstation.yml"] = "PackedStation",
|
|
||||||
};
|
|
||||||
|
|
||||||
var alone = _playerManager.PlayerCount == 1 && initiator != null;
|
var alone = _playerManager.PlayerCount == 1 && initiator != null;
|
||||||
var options = new VoteOptions
|
var options = new VoteOptions
|
||||||
@@ -175,21 +173,21 @@ namespace Content.Server.Voting.Managers
|
|||||||
|
|
||||||
vote.OnFinished += (_, args) =>
|
vote.OnFinished += (_, args) =>
|
||||||
{
|
{
|
||||||
string picked;
|
GameMapPrototype picked;
|
||||||
if (args.Winner == null)
|
if (args.Winner == null)
|
||||||
{
|
{
|
||||||
picked = (string) _random.Pick(args.Winners);
|
picked = (GameMapPrototype) _random.Pick(args.Winners);
|
||||||
_chatManager.DispatchServerAnnouncement(
|
_chatManager.DispatchServerAnnouncement(
|
||||||
Loc.GetString("ui-vote-map-tie", ("picked", maps[picked])));
|
Loc.GetString("ui-vote-map-tie", ("picked", maps[picked])));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
picked = (string) args.Winner;
|
picked = (GameMapPrototype) args.Winner;
|
||||||
_chatManager.DispatchServerAnnouncement(
|
_chatManager.DispatchServerAnnouncement(
|
||||||
Loc.GetString("ui-vote-map-win", ("winner", maps[picked])));
|
Loc.GetString("ui-vote-map-win", ("winner", maps[picked])));
|
||||||
}
|
}
|
||||||
|
|
||||||
_cfg.SetCVar(CCVars.GameMap, picked);
|
_gameMapManager.TrySelectMap(picked.ID);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Content.Server.Administration;
|
|||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.Afk;
|
using Content.Server.Afk;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Maps;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Voting;
|
using Content.Shared.Voting;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
@@ -16,6 +17,7 @@ using Robust.Shared.Enums;
|
|||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
@@ -33,6 +35,7 @@ namespace Content.Server.Voting.Managers
|
|||||||
[Dependency] private readonly IAdminManager _adminMgr = default!;
|
[Dependency] private readonly IAdminManager _adminMgr = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly IAfkManager _afkManager = default!;
|
[Dependency] private readonly IAfkManager _afkManager = default!;
|
||||||
|
[Dependency] private readonly IGameMapManager _gameMapManager = default!;
|
||||||
|
|
||||||
private int _nextVoteId = 1;
|
private int _nextVoteId = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ namespace Content.Shared.CCVar
|
|||||||
GameMaxCharacterSlots = CVarDef.Create("game.maxcharacterslots", 10, CVar.ARCHIVE | CVar.SERVERONLY);
|
GameMaxCharacterSlots = CVarDef.Create("game.maxcharacterslots", 10, CVar.ARCHIVE | CVar.SERVERONLY);
|
||||||
|
|
||||||
public static readonly CVarDef<string>
|
public static readonly CVarDef<string>
|
||||||
GameMap = CVarDef.Create("game.map", "Maps/saltern.yml", CVar.SERVERONLY);
|
GameMap = CVarDef.Create("game.map", "saltern", CVar.SERVERONLY);
|
||||||
|
public static readonly CVarDef<bool>
|
||||||
|
GameMapForced = CVarDef.Create("game.mapforced", false, CVar.SERVERONLY);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether a random position offset will be applied to the station on roundstart.
|
/// Whether a random position offset will be applied to the station on roundstart.
|
||||||
|
|||||||
1
Resources/Locale/en-US/maps/gamemap.ftl
Normal file
1
Resources/Locale/en-US/maps/gamemap.ftl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
gamemap-could-not-use-map-error = Failed to load map {$oldMap} due to it no longer being eligible! Picking {$newMap} instead.
|
||||||
20
Resources/Prototypes/Maps/game.yml
Normal file
20
Resources/Prototypes/Maps/game.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
- type: gameMap
|
||||||
|
id: saltern
|
||||||
|
mapName: Saltern
|
||||||
|
mapPath: Maps/saltern.yml
|
||||||
|
minPlayers: 0
|
||||||
|
maxPlayers: 20
|
||||||
|
fallback: true
|
||||||
|
|
||||||
|
- type: gameMap
|
||||||
|
id: packedstation
|
||||||
|
mapName: Packedstation
|
||||||
|
mapPath: Maps/packedstation.yml
|
||||||
|
minPlayers: 15
|
||||||
|
|
||||||
|
- type: gameMap
|
||||||
|
id: knightship
|
||||||
|
mapName: Knight Ship
|
||||||
|
mapPath: Maps/knightship.yml
|
||||||
|
minPlayers: 0
|
||||||
|
maxPlayers: 8
|
||||||
7
Resources/Prototypes/Maps/test.yml
Normal file
7
Resources/Prototypes/Maps/test.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
- type: gameMap
|
||||||
|
id: empty
|
||||||
|
mapName: Empty
|
||||||
|
mapPath: Maps/Test/empty.yml
|
||||||
|
minPlayers: 0
|
||||||
|
maxPlayers: 0
|
||||||
|
votable: false
|
||||||
Reference in New Issue
Block a user