Initial commit: OpenRA game engine
Fork from OpenRA/OpenRA with one-click launch script (start-ra.cmd) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
106
OpenRA.Game/Server/MapStatusCache.cs
Normal file
106
OpenRA.Game/Server/MapStatusCache.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Server
|
||||
{
|
||||
public interface ILintServerMapPass { void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules); }
|
||||
|
||||
public class MapStatusCache
|
||||
{
|
||||
readonly Dictionary<MapPreview, Session.MapStatus> cache = [];
|
||||
readonly Action<string, Session.MapStatus> onStatusChanged;
|
||||
readonly bool enableRemoteLinting;
|
||||
readonly ModData modData;
|
||||
|
||||
public MapStatusCache(ModData modData, Action<string, Session.MapStatus> onStatusChanged, bool enableRemoteLinting)
|
||||
{
|
||||
this.modData = modData;
|
||||
this.enableRemoteLinting = enableRemoteLinting;
|
||||
this.onStatusChanged = onStatusChanged;
|
||||
}
|
||||
|
||||
void RunLintTests(MapPreview map, Ruleset rules)
|
||||
{
|
||||
var status = cache[map];
|
||||
var failed = false;
|
||||
|
||||
void OnLintFailure(string message)
|
||||
{
|
||||
Log.Write("server", $"Map {map.Title} failed lint with error: {message}");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
void OnLintWarning(string _) { }
|
||||
|
||||
foreach (var customMapPassType in modData.ObjectCreator.GetTypesImplementing<ILintServerMapPass>())
|
||||
{
|
||||
try
|
||||
{
|
||||
var customMapPass = (ILintServerMapPass)modData.ObjectCreator.CreateBasic(customMapPassType);
|
||||
customMapPass.Run(OnLintFailure, OnLintWarning, modData, map, rules);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
OnLintFailure(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
status &= ~Session.MapStatus.Validating;
|
||||
status |= failed ? Session.MapStatus.Incompatible : Session.MapStatus.Playable;
|
||||
|
||||
cache[map] = status;
|
||||
onStatusChanged?.Invoke(map.Uid, status);
|
||||
}
|
||||
|
||||
public Session.MapStatus this[MapPreview map]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cache.TryGetValue(map, out var status))
|
||||
return status;
|
||||
|
||||
Ruleset rules = null;
|
||||
try
|
||||
{
|
||||
rules = map.LoadRuleset();
|
||||
|
||||
// Locally installed maps are assumed to not require linting
|
||||
status = enableRemoteLinting && map.Status != MapStatus.Available ? Session.MapStatus.Validating : Session.MapStatus.Playable;
|
||||
if (map.DefinesUnsafeCustomRules())
|
||||
status |= Session.MapStatus.UnsafeCustomRules;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Write("server", $"Failed to load rules for `{map.Title}` with error: {e.Message}");
|
||||
status = Session.MapStatus.Incompatible;
|
||||
}
|
||||
|
||||
if (map.Players.Players.Count > MapPlayers.MaximumPlayerCount)
|
||||
{
|
||||
Log.Write("server", $"Failed to load `{map.Title}`: Player count exceeds maximum ({map.Players.Players.Count}/{MapPlayers.MaximumPlayerCount}).");
|
||||
status = Session.MapStatus.Incompatible;
|
||||
}
|
||||
|
||||
cache[map] = status;
|
||||
|
||||
if ((status & Session.MapStatus.Validating) != 0)
|
||||
ThreadPool.QueueUserWorkItem(_ => RunLintTests(map, rules));
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user