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:
@@ -431,6 +431,7 @@ namespace OpenRA.Mods.Common.Server
|
||||
|
||||
var oldSlots = server.LobbyInfo.Slots.Keys.ToArray();
|
||||
server.Map = server.ModData.MapCache[server.LobbyInfo.GlobalSettings.Map];
|
||||
server.LobbyInfo.GlobalSettings.MapStatus = server.MapStatusCache[server.Map];
|
||||
|
||||
server.LobbyInfo.Slots = server.Map.Players.Players
|
||||
.Select(p => MakeSlotFromPlayerReference(p.Value))
|
||||
@@ -492,7 +493,7 @@ namespace OpenRA.Mods.Common.Server
|
||||
|
||||
server.SendMessage("{0} changed the map to {1}.".F(client.Name, server.Map.Title));
|
||||
|
||||
if (server.Map.DefinesUnsafeCustomRules)
|
||||
if ((server.LobbyInfo.GlobalSettings.MapStatus & Session.MapStatus.UnsafeCustomRules) != 0)
|
||||
server.SendMessage("This map contains custom rules. Game experience may change.");
|
||||
|
||||
if (!server.LobbyInfo.GlobalSettings.EnableSingleplayer)
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
readonly TabCompletionLogic tabCompletion = new TabCompletionLogic();
|
||||
|
||||
MapPreview map;
|
||||
Session.MapStatus mapStatus;
|
||||
|
||||
bool addBotOnMapLoad;
|
||||
bool disableTeamChat;
|
||||
bool insufficientPlayerSpawns;
|
||||
@@ -67,6 +69,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
readonly string chatLineSound = ChromeMetrics.Get<string>("ChatLineSound");
|
||||
|
||||
bool MapIsPlayable => (mapStatus & Session.MapStatus.Playable) == Session.MapStatus.Playable;
|
||||
|
||||
// Listen for connection failures
|
||||
void ConnectionStateChanged(OrderManager om)
|
||||
{
|
||||
@@ -131,7 +135,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var mapContainer = Ui.LoadWidget("MAP_PREVIEW", lobby.Get("MAP_PREVIEW_ROOT"), new WidgetArgs
|
||||
{
|
||||
{ "orderManager", orderManager },
|
||||
{ "getMap", (Func<MapPreview>)(() => map) },
|
||||
{ "getMap", (Func<(MapPreview, Session.MapStatus)>)(() => (map, mapStatus)) },
|
||||
{
|
||||
"onMouseDown", (Action<MapPreviewWidget, MapPreview, MouseInput>)((preview, mapPreview, mi) =>
|
||||
LobbyUtils.SelectSpawnPoint(orderManager, preview, mapPreview, mi))
|
||||
@@ -163,8 +167,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
var gameStarting = false;
|
||||
Func<bool> configurationDisabled = () => !Game.IsHost || gameStarting ||
|
||||
panel == PanelType.Kick || panel == PanelType.ForceStart ||
|
||||
!map.RulesLoaded || map.InvalidCustomRules ||
|
||||
panel == PanelType.Kick || panel == PanelType.ForceStart || !MapIsPlayable ||
|
||||
orderManager.LocalClient == null || orderManager.LocalClient.IsReady;
|
||||
|
||||
var mapButton = lobby.GetOrNull<ButtonWidget>("CHANGEMAP_BUTTON");
|
||||
@@ -330,7 +333,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
optionsTab.IsHighlighted = () => panel == PanelType.Options;
|
||||
optionsTab.IsDisabled = OptionsTabDisabled;
|
||||
optionsTab.OnClick = () => panel = PanelType.Options;
|
||||
optionsTab.GetText = () => !map.RulesLoaded ? "Loading..." : optionsTab.Text;
|
||||
|
||||
var playersTab = tabContainer.Get<ButtonWidget>("PLAYERS_TAB");
|
||||
playersTab.IsHighlighted = () => panel == PanelType.Players;
|
||||
@@ -476,7 +478,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
bool OptionsTabDisabled()
|
||||
{
|
||||
return !map.RulesLoaded || map.InvalidCustomRules || panel == PanelType.Kick || panel == PanelType.ForceStart;
|
||||
return !MapIsPlayable || panel == PanelType.Kick || panel == PanelType.ForceStart;
|
||||
}
|
||||
|
||||
public override void Tick()
|
||||
@@ -505,14 +507,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoadMapPreviewRules(MapPreview map)
|
||||
{
|
||||
// Force map rules to be loaded on this background thread
|
||||
new Task(map.PreloadRules).Start();
|
||||
}
|
||||
|
||||
void UpdateCurrentMap()
|
||||
{
|
||||
mapStatus = orderManager.LobbyInfo.GlobalSettings.MapStatus;
|
||||
var uid = orderManager.LobbyInfo.GlobalSettings.Map;
|
||||
if (map.Uid == uid)
|
||||
return;
|
||||
@@ -520,39 +517,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
map = modData.MapCache[uid];
|
||||
if (map.Status == MapStatus.Available)
|
||||
{
|
||||
// Maps need to be validated and pre-loaded before they can be accessed
|
||||
var currentMap = map;
|
||||
new Task(() =>
|
||||
// Tell the server that we have the map
|
||||
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
|
||||
|
||||
if (addBotOnMapLoad)
|
||||
{
|
||||
// Force map rules to be loaded on this background thread
|
||||
currentMap.PreloadRules();
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
// Map may have changed in the meantime
|
||||
if (currentMap != map)
|
||||
return;
|
||||
var slot = orderManager.LobbyInfo.FirstEmptyBotSlot();
|
||||
var bot = map.PlayerActorInfo.TraitInfos<IBotInfo>().Select(t => t.Type).FirstOrDefault();
|
||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||
if (slot != null && bot != null)
|
||||
orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
|
||||
|
||||
// Tell the server that we have the map
|
||||
if (!currentMap.InvalidCustomRules)
|
||||
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
|
||||
|
||||
if (addBotOnMapLoad)
|
||||
{
|
||||
var slot = orderManager.LobbyInfo.FirstEmptyBotSlot();
|
||||
var bot = currentMap.PlayerActorInfo.TraitInfos<IBotInfo>().Select(t => t.Type).FirstOrDefault();
|
||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||
if (slot != null && bot != null)
|
||||
orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
|
||||
|
||||
addBotOnMapLoad = false;
|
||||
}
|
||||
});
|
||||
}).Start();
|
||||
addBotOnMapLoad = false;
|
||||
}
|
||||
}
|
||||
else if (map.Status == MapStatus.DownloadAvailable)
|
||||
LoadMapPreviewRules(map);
|
||||
else if (Game.Settings.Game.AllowDownloading)
|
||||
modData.MapCache.QueryRemoteMapDetails(services.MapRepository, new[] { uid }, LoadMapPreviewRules);
|
||||
else if (map.Status != MapStatus.DownloadAvailable && Game.Settings.Game.AllowDownloading)
|
||||
modData.MapCache.QueryRemoteMapDetails(services.MapRepository, new[] { uid });
|
||||
}
|
||||
|
||||
void UpdatePlayerList()
|
||||
@@ -626,7 +606,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableHandicapWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableSpawnWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager, map, MapIsPlayable);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -686,7 +666,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
LobbyUtils.SetupEditableNameWidget(template, null, c, orderManager, worldRenderer);
|
||||
|
||||
if (client.IsAdmin)
|
||||
LobbyUtils.SetupEditableReadyWidget(template, null, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableReadyWidget(template, null, client, orderManager, map, MapIsPlayable);
|
||||
else
|
||||
LobbyUtils.HideReadyWidgets(template);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
readonly OrderManager orderManager;
|
||||
readonly Func<bool> configurationDisabled;
|
||||
MapPreview mapPreview;
|
||||
bool validOptions;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
internal LobbyOptionsLogic(Widget widget, OrderManager orderManager, Func<MapPreview> getMap, Func<bool> configurationDisabled)
|
||||
@@ -42,7 +41,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
panel = (ScrollPanelWidget)widget;
|
||||
optionsContainer = widget.Get("LOBBY_OPTIONS");
|
||||
yMargin = optionsContainer.Bounds.Y;
|
||||
optionsContainer.IsVisible = () => validOptions;
|
||||
checkboxRowTemplate = optionsContainer.Get("CHECKBOX_ROW_TEMPLATE");
|
||||
dropdownRowTemplate = optionsContainer.Get("DROPDOWN_ROW_TEMPLATE");
|
||||
|
||||
@@ -56,24 +54,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (newMapPreview == mapPreview)
|
||||
return;
|
||||
|
||||
if (newMapPreview.RulesLoaded)
|
||||
// We are currently enumerating the widget tree and so can't modify any layout
|
||||
// Defer it to the end of tick instead
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
// We are currently enumerating the widget tree and so can't modify any layout
|
||||
// Defer it to the end of tick instead
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
mapPreview = newMapPreview;
|
||||
RebuildOptions();
|
||||
validOptions = true;
|
||||
});
|
||||
}
|
||||
else
|
||||
validOptions = false;
|
||||
mapPreview = newMapPreview;
|
||||
RebuildOptions();
|
||||
});
|
||||
}
|
||||
|
||||
void RebuildOptions()
|
||||
{
|
||||
if (mapPreview == null || mapPreview.WorldActorInfo == null || mapPreview.InvalidCustomRules)
|
||||
if (mapPreview == null || mapPreview.WorldActorInfo == null)
|
||||
return;
|
||||
|
||||
optionsContainer.RemoveChildren();
|
||||
|
||||
@@ -630,13 +630,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
HideChildWidget(parent, "SPAWN_DROPDOWN");
|
||||
}
|
||||
|
||||
public static void SetupEditableReadyWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, MapPreview map)
|
||||
public static void SetupEditableReadyWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, MapPreview map, bool isEnabled)
|
||||
{
|
||||
var status = parent.Get<CheckboxWidget>("STATUS_CHECKBOX");
|
||||
status.IsChecked = () => orderManager.LocalClient.IsReady || c.Bot != null;
|
||||
status.IsVisible = () => true;
|
||||
status.IsDisabled = () => c.Bot != null || map.Status != MapStatus.Available ||
|
||||
!map.RulesLoaded || map.InvalidCustomRules;
|
||||
status.IsDisabled = () => c.Bot != null || map.Status != MapStatus.Available || !isEnabled;
|
||||
|
||||
var state = orderManager.LocalClient.IsReady ? Session.ClientState.NotReady : Session.ClientState.Ready;
|
||||
status.OnClick = () => orderManager.IssueOrder(Order.Command("state {0}".F(state)));
|
||||
|
||||
@@ -24,8 +24,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
int blinkTick;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
internal MapPreviewLogic(Widget widget, ModData modData, OrderManager orderManager, Func<MapPreview> getMap, Action<MapPreviewWidget, MapPreview, MouseInput> onMouseDown,
|
||||
Func<Dictionary<int, SpawnOccupant>> getSpawnOccupants, Func<HashSet<int>> getDisabledSpawnPoints, bool showUnoccupiedSpawnpoints)
|
||||
internal MapPreviewLogic(Widget widget, ModData modData, OrderManager orderManager, Func<(MapPreview Map, Session.MapStatus Status)> getMap,
|
||||
Action<MapPreviewWidget, MapPreview, MouseInput> onMouseDown, Func<Dictionary<int, SpawnOccupant>> getSpawnOccupants,
|
||||
Func<HashSet<int>> getDisabledSpawnPoints, bool showUnoccupiedSpawnpoints)
|
||||
{
|
||||
var mapRepository = modData.Manifest.Get<WebServices>().MapRepository;
|
||||
|
||||
@@ -34,8 +35,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
available.IsVisible = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
return map.Status == MapStatus.Available && (!map.RulesLoaded || !map.InvalidCustomRules);
|
||||
var (map, serverStatus) = getMap();
|
||||
var isPlayable = (serverStatus & Session.MapStatus.Playable) == Session.MapStatus.Playable;
|
||||
return map.Status == MapStatus.Available && isPlayable;
|
||||
};
|
||||
|
||||
SetupWidgets(available, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints);
|
||||
@@ -46,17 +48,30 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
invalid.IsVisible = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
return map.Status == MapStatus.Available && map.InvalidCustomRules;
|
||||
var (map, serverStatus) = getMap();
|
||||
return map.Status == MapStatus.Available && (serverStatus & Session.MapStatus.Incompatible) != 0;
|
||||
};
|
||||
|
||||
SetupWidgets(invalid, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints);
|
||||
}
|
||||
|
||||
var validating = widget.GetOrNull("MAP_VALIDATING");
|
||||
if (validating != null)
|
||||
{
|
||||
validating.IsVisible = () =>
|
||||
{
|
||||
var (map, serverStatus) = getMap();
|
||||
return map.Status == MapStatus.Available && (serverStatus & Session.MapStatus.Validating) != 0;
|
||||
};
|
||||
|
||||
SetupWidgets(validating, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints);
|
||||
}
|
||||
|
||||
var download = widget.GetOrNull("MAP_DOWNLOADABLE");
|
||||
if (download != null)
|
||||
{
|
||||
download.IsVisible = () => getMap().Status == MapStatus.DownloadAvailable;
|
||||
download.IsVisible = () => getMap().Map.Status == MapStatus.DownloadAvailable;
|
||||
|
||||
SetupWidgets(download, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints);
|
||||
|
||||
var install = download.GetOrNull<ButtonWidget>("MAP_INSTALL");
|
||||
@@ -64,10 +79,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
install.OnClick = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
map.Install(mapRepository, () =>
|
||||
getMap().Map.Install(mapRepository, () =>
|
||||
{
|
||||
map.PreloadRules();
|
||||
if (orderManager != null)
|
||||
Game.RunAfterTick(() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady))));
|
||||
});
|
||||
@@ -82,7 +95,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
progress.IsVisible = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
var (map, _) = getMap();
|
||||
return map.Status != MapStatus.Available && map.Status != MapStatus.DownloadAvailable;
|
||||
};
|
||||
|
||||
@@ -90,29 +103,36 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
var statusSearching = progress.GetOrNull("MAP_STATUS_SEARCHING");
|
||||
if (statusSearching != null)
|
||||
statusSearching.IsVisible = () => getMap().Status == MapStatus.Searching;
|
||||
{
|
||||
statusSearching.IsVisible = () =>
|
||||
{
|
||||
var (map, _) = getMap();
|
||||
return map.Status == MapStatus.Searching;
|
||||
};
|
||||
}
|
||||
|
||||
var statusUnavailable = progress.GetOrNull("MAP_STATUS_UNAVAILABLE");
|
||||
if (statusUnavailable != null)
|
||||
{
|
||||
statusUnavailable.IsVisible = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
var (map, _) = getMap();
|
||||
return map.Status == MapStatus.Unavailable && map != MapCache.UnknownMap;
|
||||
};
|
||||
}
|
||||
|
||||
var statusError = progress.GetOrNull("MAP_STATUS_ERROR");
|
||||
if (statusError != null)
|
||||
statusError.IsVisible = () => getMap().Status == MapStatus.DownloadError;
|
||||
statusError.IsVisible = () => getMap().Map.Status == MapStatus.DownloadError;
|
||||
|
||||
var statusDownloading = progress.GetOrNull<LabelWidget>("MAP_STATUS_DOWNLOADING");
|
||||
if (statusDownloading != null)
|
||||
{
|
||||
statusDownloading.IsVisible = () => getMap().Status == MapStatus.Downloading;
|
||||
statusDownloading.IsVisible = () => getMap().Map.Status == MapStatus.Downloading;
|
||||
|
||||
statusDownloading.GetText = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
var (map, _) = getMap();
|
||||
if (map.DownloadBytes == 0)
|
||||
return "Connecting...";
|
||||
|
||||
@@ -129,18 +149,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
retry.IsVisible = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
var (map, _) = getMap();
|
||||
return (map.Status == MapStatus.DownloadError || map.Status == MapStatus.Unavailable) && map != MapCache.UnknownMap;
|
||||
};
|
||||
|
||||
retry.OnClick = () =>
|
||||
{
|
||||
var map = getMap();
|
||||
var (map, _) = getMap();
|
||||
if (map.Status == MapStatus.DownloadError)
|
||||
{
|
||||
map.Install(mapRepository, () =>
|
||||
{
|
||||
map.PreloadRules();
|
||||
if (orderManager != null)
|
||||
Game.RunAfterTick(() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady))));
|
||||
});
|
||||
@@ -149,15 +168,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
modData.MapCache.QueryRemoteMapDetails(mapRepository, new[] { map.Uid });
|
||||
};
|
||||
|
||||
retry.GetText = () => getMap().Status == MapStatus.DownloadError ? "Retry Install" : "Retry Search";
|
||||
retry.GetText = () => getMap().Map.Status == MapStatus.DownloadError ? "Retry Install" : "Retry Search";
|
||||
}
|
||||
|
||||
var progressbar = progress.GetOrNull<ProgressBarWidget>("MAP_PROGRESSBAR");
|
||||
if (progressbar != null)
|
||||
{
|
||||
progressbar.IsIndeterminate = () => getMap().DownloadPercentage == 0;
|
||||
progressbar.GetPercentage = () => getMap().DownloadPercentage;
|
||||
progressbar.IsVisible = () => getMap().Status == MapStatus.Downloading;
|
||||
progressbar.IsIndeterminate = () => getMap().Map.DownloadPercentage == 0;
|
||||
progressbar.GetPercentage = () => getMap().Map.DownloadPercentage;
|
||||
progressbar.IsVisible = () => getMap().Map.Status == MapStatus.Downloading;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,12 +190,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
}
|
||||
|
||||
void SetupWidgets(Widget parent, Func<MapPreview> getMap,
|
||||
Action<MapPreviewWidget, MapPreview, MouseInput> onMouseDown, Func<Dictionary<int, SpawnOccupant>> getSpawnOccupants, Func<HashSet<int>> getDisabledSpawnPoints, bool showUnoccupiedSpawnpoints)
|
||||
void SetupWidgets(Widget parent,
|
||||
Func<(MapPreview Map, Session.MapStatus Status)> getMap,
|
||||
Action<MapPreviewWidget, MapPreview, MouseInput> onMouseDown,
|
||||
Func<Dictionary<int, SpawnOccupant>> getSpawnOccupants,
|
||||
Func<HashSet<int>> getDisabledSpawnPoints,
|
||||
bool showUnoccupiedSpawnpoints)
|
||||
{
|
||||
var preview = parent.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||
preview.Preview = () => getMap();
|
||||
preview.OnMouseDown = mi => onMouseDown(preview, getMap(), mi);
|
||||
preview.Preview = () => getMap().Map;
|
||||
preview.OnMouseDown = mi => onMouseDown(preview, getMap().Map, mi);
|
||||
preview.SpawnOccupants = getSpawnOccupants;
|
||||
preview.DisabledSpawnPoints = getDisabledSpawnPoints;
|
||||
preview.ShowUnoccupiedSpawnpoints = showUnoccupiedSpawnpoints;
|
||||
@@ -184,18 +207,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var titleLabel = parent.GetOrNull<LabelWithTooltipWidget>("MAP_TITLE");
|
||||
if (titleLabel != null)
|
||||
{
|
||||
titleLabel.IsVisible = () => getMap() != MapCache.UnknownMap;
|
||||
titleLabel.IsVisible = () => getMap().Map != MapCache.UnknownMap;
|
||||
var font = Game.Renderer.Fonts[titleLabel.Font];
|
||||
var title = new CachedTransform<MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font));
|
||||
titleLabel.GetText = () => title.Update(getMap());
|
||||
titleLabel.GetTooltipText = () => getMap().Title;
|
||||
titleLabel.GetText = () => title.Update(getMap().Map);
|
||||
titleLabel.GetTooltipText = () => getMap().Map.Title;
|
||||
}
|
||||
|
||||
var typeLabel = parent.GetOrNull<LabelWidget>("MAP_TYPE");
|
||||
if (typeLabel != null)
|
||||
{
|
||||
var type = new CachedTransform<MapPreview, string>(m => m.Categories.FirstOrDefault() ?? "");
|
||||
typeLabel.GetText = () => type.Update(getMap());
|
||||
typeLabel.GetText = () => type.Update(getMap().Map);
|
||||
}
|
||||
|
||||
var authorLabel = parent.GetOrNull<LabelWidget>("MAP_AUTHOR");
|
||||
@@ -204,7 +227,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var font = Game.Renderer.Fonts[authorLabel.Font];
|
||||
var author = new CachedTransform<MapPreview, string>(
|
||||
m => WidgetUtils.TruncateText("Created by {0}".F(m.Author), authorLabel.Bounds.Width, font));
|
||||
authorLabel.GetText = () => author.Update(getMap());
|
||||
authorLabel.GetText = () => author.Update(getMap().Map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,19 +139,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (allPreviews.Any())
|
||||
SelectMap(allPreviews.First());
|
||||
|
||||
// Preload map preview and rules to reduce jank
|
||||
// Preload map preview to reduce jank
|
||||
new Thread(() =>
|
||||
{
|
||||
foreach (var p in allPreviews)
|
||||
{
|
||||
p.GetMinimap();
|
||||
p.PreloadRules();
|
||||
}
|
||||
}).Start();
|
||||
|
||||
var startButton = widget.Get<ButtonWidget>("STARTGAME_BUTTON");
|
||||
startButton.OnClick = StartMissionClicked;
|
||||
startButton.IsDisabled = () => selectedMap == null || selectedMap.InvalidCustomRules;
|
||||
startButton.IsDisabled = () => selectedMap == null;
|
||||
|
||||
widget.Get<ButtonWidget>("BACK_BUTTON").OnClick = () =>
|
||||
{
|
||||
@@ -373,9 +370,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
StopVideo(videoPlayer);
|
||||
|
||||
if (selectedMap.InvalidCustomRules)
|
||||
return;
|
||||
|
||||
var orders = new List<Order>();
|
||||
if (difficulty != null)
|
||||
orders.Add(Order.Command("option difficulty {0}".F(difficulty)));
|
||||
|
||||
@@ -17,6 +17,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
@@ -93,7 +94,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
Ui.LoadWidget("MAP_PREVIEW", mapPreviewRoot, new WidgetArgs
|
||||
{
|
||||
{ "orderManager", null },
|
||||
{ "getMap", (Func<MapPreview>)(() => map) },
|
||||
{ "getMap", (Func<(MapPreview, Session.MapStatus)>)(() => (map, Session.MapStatus.Playable)) },
|
||||
{ "onMouseDown", (Action<MapPreviewWidget, MapPreview, MouseInput>)((preview, mapPreview, mi) => { }) },
|
||||
{ "getSpawnOccupants", (Func<Dictionary<int, SpawnOccupant>>)(() => spawnOccupants.Update(selectedReplay)) },
|
||||
{ "getDisabledSpawnPoints", (Func<HashSet<int>>)(() => disabledSpawnPoints.Update(selectedReplay)) },
|
||||
@@ -623,13 +624,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
try
|
||||
{
|
||||
if (map.Status != MapStatus.Available)
|
||||
{
|
||||
if (map.Status == MapStatus.DownloadAvailable)
|
||||
LoadMapPreviewRules(map);
|
||||
else if (Game.Settings.Game.AllowDownloading)
|
||||
modData.MapCache.QueryRemoteMapDetails(services.MapRepository, new[] { map.Uid }, LoadMapPreviewRules);
|
||||
}
|
||||
if (map.Status == MapStatus.Unavailable && Game.Settings.Game.AllowDownloading)
|
||||
modData.MapCache.QueryRemoteMapDetails(services.MapRepository, new[] { map.Uid });
|
||||
|
||||
var players = replay.GameInfo.Players
|
||||
.GroupBy(p => p.Team)
|
||||
@@ -685,15 +681,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
}
|
||||
|
||||
void LoadMapPreviewRules(MapPreview map)
|
||||
{
|
||||
new Task(() =>
|
||||
{
|
||||
// Force map rules to be loaded on this background thread
|
||||
map.PreloadRules();
|
||||
}).Start();
|
||||
}
|
||||
|
||||
void WatchReplay()
|
||||
{
|
||||
if (selectedReplay != null && ReplayUtils.PromptConfirmReplayCompatibility(selectedReplay))
|
||||
|
||||
Reference in New Issue
Block a user