Refactor GameSpeed setting
*Remove internal GameSpeed defaults Enforce setting values explicitly all the time Require definition of a DefaultSpeed *Remove Global.Timestep default *Remove the hacky Timestep/OrderLatency setting via LobbyInfo *Fix shellmaps ignoring mod-defined gamespeeds *Make DateTimeGlobal use the MapOptions gamespeed
This commit is contained in:
@@ -162,8 +162,12 @@ namespace OpenRA
|
||||
|
||||
using (new PerfTimer("PrepareMap"))
|
||||
map = ModData.PrepareMap(mapUID);
|
||||
|
||||
using (new PerfTimer("NewWorld"))
|
||||
{
|
||||
OrderManager.World = new World(ModData, map, OrderManager, type);
|
||||
OrderManager.FramesAhead = OrderManager.World.OrderLatency;
|
||||
}
|
||||
|
||||
OrderManager.World.GameOver += FinishBenchmark;
|
||||
|
||||
@@ -581,7 +585,11 @@ namespace OpenRA
|
||||
Cursor.Tick();
|
||||
}
|
||||
|
||||
var worldTimestep = world == null ? Ui.Timestep : world.IsLoadingGameSave ? 1 : world.Timestep;
|
||||
var worldTimestep = world == null ? Ui.Timestep :
|
||||
world.IsLoadingGameSave ? 1 :
|
||||
world.IsReplay ? world.ReplayTimestep :
|
||||
world.Timestep;
|
||||
|
||||
var worldTickDelta = tick - orderManager.LastTickTime;
|
||||
if (worldTimestep != 0 && worldTickDelta >= worldTimestep)
|
||||
{
|
||||
@@ -776,9 +784,14 @@ namespace OpenRA
|
||||
|
||||
while (state == RunStatus.Running)
|
||||
{
|
||||
// Ideal time between logic updates. Timestep = 0 means the game is paused
|
||||
// but we still call LogicTick() because it handles pausing internally.
|
||||
var logicInterval = worldRenderer != null && worldRenderer.World.Timestep != 0 ? worldRenderer.World.Timestep : Ui.Timestep;
|
||||
var logicInterval = Ui.Timestep;
|
||||
var logicWorld = worldRenderer?.World;
|
||||
|
||||
// ReplayTimestep = 0 means the replay is paused: we need to keep logicInterval as UI.Timestep to avoid breakage
|
||||
if (logicWorld != null && !(logicWorld.IsReplay && logicWorld.ReplayTimestep == 0))
|
||||
logicInterval = logicWorld.IsLoadingGameSave ? 1 :
|
||||
logicWorld.IsReplay ? logicWorld.ReplayTimestep :
|
||||
logicWorld.Timestep;
|
||||
|
||||
// Ideal time between screen updates
|
||||
var maxFramerate = Settings.Graphics.CapFramerate ? Settings.Graphics.MaxFramerate.Clamp(1, 1000) : 1000;
|
||||
|
||||
@@ -10,26 +10,49 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class GameSpeed
|
||||
{
|
||||
public readonly string Name = "Default";
|
||||
public readonly int Timestep = 40;
|
||||
public readonly int OrderLatency = 3;
|
||||
[FieldLoader.Require]
|
||||
public readonly string Name;
|
||||
|
||||
[FieldLoader.Require]
|
||||
public readonly int Timestep;
|
||||
|
||||
[FieldLoader.Require]
|
||||
public readonly int OrderLatency;
|
||||
}
|
||||
|
||||
public class GameSpeeds : IGlobalModData
|
||||
{
|
||||
[FieldLoader.Require]
|
||||
public readonly string DefaultSpeed;
|
||||
|
||||
[FieldLoader.LoadUsing(nameof(LoadSpeeds))]
|
||||
public readonly Dictionary<string, GameSpeed> Speeds;
|
||||
|
||||
static object LoadSpeeds(MiniYaml y)
|
||||
{
|
||||
var ret = new Dictionary<string, GameSpeed>();
|
||||
foreach (var node in y.Nodes)
|
||||
ret.Add(node.Key, FieldLoader.Load<GameSpeed>(node.Value));
|
||||
var speedsNode = y.Nodes.FirstOrDefault(n => n.Key == "Speeds");
|
||||
if (speedsNode == null)
|
||||
throw new YamlException("Error parsing GameSpeeds: Missing Speeds node!");
|
||||
|
||||
foreach (var node in speedsNode.Value.Nodes)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret.Add(node.Key, FieldLoader.Load<GameSpeed>(node.Value));
|
||||
}
|
||||
catch (FieldLoader.MissingFieldsException e)
|
||||
{
|
||||
var label = e.Missing.Length > 1 ? "Required properties missing" : "Required property missing";
|
||||
throw new YamlException("Error parsing GameSpeed {0}: {1}: {2}".F(node.Key, label, e.Missing.JoinWith(", ")));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,10 @@ namespace OpenRA.Network
|
||||
|
||||
Queue<Chunk> chunks = new Queue<Chunk>();
|
||||
List<byte[]> sync = new List<byte[]>();
|
||||
|
||||
readonly int orderLatency;
|
||||
int ordersFrame;
|
||||
|
||||
Dictionary<int, int> lastClientsFrame = new Dictionary<int, int>();
|
||||
|
||||
public int LocalClientId => -1;
|
||||
@@ -122,7 +125,10 @@ namespace OpenRA.Network
|
||||
}
|
||||
}
|
||||
|
||||
ordersFrame = LobbyInfo.GlobalSettings.OrderLatency;
|
||||
var gameSpeeds = Game.ModData.Manifest.Get<GameSpeeds>();
|
||||
var gameSpeedName = LobbyInfo.GlobalSettings.OptionOrDefault("gamespeed", gameSpeeds.DefaultSpeed);
|
||||
orderLatency = gameSpeeds.Speeds[gameSpeedName].OrderLatency;
|
||||
ordersFrame = orderLatency;
|
||||
}
|
||||
|
||||
// Do nothing: ignore locally generated orders
|
||||
@@ -137,7 +143,7 @@ namespace OpenRA.Network
|
||||
sync.Add(ms.GetBuffer());
|
||||
|
||||
// Store the current frame so Receive() can return the next chunk of orders.
|
||||
ordersFrame = frame + LobbyInfo.GlobalSettings.OrderLatency;
|
||||
ordersFrame = frame + orderLatency;
|
||||
}
|
||||
|
||||
public void Receive(Action<int, byte[]> packetFn)
|
||||
|
||||
@@ -222,8 +222,6 @@ namespace OpenRA.Network
|
||||
{
|
||||
public string ServerName;
|
||||
public string Map;
|
||||
public int Timestep = 40;
|
||||
public int OrderLatency = 3; // net tick frames (x 120 = ms)
|
||||
public int RandomSeed = 0;
|
||||
public bool AllowSpectators = true;
|
||||
public string GameUid;
|
||||
|
||||
@@ -254,7 +254,6 @@ namespace OpenRA.Network
|
||||
case "SyncInfo":
|
||||
{
|
||||
orderManager.LobbyInfo = Session.Deserialize(order.TargetString);
|
||||
SetOrderLag(orderManager);
|
||||
Game.SyncLobbyInfo();
|
||||
break;
|
||||
}
|
||||
@@ -304,7 +303,6 @@ namespace OpenRA.Network
|
||||
orderManager.LobbyInfo.GlobalSettings = Session.Global.Deserialize(node.Value);
|
||||
}
|
||||
|
||||
SetOrderLag(orderManager);
|
||||
Game.SyncLobbyInfo();
|
||||
break;
|
||||
}
|
||||
@@ -354,14 +352,5 @@ namespace OpenRA.Network
|
||||
if (world.OrderValidators.All(vo => vo.OrderValidation(orderManager, world, clientId, order)))
|
||||
order.Subject.ResolveOrder(order);
|
||||
}
|
||||
|
||||
static void SetOrderLag(OrderManager o)
|
||||
{
|
||||
if (o.FramesAhead != o.LobbyInfo.GlobalSettings.OrderLatency && !o.GameStarted)
|
||||
{
|
||||
o.FramesAhead = o.LobbyInfo.GlobalSettings.OrderLatency;
|
||||
Log.Write("server", "Order lag is now {0} frames.", o.LobbyInfo.GlobalSettings.OrderLatency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1200,10 +1200,6 @@ namespace OpenRA.Server
|
||||
DropClient(c);
|
||||
}
|
||||
|
||||
// HACK: Turn down the latency if there is only one real player
|
||||
if (LobbyInfo.NonBotClients.Count() == 1)
|
||||
LobbyInfo.GlobalSettings.OrderLatency = 1;
|
||||
|
||||
// Enable game saves for singleplayer missions only
|
||||
// TODO: Enable for multiplayer (non-dedicated servers only) once the lobby UI has been created
|
||||
LobbyInfo.GlobalSettings.GameSavesEnabled = Type != ServerType.Dedicated && LobbyInfo.NonBotClients.Count() == 1;
|
||||
|
||||
@@ -36,7 +36,12 @@ namespace OpenRA
|
||||
|
||||
readonly Queue<Action<World>> frameEndActions = new Queue<Action<World>>();
|
||||
|
||||
public int Timestep;
|
||||
public readonly GameSpeed GameSpeed;
|
||||
|
||||
public readonly int Timestep;
|
||||
public readonly int OrderLatency;
|
||||
|
||||
public int ReplayTimestep;
|
||||
|
||||
internal readonly OrderManager OrderManager;
|
||||
public Session LobbyInfo => OrderManager.LobbyInfo;
|
||||
@@ -180,7 +185,18 @@ namespace OpenRA
|
||||
OrderManager = orderManager;
|
||||
orderGenerator = new UnitOrderGenerator();
|
||||
Map = map;
|
||||
Timestep = orderManager.LobbyInfo.GlobalSettings.Timestep;
|
||||
|
||||
var gameSpeeds = modData.Manifest.Get<GameSpeeds>();
|
||||
var gameSpeedName = orderManager.LobbyInfo.GlobalSettings.OptionOrDefault("gamespeed", gameSpeeds.DefaultSpeed);
|
||||
GameSpeed = gameSpeeds.Speeds[gameSpeedName];
|
||||
|
||||
Timestep = ReplayTimestep = GameSpeed.Timestep;
|
||||
OrderLatency = GameSpeed.OrderLatency;
|
||||
|
||||
// HACK: Turn down the latency if there is only one real player/spectator
|
||||
if (orderManager.LobbyInfo.NonBotClients.Count() == 1)
|
||||
OrderLatency = 1;
|
||||
|
||||
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
||||
LocalRandom = new MersenneTwister();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user