Rework MapPreview custom rule handling.

The previous asynchronous approach did not work particularly well,
leading to large janks when switching to custom maps or opening the
mission browser.

This commit introduces two key changes:

 * Rule loading for WorldActorInfo and PlayerActorInfo is made
   synchronous, in preparation for the next commit which will
   significantly optimize this path.
 * The full ruleset loading, which is required for map validation,
   is moved to the server-side and managed by a new ServerMapStatusCache.
   The previous syntax check is expanded to include the ability to run
   lint tests.
This commit is contained in:
Paul Chote
2021-04-06 13:53:38 +01:00
committed by teinarss
parent 61d64287e1
commit 0bbb32e8ac
17 changed files with 373 additions and 229 deletions

View File

@@ -61,6 +61,7 @@ namespace OpenRA.Server
// Managed by LobbyCommands
public MapPreview Map;
public readonly MapStatusCache MapStatusCache;
public GameSave GameSave = null;
readonly int randomSeed;
@@ -170,6 +171,17 @@ namespace OpenRA.Server
}.Serialize());
}
void MapStatusChanged(string uid, Session.MapStatus status)
{
lock (LobbyInfo)
{
if (LobbyInfo.GlobalSettings.Map == uid)
LobbyInfo.GlobalSettings.MapStatus = status;
SyncLobbyInfo();
}
}
public Server(List<IPEndPoint> endpoints, ServerSettings settings, ModData modData, ServerType type)
{
Log.AddChannel("server", "server.log", true);
@@ -229,12 +241,16 @@ namespace OpenRA.Server
serverTraits.TrimExcess();
Map = ModData.MapCache[settings.Map];
MapStatusCache = new MapStatusCache(modData, MapStatusChanged, type == ServerType.Dedicated && settings.EnableLintChecks);
LobbyInfo = new Session
{
GlobalSettings =
{
RandomSeed = randomSeed,
Map = settings.Map,
Map = Map.Uid,
MapStatus = Session.MapStatus.Unknown,
ServerName = settings.Name,
EnableSingleplayer = settings.EnableSingleplayer || Type != ServerType.Dedicated,
EnableSyncReports = settings.EnableSyncReports,
@@ -254,6 +270,8 @@ namespace OpenRA.Server
new Thread(_ =>
{
// Initial status is set off the main thread to avoid triggering a load screen when joining a skirmish game
LobbyInfo.GlobalSettings.MapStatus = MapStatusCache[Map];
foreach (var t in serverTraits.WithInterface<INotifyServerStart>())
t.ServerStarted(this);
@@ -541,7 +559,7 @@ namespace OpenRA.Server
SendOrderTo(newConn, "Message", motd);
}
if (Map.DefinesUnsafeCustomRules)
if ((LobbyInfo.GlobalSettings.MapStatus & Session.MapStatus.UnsafeCustomRules) != 0)
SendOrderTo(newConn, "Message", "This map contains custom rules. Game experience may change.");
if (!LobbyInfo.GlobalSettings.EnableSingleplayer)