Merge pull request #5353 from pchote/map-validation
Disable maps with invalid rules
This commit is contained in:
@@ -21,12 +21,13 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public readonly ModMetadata Mod;
|
public readonly ModMetadata Mod;
|
||||||
public readonly string[]
|
public readonly string[]
|
||||||
Folders, MapFolders, Rules, ServerTraits,
|
Folders, Rules, ServerTraits,
|
||||||
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
||||||
Weapons, Voices, Notifications, Music, Movies, Translations, TileSets,
|
Weapons, Voices, Notifications, Music, Movies, Translations, TileSets,
|
||||||
ChromeMetrics, PackageContents, LuaScripts, MapCompatibility, Missions;
|
ChromeMetrics, PackageContents, LuaScripts, MapCompatibility, Missions;
|
||||||
|
|
||||||
public readonly Dictionary<string, string> Packages;
|
public readonly IReadOnlyDictionary<string, string> Packages;
|
||||||
|
public readonly IReadOnlyDictionary<string, string> MapFolders;
|
||||||
public readonly MiniYaml LoadScreen;
|
public readonly MiniYaml LoadScreen;
|
||||||
public readonly MiniYaml LobbyDefaults;
|
public readonly MiniYaml LobbyDefaults;
|
||||||
public readonly Dictionary<string, Pair<string, int>> Fonts;
|
public readonly Dictionary<string, Pair<string, int>> Fonts;
|
||||||
@@ -43,8 +44,8 @@ namespace OpenRA
|
|||||||
|
|
||||||
// TODO: Use fieldloader
|
// TODO: Use fieldloader
|
||||||
Folders = YamlList(yaml, "Folders");
|
Folders = YamlList(yaml, "Folders");
|
||||||
MapFolders = YamlList(yaml, "MapFolders");
|
MapFolders = YamlDictionary(yaml, "MapFolders");
|
||||||
Packages = yaml["Packages"].NodesDict.ToDictionary(x => x.Key, x => x.Value.Value);
|
Packages = YamlDictionary(yaml, "Packages");
|
||||||
Rules = YamlList(yaml, "Rules");
|
Rules = YamlList(yaml, "Rules");
|
||||||
ServerTraits = YamlList(yaml, "ServerTraits");
|
ServerTraits = YamlList(yaml, "ServerTraits");
|
||||||
Sequences = YamlList(yaml, "Sequences");
|
Sequences = YamlList(yaml, "Sequences");
|
||||||
@@ -95,5 +96,14 @@ namespace OpenRA
|
|||||||
|
|
||||||
return yaml[key].NodesDict.Keys.ToArray();
|
return yaml[key].NodesDict.Keys.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IReadOnlyDictionary<string, string> YamlDictionary(Dictionary<string, MiniYaml> yaml, string key)
|
||||||
|
{
|
||||||
|
if (!yaml.ContainsKey(key))
|
||||||
|
return new ReadOnlyDictionary<string, string>();
|
||||||
|
|
||||||
|
var inner = yaml[key].NodesDict.ToDictionary(x => x.Key, x => x.Value.Value);
|
||||||
|
return new ReadOnlyDictionary<string, string>(inner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,16 +42,19 @@ namespace OpenRA
|
|||||||
|
|
||||||
public void LoadMaps()
|
public void LoadMaps()
|
||||||
{
|
{
|
||||||
var paths = modData.Manifest.MapFolders.SelectMany(f => FindMapsIn(f));
|
// Expand the dictionary (dir path, dir type) to a dictionary of (map path, dir type)
|
||||||
foreach (var path in paths)
|
var mapPaths = modData.Manifest.MapFolders.SelectMany(kv =>
|
||||||
|
FindMapsIn(kv.Key).ToDictionary(p => p, p => string.IsNullOrEmpty(kv.Value) ? MapClassification.Unknown : Enum<MapClassification>.Parse(kv.Value)));
|
||||||
|
|
||||||
|
foreach (var path in mapPaths)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (new Support.PerfTimer(path))
|
using (new Support.PerfTimer(path.Key))
|
||||||
{
|
{
|
||||||
var map = new Map(path, modData.Manifest.Mod.Id);
|
var map = new Map(path.Key, modData.Manifest.Mod.Id);
|
||||||
if (modData.Manifest.MapCompatibility.Contains(map.RequiresMod))
|
if (modData.Manifest.MapCompatibility.Contains(map.RequiresMod))
|
||||||
previews[map.Uid].UpdateFromMap(map);
|
previews[map.Uid].UpdateFromMap(map, path.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public enum MapStatus { Available, Unavailable, Searching, DownloadAvailable, Downloading, DownloadError }
|
public enum MapStatus { Available, Unavailable, Searching, DownloadAvailable, Downloading, DownloadError }
|
||||||
|
|
||||||
|
// Used for grouping maps in the UI
|
||||||
|
public enum MapClassification { Unknown, System, User, Remote }
|
||||||
|
|
||||||
|
// Used for verifying map availability in the lobby
|
||||||
|
public enum MapRuleStatus { Unknown, Cached, Invalid }
|
||||||
|
|
||||||
// Fields names must match the with the remote API
|
// Fields names must match the with the remote API
|
||||||
public class RemoteMapData
|
public class RemoteMapData
|
||||||
{
|
{
|
||||||
@@ -53,6 +59,9 @@ namespace OpenRA
|
|||||||
public Bitmap CustomPreview { get; private set; }
|
public Bitmap CustomPreview { get; private set; }
|
||||||
public Map Map { get; private set; }
|
public Map Map { get; private set; }
|
||||||
public MapStatus Status { get; private set; }
|
public MapStatus Status { get; private set; }
|
||||||
|
public MapClassification Class { get; private set; }
|
||||||
|
|
||||||
|
public MapRuleStatus RuleStatus { get; private set; }
|
||||||
|
|
||||||
Download download;
|
Download download;
|
||||||
public long DownloadBytes { get; private set; }
|
public long DownloadBytes { get; private set; }
|
||||||
@@ -94,9 +103,10 @@ namespace OpenRA
|
|||||||
Bounds = Rectangle.Empty;
|
Bounds = Rectangle.Empty;
|
||||||
SpawnPoints = NoSpawns;
|
SpawnPoints = NoSpawns;
|
||||||
Status = MapStatus.Unavailable;
|
Status = MapStatus.Unavailable;
|
||||||
|
Class = MapClassification.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateFromMap(Map m)
|
public void UpdateFromMap(Map m, MapClassification classification)
|
||||||
{
|
{
|
||||||
Map = m;
|
Map = m;
|
||||||
Title = m.Title;
|
Title = m.Title;
|
||||||
@@ -108,6 +118,7 @@ namespace OpenRA
|
|||||||
SpawnPoints = m.GetSpawnPoints().ToList();
|
SpawnPoints = m.GetSpawnPoints().ToList();
|
||||||
CustomPreview = m.CustomPreview;
|
CustomPreview = m.CustomPreview;
|
||||||
Status = MapStatus.Available;
|
Status = MapStatus.Available;
|
||||||
|
Class = classification;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml)
|
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml)
|
||||||
@@ -146,8 +157,9 @@ namespace OpenRA
|
|||||||
if (CustomPreview != null)
|
if (CustomPreview != null)
|
||||||
cache.CacheMinimap(this);
|
cache.CacheMinimap(this);
|
||||||
}
|
}
|
||||||
Status = status;
|
|
||||||
|
|
||||||
|
Status = status;
|
||||||
|
Class = MapClassification.Remote;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +211,7 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log.Write("debug", "Downloaded map to '{0}'", mapPath);
|
Log.Write("debug", "Downloaded map to '{0}'", mapPath);
|
||||||
Game.RunAfterTick(() => UpdateFromMap(new Map(mapPath)));
|
Game.RunAfterTick(() => UpdateFromMap(new Map(mapPath), MapClassification.User));
|
||||||
};
|
};
|
||||||
|
|
||||||
download = new Download(mapUrl, mapPath, onDownloadProgress, onDownloadComplete);
|
download = new Download(mapUrl, mapPath, onDownloadProgress, onDownloadComplete);
|
||||||
@@ -220,5 +232,22 @@ namespace OpenRA
|
|||||||
download.Cancel();
|
download.Cancel();
|
||||||
download = null;
|
download = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CacheRules()
|
||||||
|
{
|
||||||
|
if (RuleStatus != MapRuleStatus.Unknown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Map.PreloadRules();
|
||||||
|
RuleStatus = MapRuleStatus.Cached;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Write("debug", "Map {0} failed validation with an exception:\n{1}", Uid, e.Message);
|
||||||
|
RuleStatus = MapRuleStatus.Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Network;
|
using OpenRA.Network;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
@@ -170,7 +171,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
if (slotsButton != null)
|
if (slotsButton != null)
|
||||||
{
|
{
|
||||||
slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players ||
|
slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players ||
|
||||||
!orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots || !s.LockTeam);
|
Map.RuleStatus != MapRuleStatus.Cached || !orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots || !s.LockTeam);
|
||||||
|
|
||||||
var botNames = modRules.Actors["player"].Traits.WithInterface<IBotInfo>().Select(t => t.Name);
|
var botNames = modRules.Actors["player"].Traits.WithInterface<IBotInfo>().Select(t => t.Name);
|
||||||
slotsButton.OnMouseDown = _ =>
|
slotsButton.OnMouseDown = _ =>
|
||||||
@@ -264,7 +265,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
optionsBin.IsVisible = () => panel == PanelType.Options;
|
optionsBin.IsVisible = () => panel == PanelType.Options;
|
||||||
|
|
||||||
var optionsButton = lobby.Get<ButtonWidget>("OPTIONS_BUTTON");
|
var optionsButton = lobby.Get<ButtonWidget>("OPTIONS_BUTTON");
|
||||||
optionsButton.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart;
|
optionsButton.IsDisabled = () => Map.RuleStatus != MapRuleStatus.Cached || panel == PanelType.Kick || panel == PanelType.ForceStart;
|
||||||
optionsButton.GetText = () => panel == PanelType.Options ? "Players" : "Options";
|
optionsButton.GetText = () => panel == PanelType.Options ? "Players" : "Options";
|
||||||
optionsButton.OnClick = () => panel = (panel == PanelType.Options) ? PanelType.Players : PanelType.Options;
|
optionsButton.OnClick = () => panel = (panel == PanelType.Options) ? PanelType.Players : PanelType.Options;
|
||||||
|
|
||||||
@@ -278,7 +279,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
var startGameButton = lobby.GetOrNull<ButtonWidget>("START_GAME_BUTTON");
|
var startGameButton = lobby.GetOrNull<ButtonWidget>("START_GAME_BUTTON");
|
||||||
if (startGameButton != null)
|
if (startGameButton != null)
|
||||||
{
|
{
|
||||||
startGameButton.IsDisabled = () => configurationDisabled() ||
|
startGameButton.IsDisabled = () => configurationDisabled() || Map.RuleStatus != MapRuleStatus.Cached ||
|
||||||
orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null);
|
orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null);
|
||||||
startGameButton.OnClick = () =>
|
startGameButton.OnClick = () =>
|
||||||
{
|
{
|
||||||
@@ -582,8 +583,20 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Map = Game.modData.MapCache[uid];
|
Map = Game.modData.MapCache[uid];
|
||||||
|
|
||||||
if (Map.Status == MapStatus.Available)
|
if (Map.Status == MapStatus.Available)
|
||||||
|
{
|
||||||
|
// Maps need to be validated and pre-loaded before they can be accessed
|
||||||
|
new Thread(_ =>
|
||||||
|
{
|
||||||
|
var map = Map;
|
||||||
|
map.CacheRules();
|
||||||
|
Game.RunAfterTick(() =>
|
||||||
|
{
|
||||||
|
// Map may have changed in the meantime
|
||||||
|
if (map != Map)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (map.RuleStatus != MapRuleStatus.Invalid)
|
||||||
{
|
{
|
||||||
// Tell the server that we have the map
|
// Tell the server that we have the map
|
||||||
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
|
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
|
||||||
@@ -593,6 +606,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
if (!Map.Map.Options.StartingCash.HasValue && !pri.SelectableCash.Contains(orderManager.LobbyInfo.GlobalSettings.StartingCash))
|
if (!Map.Map.Options.StartingCash.HasValue && !pri.SelectableCash.Contains(orderManager.LobbyInfo.GlobalSettings.StartingCash))
|
||||||
orderManager.IssueOrder(Order.Command("startingcash {0}".F(pri.DefaultCash)));
|
orderManager.IssueOrder(Order.Command("startingcash {0}".F(pri.DefaultCash)));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}).Start();
|
||||||
|
}
|
||||||
else if (Game.Settings.Game.AllowDownloading)
|
else if (Game.Settings.Game.AllowDownloading)
|
||||||
Game.modData.MapCache.QueryRemoteMapDetails(new [] { uid });
|
Game.modData.MapCache.QueryRemoteMapDetails(new [] { uid });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
var available = widget.GetOrNull("MAP_AVAILABLE");
|
var available = widget.GetOrNull("MAP_AVAILABLE");
|
||||||
if (available != null)
|
if (available != null)
|
||||||
{
|
{
|
||||||
available.IsVisible = () => lobby.Map.Status == MapStatus.Available;
|
available.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.RuleStatus == MapRuleStatus.Cached;
|
||||||
|
|
||||||
var preview = available.Get<MapPreviewWidget>("MAP_PREVIEW");
|
var preview = available.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||||
preview.Preview = () => lobby.Map;
|
preview.Preview = () => lobby.Map;
|
||||||
@@ -46,6 +46,25 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
author.GetText = () => "Created by {0}".F(lobby.Map.Author);
|
author.GetText = () => "Created by {0}".F(lobby.Map.Author);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var invalid = widget.GetOrNull("MAP_INVALID");
|
||||||
|
if (invalid != null)
|
||||||
|
{
|
||||||
|
invalid.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.RuleStatus == MapRuleStatus.Invalid;
|
||||||
|
|
||||||
|
var preview = invalid.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||||
|
preview.Preview = () => lobby.Map;
|
||||||
|
preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi);
|
||||||
|
preview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager.LobbyInfo, lobby.Map);
|
||||||
|
|
||||||
|
var title = invalid.GetOrNull<LabelWidget>("MAP_TITLE");
|
||||||
|
if (title != null)
|
||||||
|
title.GetText = () => lobby.Map.Title;
|
||||||
|
|
||||||
|
var type = invalid.GetOrNull<LabelWidget>("MAP_TYPE");
|
||||||
|
if (type != null)
|
||||||
|
type.GetText = () => lobby.Map.Type;
|
||||||
|
}
|
||||||
|
|
||||||
var download = widget.GetOrNull("MAP_DOWNLOADABLE");
|
var download = widget.GetOrNull("MAP_DOWNLOADABLE");
|
||||||
if (download != null)
|
if (download != null)
|
||||||
{
|
{
|
||||||
@@ -76,7 +95,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
var progress = widget.GetOrNull("MAP_PROGRESS");
|
var progress = widget.GetOrNull("MAP_PROGRESS");
|
||||||
if (progress != null)
|
if (progress != null)
|
||||||
{
|
{
|
||||||
progress.IsVisible = () => lobby.Map.Status != MapStatus.Available && lobby.Map.Status != MapStatus.DownloadAvailable;
|
progress.IsVisible = () => (lobby.Map.Status != MapStatus.Available || lobby.Map.RuleStatus == MapRuleStatus.Unknown) && lobby.Map.Status != MapStatus.DownloadAvailable;
|
||||||
|
|
||||||
var preview = progress.Get<MapPreviewWidget>("MAP_PREVIEW");
|
var preview = progress.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||||
preview.Preview = () => lobby.Map;
|
preview.Preview = () => lobby.Map;
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
var status = parent.Get<CheckboxWidget>("STATUS_CHECKBOX");
|
var status = parent.Get<CheckboxWidget>("STATUS_CHECKBOX");
|
||||||
status.IsChecked = () => orderManager.LocalClient.IsReady || c.Bot != null;
|
status.IsChecked = () => orderManager.LocalClient.IsReady || c.Bot != null;
|
||||||
status.IsVisible = () => true;
|
status.IsVisible = () => true;
|
||||||
status.IsDisabled = () => c.Bot != null || map.Status != MapStatus.Available;
|
status.IsDisabled = () => c.Bot != null || map.Status != MapStatus.Available || map.RuleStatus != MapRuleStatus.Cached;
|
||||||
|
|
||||||
var state = orderManager.LocalClient.IsReady ? Session.ClientState.NotReady : Session.ClientState.Ready;
|
var state = orderManager.LocalClient.IsReady ? Session.ClientState.NotReady : Session.ClientState.Ready;
|
||||||
status.OnClick = () => orderManager.IssueOrder(Order.Command("state {0}".F(state)));
|
status.OnClick = () => orderManager.IssueOrder(Order.Command("state {0}".F(state)));
|
||||||
|
|||||||
@@ -38,6 +38,41 @@ Container@LOBBY_MAP_PREVIEW:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Font: Tiny
|
Font: Tiny
|
||||||
Align: Center
|
Align: Center
|
||||||
|
Container@MAP_INVALID:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
Background@MAP_BG:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 194
|
||||||
|
Background: panel-gray
|
||||||
|
Children:
|
||||||
|
MapPreview@MAP_PREVIEW:
|
||||||
|
X: 1
|
||||||
|
Y: 1
|
||||||
|
Width: PARENT_RIGHT-2
|
||||||
|
Height: PARENT_BOTTOM-2
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Label@MAP_TITLE:
|
||||||
|
Y: 197
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
Align: Center
|
||||||
|
Label@MAP_STATUS_A:
|
||||||
|
Y: 212
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Tiny
|
||||||
|
Align: Center
|
||||||
|
Text: This map is not compatible
|
||||||
|
Label@MAP_STATUS_B:
|
||||||
|
Y: 225
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Tiny
|
||||||
|
Align: Center
|
||||||
|
Text: with this version of OpenRA
|
||||||
Container@MAP_DOWNLOADABLE:
|
Container@MAP_DOWNLOADABLE:
|
||||||
Width: PARENT_RIGHT
|
Width: PARENT_RIGHT
|
||||||
Height: PARENT_BOTTOM
|
Height: PARENT_BOTTOM
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ Folders:
|
|||||||
~^Content/cnc
|
~^Content/cnc
|
||||||
|
|
||||||
MapFolders:
|
MapFolders:
|
||||||
./mods/cnc/maps
|
./mods/cnc/maps: System
|
||||||
~^maps/cnc
|
~^maps/cnc: User
|
||||||
|
|
||||||
Packages:
|
Packages:
|
||||||
bluetib.mix
|
bluetib.mix
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ Folders:
|
|||||||
~^Content/d2k/Music
|
~^Content/d2k/Music
|
||||||
|
|
||||||
MapFolders:
|
MapFolders:
|
||||||
./mods/d2k/maps
|
./mods/d2k/maps: System
|
||||||
~^maps/d2k
|
~^maps/d2k: User
|
||||||
|
|
||||||
Packages:
|
Packages:
|
||||||
SOUND.RS
|
SOUND.RS
|
||||||
|
|||||||
@@ -47,5 +47,4 @@ Fonts:
|
|||||||
TinyBold:
|
TinyBold:
|
||||||
Font:FreeSansBold.ttf
|
Font:FreeSansBold.ttf
|
||||||
Size:10
|
Size:10
|
||||||
Packages:
|
|
||||||
LobbyDefaults:
|
LobbyDefaults:
|
||||||
@@ -38,6 +38,41 @@ Container@LOBBY_MAP_PREVIEW:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Font: Tiny
|
Font: Tiny
|
||||||
Align: Center
|
Align: Center
|
||||||
|
Container@MAP_INVALID:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
Background@MAP_BG:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 214
|
||||||
|
Background: dialog3
|
||||||
|
Children:
|
||||||
|
MapPreview@MAP_PREVIEW:
|
||||||
|
X: 1
|
||||||
|
Y: 1
|
||||||
|
Width: PARENT_RIGHT-2
|
||||||
|
Height: PARENT_BOTTOM-2
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Label@MAP_TITLE:
|
||||||
|
Y: 215
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
Align: Center
|
||||||
|
Label@MAP_STATUS_A:
|
||||||
|
Y:232
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Tiny
|
||||||
|
Align: Center
|
||||||
|
Text: This map is not compatible
|
||||||
|
Label@MAP_STATUS_B:
|
||||||
|
Y:245
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Tiny
|
||||||
|
Align: Center
|
||||||
|
Text: with this version of OpenRA
|
||||||
Container@MAP_DOWNLOADABLE:
|
Container@MAP_DOWNLOADABLE:
|
||||||
Width: PARENT_RIGHT
|
Width: PARENT_RIGHT
|
||||||
Height: PARENT_BOTTOM
|
Height: PARENT_BOTTOM
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ Folders:
|
|||||||
~^Content/ra
|
~^Content/ra
|
||||||
|
|
||||||
MapFolders:
|
MapFolders:
|
||||||
./mods/ra/maps
|
./mods/ra/maps: System
|
||||||
~^maps/ra
|
~^maps/ra: User
|
||||||
|
|
||||||
Packages:
|
Packages:
|
||||||
~main.mix
|
~main.mix
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ Folders:
|
|||||||
./mods/ra/uibits
|
./mods/ra/uibits
|
||||||
|
|
||||||
MapFolders:
|
MapFolders:
|
||||||
./mods/ts/maps
|
./mods/ts/maps: System
|
||||||
~^maps/ts
|
~^maps/ts: User
|
||||||
|
|
||||||
Packages:
|
Packages:
|
||||||
# Tiberian Sun
|
# Tiberian Sun
|
||||||
|
|||||||
Reference in New Issue
Block a user