Merge pull request #4901 from pchote/async-maps
Asynchronous map downloading.
This commit is contained in:
@@ -27,6 +27,9 @@ NEW:
|
||||
Fixed the game sometimes crashing when deploying and activating the guard cursor at the same time.
|
||||
Build time is now set when an item reaches the front of a queue, instead of immediately when queued.
|
||||
The attack cursor now changes if the target is out of range.
|
||||
The server browser will now show map details from other mods if the maps are available online.
|
||||
Fixed a crash when connecting to a server with an unavailable map.
|
||||
Added a warning dialog when force starting a match.
|
||||
Dune 2000:
|
||||
Added the Atreides grenadier from the 1.06 patch.
|
||||
Added randomized tiles for Sand and Rock terrain.
|
||||
|
||||
@@ -531,46 +531,5 @@ namespace OpenRA
|
||||
{
|
||||
return orderManager != null && orderManager.world == world;
|
||||
}
|
||||
|
||||
public static bool DownloadMap(string mapHash)
|
||||
{
|
||||
var mod = Game.modData.Manifest.Mod;
|
||||
var dirPath = new[] { Platform.SupportDir, "maps", mod.Id }.Aggregate(Path.Combine);
|
||||
var tempFile = Path.Combine(dirPath, Path.GetRandomFileName());
|
||||
if (!Directory.Exists(dirPath))
|
||||
Directory.CreateDirectory(dirPath);
|
||||
foreach (var MapRepository in Game.Settings.Game.MapRepositories)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = MapRepository + mapHash;
|
||||
|
||||
var request = WebRequest.Create(url);
|
||||
request.Method = "HEAD";
|
||||
var res = request.GetResponse();
|
||||
|
||||
if (res.Headers["Content-Disposition"] == null)
|
||||
continue;
|
||||
var mapPath = Path.Combine(dirPath, res.Headers ["Content-Disposition"].Replace("attachment; filename = ", ""));
|
||||
Log.Write("debug", "Trying to download map to '{0}' using {1}", mapPath, MapRepository);
|
||||
|
||||
WebClient webClient = new WebClient();
|
||||
webClient.DownloadFile(url, tempFile);
|
||||
File.Move(tempFile, mapPath);
|
||||
Game.modData.MapCache[mapHash].UpdateFromMap(new Map(mapPath));
|
||||
Log.Write("debug", "New map has been downloaded to '{0}'", mapPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
Log.Write("debug", "Could not download map '{0}' using {1}", mapHash, MapRepository);
|
||||
Log.Write("debug", e.ToString());
|
||||
File.Delete(tempFile);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace OpenRA.GameRules
|
||||
public bool TeamHealthColors = false;
|
||||
|
||||
public bool AllowDownloading = true;
|
||||
public string[] MapRepositories = { "http://resource.openra.net/map/", "http://resource.ihptru.net:8080/map/" };
|
||||
public string MapRepository = "http://resource.openra.net/map/";
|
||||
}
|
||||
|
||||
public class KeySettings
|
||||
|
||||
@@ -14,10 +14,11 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -57,6 +58,43 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryRemoteMapDetails(IEnumerable<string> uids)
|
||||
{
|
||||
var maps = uids.Distinct()
|
||||
.Select(uid => previews[uid])
|
||||
.Where(p => p.Status == MapStatus.Unavailable)
|
||||
.ToDictionary(p => p.Uid, p => p);
|
||||
|
||||
if (!maps.Any())
|
||||
return;
|
||||
|
||||
foreach (var p in maps.Values)
|
||||
p.UpdateRemoteSearch(MapStatus.Searching, null);
|
||||
|
||||
var url = Game.Settings.Game.MapRepository + "hash/" + string.Join(",", maps.Keys.ToArray()) + "/yaml";
|
||||
|
||||
Action<DownloadDataCompletedEventArgs, bool> onInfoComplete = (i, cancelled) =>
|
||||
{
|
||||
if (cancelled || i.Error != null)
|
||||
{
|
||||
Log.Write("debug", "Remote map query failed with error: {0}", i.Error != null ? i.Error.Message : "cancelled");
|
||||
Log.Write("debug", "URL was: {0}", url);
|
||||
foreach (var p in maps.Values)
|
||||
p.UpdateRemoteSearch(MapStatus.Unavailable, null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var data = Encoding.UTF8.GetString(i.Result);
|
||||
var yaml = MiniYaml.FromString(data);
|
||||
|
||||
foreach (var kv in yaml)
|
||||
maps[kv.Key].UpdateRemoteSearch(MapStatus.DownloadAvailable, kv.Value);
|
||||
};
|
||||
|
||||
new Download(url, _ => { }, onInfoComplete);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> FindMapsIn(string dir)
|
||||
{
|
||||
string[] noMaps = { };
|
||||
|
||||
@@ -11,9 +11,11 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
@@ -21,10 +23,26 @@ using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public enum MapStatus { Available, Unavailable }
|
||||
public enum MapStatus { Available, Unavailable, Searching, DownloadAvailable, Downloading, DownloadError }
|
||||
|
||||
// Fields names must match the with the remote API
|
||||
public class RemoteMapData
|
||||
{
|
||||
public readonly string title;
|
||||
public readonly string author;
|
||||
public readonly string map_type;
|
||||
public readonly int players;
|
||||
public readonly Rectangle bounds;
|
||||
public readonly int[] spawnpoints = {};
|
||||
public readonly string minimap;
|
||||
public readonly bool downloading;
|
||||
public readonly bool requires_upgrade;
|
||||
}
|
||||
|
||||
public class MapPreview
|
||||
{
|
||||
static readonly List<CPos> NoSpawns = new List<CPos>();
|
||||
MapCache cache;
|
||||
|
||||
public readonly string Uid;
|
||||
public string Title { get; private set; }
|
||||
@@ -37,6 +55,10 @@ namespace OpenRA
|
||||
public Map Map { get; private set; }
|
||||
public MapStatus Status { get; private set; }
|
||||
|
||||
Download download;
|
||||
public long DownloadBytes { get; private set; }
|
||||
public int DownloadPercentage { get; private set; }
|
||||
|
||||
Sprite minimap;
|
||||
bool generatingMinimap;
|
||||
public Sprite Minimap
|
||||
@@ -62,7 +84,6 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
MapCache cache;
|
||||
public MapPreview(string uid, MapCache cache)
|
||||
{
|
||||
this.cache = cache;
|
||||
@@ -89,5 +110,116 @@ namespace OpenRA
|
||||
CustomPreview = m.CustomPreview;
|
||||
Status = MapStatus.Available;
|
||||
}
|
||||
|
||||
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml)
|
||||
{
|
||||
// Update on the main thread to ensure consistency
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
if (status == MapStatus.DownloadAvailable)
|
||||
{
|
||||
try
|
||||
{
|
||||
var r = FieldLoader.Load<RemoteMapData>(yaml);
|
||||
|
||||
// Map is not useable by the current version
|
||||
if (!r.downloading || r.requires_upgrade)
|
||||
{
|
||||
Status = MapStatus.Unavailable;
|
||||
return;
|
||||
}
|
||||
|
||||
Title = r.title;
|
||||
Type = r.map_type;
|
||||
Author = r.author;
|
||||
PlayerCount = r.players;
|
||||
Bounds = r.bounds;
|
||||
|
||||
var spawns = new List<CPos>();
|
||||
for (var j = 0; j < r.spawnpoints.Length; j += 2)
|
||||
spawns.Add(new CPos(r.spawnpoints[j], r.spawnpoints[j+1]));
|
||||
SpawnPoints = spawns;
|
||||
|
||||
CustomPreview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap)));
|
||||
}
|
||||
catch (Exception) {}
|
||||
|
||||
if (CustomPreview != null)
|
||||
cache.CacheMinimap(this);
|
||||
}
|
||||
Status = status;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void Install()
|
||||
{
|
||||
if (Status != MapStatus.DownloadAvailable || !Game.Settings.Game.AllowDownloading)
|
||||
return;
|
||||
|
||||
Status = MapStatus.Downloading;
|
||||
var baseMapPath = new[] { Platform.SupportDir, "maps", Game.modData.Manifest.Mod.Id }.Aggregate(Path.Combine);
|
||||
|
||||
// Create the map directory if it doesn't exist
|
||||
if (!Directory.Exists(baseMapPath))
|
||||
Directory.CreateDirectory(baseMapPath);
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
// Request the filename from the server
|
||||
// Run in a worker thread to avoid network delays
|
||||
var mapUrl = Game.Settings.Game.MapRepository + Uid;
|
||||
try
|
||||
{
|
||||
|
||||
var request = WebRequest.Create(mapUrl);
|
||||
request.Method = "HEAD";
|
||||
var res = request.GetResponse();
|
||||
|
||||
// Map not found
|
||||
if (res.Headers["Content-Disposition"] == null)
|
||||
{
|
||||
Status = MapStatus.DownloadError;
|
||||
return;
|
||||
}
|
||||
|
||||
var mapPath = Path.Combine(baseMapPath, res.Headers["Content-Disposition"].Replace("attachment; filename = ", ""));
|
||||
|
||||
Action<DownloadProgressChangedEventArgs> onDownloadProgress = i => { DownloadBytes = i.BytesReceived; DownloadPercentage = i.ProgressPercentage; };
|
||||
Action<AsyncCompletedEventArgs, bool> onDownloadComplete = (i, cancelled) =>
|
||||
{
|
||||
download = null;
|
||||
|
||||
if (cancelled || i.Error != null)
|
||||
{
|
||||
Log.Write("debug", "Remote map download failed with error: {0}", i.Error != null ? i.Error.Message : "cancelled");
|
||||
Log.Write("debug", "URL was: {0}", mapUrl);
|
||||
|
||||
Status = MapStatus.DownloadError;
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Write("debug", "Downloaded map to '{0}'", mapPath);
|
||||
Game.RunAfterTick(() => UpdateFromMap(new Map(mapPath)));
|
||||
};
|
||||
|
||||
download = new Download(mapUrl, mapPath, onDownloadProgress, onDownloadComplete);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
Status = MapStatus.DownloadError;
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void CancelInstall()
|
||||
{
|
||||
if (download == null)
|
||||
return;
|
||||
|
||||
download.Cancel();
|
||||
download = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace OpenRA.Network
|
||||
get { return Clients.Count(c => c.Bot == null) == 1; }
|
||||
}
|
||||
|
||||
public enum ClientState { NotReady, Ready, Disconnected = 1000 }
|
||||
public enum ClientState { NotReady, Invalid, Ready, Disconnected = 1000 }
|
||||
|
||||
public class Client
|
||||
{
|
||||
@@ -93,13 +93,14 @@ namespace OpenRA.Network
|
||||
public int SpawnPoint;
|
||||
public string Name;
|
||||
public string IpAddress;
|
||||
public ClientState State;
|
||||
public ClientState State = ClientState.Invalid;
|
||||
public int Team;
|
||||
public string Slot; // slot ID, or null for observer
|
||||
public string Bot; // Bot type, null for real clients
|
||||
public int BotControllerClientIndex; // who added the bot to the slot
|
||||
public bool IsAdmin;
|
||||
public bool IsReady { get { return State == ClientState.Ready; } }
|
||||
public bool IsInvalid { get { return State == ClientState.Invalid; } }
|
||||
public bool IsObserver { get { return Slot == null; } }
|
||||
public int Latency = -1;
|
||||
public int LatencyJitter = -1;
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace OpenRA.Network
|
||||
Country = "random",
|
||||
SpawnPoint = 0,
|
||||
Team = 0,
|
||||
State = Session.ClientState.NotReady
|
||||
State = Session.ClientState.Invalid
|
||||
};
|
||||
|
||||
var response = new HandshakeResponse()
|
||||
|
||||
@@ -272,7 +272,7 @@ namespace OpenRA.Server
|
||||
Country = "random",
|
||||
SpawnPoint = 0,
|
||||
Team = 0,
|
||||
State = Session.ClientState.NotReady,
|
||||
State = Session.ClientState.Invalid,
|
||||
IsAdmin = !LobbyInfo.Clients.Any(c1 => c1.IsAdmin)
|
||||
};
|
||||
|
||||
@@ -572,19 +572,31 @@ namespace OpenRA.Server
|
||||
|
||||
public void StartGame()
|
||||
{
|
||||
State = ServerState.GameStarted;
|
||||
listener.Stop();
|
||||
|
||||
Console.WriteLine("Game started");
|
||||
|
||||
foreach (var c in Conns)
|
||||
foreach (var d in Conns)
|
||||
DispatchOrdersToClient(c, d.PlayerIndex, 0x7FFFFFFF, new byte[] { 0xBF });
|
||||
|
||||
// Drop any unvalidated clients
|
||||
foreach (var c in PreConns.ToArray())
|
||||
DropClient(c);
|
||||
|
||||
// Drop any players who are not ready
|
||||
foreach (var c in Conns.ToArray())
|
||||
{
|
||||
if (GetClient(c).IsInvalid)
|
||||
{
|
||||
SendOrderTo(c, "ServerError", "You have been kicked from the server");
|
||||
DropClient(c);
|
||||
}
|
||||
}
|
||||
|
||||
SyncLobbyInfo();
|
||||
State = ServerState.GameStarted;
|
||||
|
||||
foreach (var c in Conns)
|
||||
foreach (var d in Conns)
|
||||
DispatchOrdersToClient(c, d.PlayerIndex, 0x7FFFFFFF, new byte[] { 0xBF });
|
||||
|
||||
DispatchOrders(null, 0,
|
||||
new ServerOrder("StartGame", "").Serialize());
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Widgets
|
||||
@@ -17,45 +18,57 @@ namespace OpenRA.Widgets
|
||||
public int Percentage = 0;
|
||||
public bool Indeterminate = false;
|
||||
|
||||
public Func<int> GetPercentage;
|
||||
public Func<bool> IsIndeterminate;
|
||||
|
||||
// Indeterminant bar properties
|
||||
float offset = 0f;
|
||||
float tickStep = 0.04f;
|
||||
|
||||
public ProgressBarWidget() {}
|
||||
protected ProgressBarWidget(ProgressBarWidget widget)
|
||||
: base(widget)
|
||||
public ProgressBarWidget()
|
||||
{
|
||||
Percentage = widget.Percentage;
|
||||
GetPercentage = () => Percentage;
|
||||
IsIndeterminate = () => Indeterminate;
|
||||
}
|
||||
|
||||
protected ProgressBarWidget(ProgressBarWidget other)
|
||||
: base(other)
|
||||
{
|
||||
Percentage = other.Percentage;
|
||||
GetPercentage = other.GetPercentage;
|
||||
IsIndeterminate = other.IsIndeterminate;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
var rb = RenderBounds;
|
||||
var percentage = GetPercentage();
|
||||
WidgetUtils.DrawPanel("progressbar-bg", rb);
|
||||
|
||||
Rectangle barRect = Indeterminate ?
|
||||
Rectangle barRect = wasIndeterminate ?
|
||||
new Rectangle(rb.X + 2 + (int)(0.75*offset*(rb.Width - 4)), rb.Y + 2, (rb.Width - 4) / 4, rb.Height - 4) :
|
||||
new Rectangle(rb.X + 2, rb.Y + 2, Percentage * (rb.Width - 4) / 100, rb.Height - 4);
|
||||
new Rectangle(rb.X + 2, rb.Y + 2, percentage * (rb.Width - 4) / 100, rb.Height - 4);
|
||||
|
||||
if (barRect.Width > 0)
|
||||
WidgetUtils.DrawPanel("progressbar-thumb", barRect);
|
||||
}
|
||||
|
||||
bool wasIndeterminate;
|
||||
public override void Tick()
|
||||
{
|
||||
if (Indeterminate)
|
||||
var indeterminate = IsIndeterminate();
|
||||
if (indeterminate != wasIndeterminate)
|
||||
offset = 0f;
|
||||
|
||||
if (indeterminate)
|
||||
{
|
||||
offset += tickStep;
|
||||
offset = offset.Clamp(0f, 1f);
|
||||
if (offset == 0f || offset == 1f)
|
||||
tickStep *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetIndeterminate(bool value)
|
||||
{
|
||||
Indeterminate = value;
|
||||
offset = 0f;
|
||||
wasIndeterminate = indeterminate;
|
||||
}
|
||||
|
||||
public override Widget Clone() { return new ProgressBarWidget(this); }
|
||||
|
||||
@@ -487,6 +487,7 @@
|
||||
<Compile Include="RemoveImmediately.cs" />
|
||||
<Compile Include="Attack\AttackFollow.cs" />
|
||||
<Compile Include="Attack\AttackGarrisoned.cs" />
|
||||
<Compile Include="Widgets\Logic\LobbyMapPreviewLogic.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA.Server
|
||||
server.SendOrderTo(conn, "Message", "Cannot change state when game started. ({0})".F(cmd));
|
||||
return false;
|
||||
}
|
||||
else if (client.State == Session.ClientState.Ready && !(cmd == "ready" || cmd == "startgame"))
|
||||
else if (client.State == Session.ClientState.Ready && !(cmd.StartsWith("state") || cmd == "startgame"))
|
||||
{
|
||||
server.SendOrderTo(conn, "Message", "Cannot change state when marked as ready.");
|
||||
return false;
|
||||
@@ -75,14 +75,17 @@ namespace OpenRA.Mods.RA.Server
|
||||
|
||||
var dict = new Dictionary<string, Func<string, bool>>
|
||||
{
|
||||
{ "ready",
|
||||
{ "state",
|
||||
s =>
|
||||
{
|
||||
// if we're downloading, we can't ready up.
|
||||
if (client.State == Session.ClientState.NotReady)
|
||||
client.State = Session.ClientState.Ready;
|
||||
else if (client.State == Session.ClientState.Ready)
|
||||
client.State = Session.ClientState.NotReady;
|
||||
var state = Session.ClientState.Invalid;
|
||||
if (!Enum<Session.ClientState>.TryParse(s, false, out state))
|
||||
{
|
||||
server.SendOrderTo(conn, "Message", "Malformed state command");
|
||||
return true;
|
||||
}
|
||||
|
||||
client.State = state;
|
||||
|
||||
Log.Write("server", "Player @{0} is {1}",
|
||||
conn.socket.RemoteEndPoint, client.State);
|
||||
@@ -290,6 +293,10 @@ namespace OpenRA.Mods.RA.Server
|
||||
LoadMap(server);
|
||||
SetDefaultDifficulty(server);
|
||||
|
||||
// Reset client states
|
||||
foreach (var c in server.LobbyInfo.Clients)
|
||||
c.State = Session.ClientState.Invalid;
|
||||
|
||||
// Reassign players into new slots based on their old slots:
|
||||
// - Observers remain as observers
|
||||
// - Players who now lack a slot are made observers
|
||||
@@ -303,7 +310,6 @@ namespace OpenRA.Mods.RA.Server
|
||||
continue;
|
||||
|
||||
c.SpawnPoint = 0;
|
||||
c.State = Session.ClientState.NotReady;
|
||||
c.Slot = i < slots.Length ? slots[i++] : null;
|
||||
if (c.Slot != null)
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
void ShowDownloadDialog()
|
||||
{
|
||||
statusLabel.GetText = () => "Initializing...";
|
||||
progressBar.SetIndeterminate(true);
|
||||
progressBar.Indeterminate = true;
|
||||
var retryButton = panel.Get<ButtonWidget>("RETRY_BUTTON");
|
||||
retryButton.IsVisible = () => false;
|
||||
|
||||
@@ -55,9 +55,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
Action<DownloadProgressChangedEventArgs> onDownloadProgress = i =>
|
||||
{
|
||||
if (progressBar.Indeterminate)
|
||||
progressBar.SetIndeterminate(false);
|
||||
|
||||
progressBar.Indeterminate = false;
|
||||
progressBar.Percentage = i.ProgressPercentage;
|
||||
statusLabel.GetText = () => "Downloading {1}/{2} kB ({0}%)".F(i.ProgressPercentage, i.BytesReceived / 1024, i.TotalBytesToReceive / 1024);
|
||||
};
|
||||
@@ -91,7 +89,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
// Automatically extract
|
||||
statusLabel.GetText = () => "Extracting...";
|
||||
progressBar.SetIndeterminate(true);
|
||||
progressBar.Indeterminate = true;
|
||||
if (InstallUtils.ExtractZip(file, dest, onExtractProgress, onError))
|
||||
{
|
||||
Game.RunAfterTick(() =>
|
||||
|
||||
@@ -23,12 +23,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
static readonly Action DoNothing = () => { };
|
||||
|
||||
public MapPreview Map = MapCache.UnknownMap;
|
||||
|
||||
readonly Action onStart;
|
||||
readonly Action onExit;
|
||||
readonly OrderManager orderManager;
|
||||
readonly bool skirmishMode;
|
||||
|
||||
enum PanelType { Players, Options, Kick }
|
||||
enum PanelType { Players, Options, Kick, ForceStart }
|
||||
PanelType panel = PanelType.Players;
|
||||
|
||||
Widget lobby;
|
||||
@@ -41,7 +43,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
ScrollPanelWidget players;
|
||||
Dictionary<string, string> countryNames;
|
||||
MapPreview preview = MapCache.UnknownMap;
|
||||
|
||||
ColorPreviewManagerWidget colorPreview;
|
||||
|
||||
@@ -108,6 +109,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (name != null)
|
||||
name.GetText = () => orderManager.LobbyInfo.GlobalSettings.ServerName;
|
||||
|
||||
Ui.LoadWidget("LOBBY_MAP_PREVIEW", lobby.Get("MAP_PREVIEW_ROOT"), new WidgetArgs
|
||||
{
|
||||
{ "orderManager", orderManager },
|
||||
{ "lobby", this }
|
||||
});
|
||||
|
||||
UpdateCurrentMap();
|
||||
players = Ui.LoadWidget<ScrollPanelWidget>("LOBBY_PLAYER_BIN", lobby.Get("PLAYER_BIN_ROOT"), new WidgetArgs());
|
||||
players.IsVisible = () => panel == PanelType.Players;
|
||||
@@ -125,30 +132,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
colorPreview = lobby.Get<ColorPreviewManagerWidget>("COLOR_MANAGER");
|
||||
colorPreview.Color = Game.Settings.Player.Color;
|
||||
|
||||
var mapPreview = lobby.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||
mapPreview.Preview = () => preview;
|
||||
mapPreview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, mapPreview, preview, mi);
|
||||
mapPreview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, preview);
|
||||
|
||||
var mapTitle = lobby.GetOrNull<LabelWidget>("MAP_TITLE");
|
||||
if (mapTitle != null)
|
||||
mapTitle.GetText = () => preview.Title;
|
||||
|
||||
var mapType = lobby.GetOrNull<LabelWidget>("MAP_TYPE");
|
||||
if (mapType != null)
|
||||
mapType.GetText = () => preview.Type;
|
||||
|
||||
var mapAuthor = lobby.GetOrNull<LabelWidget>("MAP_AUTHOR");
|
||||
if (mapAuthor != null)
|
||||
mapAuthor.GetText = () => "Created by {0}".F(preview.Author);
|
||||
|
||||
countryNames = Rules.Info["world"].Traits.WithInterface<CountryInfo>()
|
||||
.Where(c => c.Selectable)
|
||||
.ToDictionary(a => a.Race, a => a.Name);
|
||||
countryNames.Add("random", "Any");
|
||||
|
||||
var gameStarting = false;
|
||||
Func<bool> configurationDisabled = () => !Game.IsHost || gameStarting || panel == PanelType.Kick ||
|
||||
Func<bool> configurationDisabled = () => !Game.IsHost || gameStarting ||
|
||||
panel == PanelType.Kick || panel == PanelType.ForceStart ||
|
||||
orderManager.LocalClient == null || orderManager.LocalClient.IsReady;
|
||||
|
||||
var mapButton = lobby.GetOrNull<ButtonWidget>("CHANGEMAP_BUTTON");
|
||||
@@ -166,7 +157,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||
{
|
||||
{ "initialMap", preview.Uid },
|
||||
{ "initialMap", Map.Uid },
|
||||
{ "onExit", DoNothing },
|
||||
{ "onSelect", onSelect }
|
||||
});
|
||||
@@ -271,10 +262,17 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
optionsBin.IsVisible = () => panel == PanelType.Options;
|
||||
|
||||
var optionsButton = lobby.Get<ButtonWidget>("OPTIONS_BUTTON");
|
||||
optionsButton.IsDisabled = () => panel == PanelType.Kick;
|
||||
optionsButton.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart;
|
||||
optionsButton.GetText = () => panel == PanelType.Options ? "Players" : "Options";
|
||||
optionsButton.OnClick = () => panel = (panel == PanelType.Options) ? PanelType.Players : PanelType.Options;
|
||||
|
||||
// Force start panel
|
||||
Action startGame = () =>
|
||||
{
|
||||
gameStarting = true;
|
||||
orderManager.IssueOrder(Order.Command("startgame"));
|
||||
};
|
||||
|
||||
var startGameButton = lobby.GetOrNull<ButtonWidget>("START_GAME_BUTTON");
|
||||
if (startGameButton != null)
|
||||
{
|
||||
@@ -282,25 +280,33 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null);
|
||||
startGameButton.OnClick = () =>
|
||||
{
|
||||
gameStarting = true;
|
||||
orderManager.IssueOrder(Order.Command("startgame"));
|
||||
Func<KeyValuePair<string, Session.Slot>, bool> notReady = sl =>
|
||||
{
|
||||
var cl = orderManager.LobbyInfo.ClientInSlot(sl.Key);
|
||||
|
||||
// Bots and admins don't count
|
||||
return cl != null && !cl.IsAdmin && cl.Bot == null && !cl.IsReady;
|
||||
};
|
||||
|
||||
if (orderManager.LobbyInfo.Slots.Any(notReady))
|
||||
panel = PanelType.ForceStart;
|
||||
else
|
||||
startGame();
|
||||
};
|
||||
}
|
||||
|
||||
var statusCheckbox = lobby.GetOrNull<CheckboxWidget>("STATUS_CHECKBOX");
|
||||
if (statusCheckbox != null)
|
||||
{
|
||||
statusCheckbox.IsHighlighted = () => !statusCheckbox.IsChecked() &&
|
||||
orderManager.LobbyInfo.FirstEmptySlot() == null &&
|
||||
orderManager.LocalFrameNumber / 25 % 2 == 0;
|
||||
}
|
||||
var forceStartBin = Ui.LoadWidget("FORCE_START_DIALOG", lobby, new WidgetArgs());
|
||||
forceStartBin.IsVisible = () => panel == PanelType.ForceStart;
|
||||
forceStartBin.Get("KICK_WARNING").IsVisible = () => orderManager.LobbyInfo.Clients.Any(c => c.IsInvalid);
|
||||
forceStartBin.Get<ButtonWidget>("OK_BUTTON").OnClick = startGame;
|
||||
forceStartBin.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players;
|
||||
|
||||
// Options panel
|
||||
var allowCheats = optionsBin.GetOrNull<CheckboxWidget>("ALLOWCHEATS_CHECKBOX");
|
||||
if (allowCheats != null)
|
||||
{
|
||||
allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
|
||||
allowCheats.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Cheats.HasValue || configurationDisabled();
|
||||
allowCheats.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Cheats.HasValue || configurationDisabled();
|
||||
allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command(
|
||||
"allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));
|
||||
}
|
||||
@@ -309,7 +315,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (crates != null)
|
||||
{
|
||||
crates.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Crates;
|
||||
crates.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Crates.HasValue || configurationDisabled();
|
||||
crates.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Crates.HasValue || configurationDisabled();
|
||||
crates.OnClick = () => orderManager.IssueOrder(Order.Command(
|
||||
"crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates)));
|
||||
}
|
||||
@@ -318,7 +324,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (allybuildradius != null)
|
||||
{
|
||||
allybuildradius.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius;
|
||||
allybuildradius.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.AllyBuildRadius.HasValue || configurationDisabled();
|
||||
allybuildradius.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.AllyBuildRadius.HasValue || configurationDisabled();
|
||||
allybuildradius.OnClick = () => orderManager.IssueOrder(Order.Command(
|
||||
"allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius)));
|
||||
}
|
||||
@@ -327,7 +333,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (fragileAlliance != null)
|
||||
{
|
||||
fragileAlliance.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances;
|
||||
fragileAlliance.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.FragileAlliances.HasValue || configurationDisabled();
|
||||
fragileAlliance.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.FragileAlliances.HasValue || configurationDisabled();
|
||||
fragileAlliance.OnClick = () => orderManager.IssueOrder(Order.Command(
|
||||
"fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances)));
|
||||
}
|
||||
@@ -335,12 +341,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
var difficulty = optionsBin.GetOrNull<DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");
|
||||
if (difficulty != null)
|
||||
{
|
||||
difficulty.IsVisible = () => preview.Status == MapStatus.Available && preview.Map.Options.Difficulties.Any();
|
||||
difficulty.IsDisabled = () => preview.Status != MapStatus.Available || configurationDisabled();
|
||||
difficulty.IsVisible = () => Map.Status == MapStatus.Available && Map.Map.Options.Difficulties.Any();
|
||||
difficulty.IsDisabled = () => Map.Status != MapStatus.Available || configurationDisabled();
|
||||
difficulty.GetText = () => orderManager.LobbyInfo.GlobalSettings.Difficulty;
|
||||
difficulty.OnMouseDown = _ =>
|
||||
{
|
||||
var options = preview.Map.Options.Difficulties.Select(d => new DropDownOption
|
||||
var options = Map.Map.Options.Difficulties.Select(d => new DropDownOption
|
||||
{
|
||||
Title = d,
|
||||
IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d,
|
||||
@@ -372,8 +378,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
var classes = Rules.Info["world"].Traits.WithInterface<MPStartUnitsInfo>()
|
||||
.Select(a => a.Class).Distinct();
|
||||
|
||||
startingUnits.IsDisabled = () => preview.Status != MapStatus.Available || !preview.Map.Options.ConfigurableStartingUnits || configurationDisabled();
|
||||
startingUnits.GetText = () => preview.Status != MapStatus.Available || !preview.Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
|
||||
startingUnits.IsDisabled = () => Map.Status != MapStatus.Available || !Map.Map.Options.ConfigurableStartingUnits || configurationDisabled();
|
||||
startingUnits.GetText = () => Map.Status != MapStatus.Available || !Map.Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
|
||||
startingUnits.OnMouseDown = _ =>
|
||||
{
|
||||
var options = classes.Select(c => new DropDownOption
|
||||
@@ -399,8 +405,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
var startingCash = optionsBin.GetOrNull<DropDownButtonWidget>("STARTINGCASH_DROPDOWNBUTTON");
|
||||
if (startingCash != null)
|
||||
{
|
||||
startingCash.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.StartingCash.HasValue || configurationDisabled();
|
||||
startingCash.GetText = () => preview.Status != MapStatus.Available || preview.Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
|
||||
startingCash.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.StartingCash.HasValue || configurationDisabled();
|
||||
startingCash.GetText = () => Map.Status != MapStatus.Available || Map.Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
|
||||
startingCash.OnMouseDown = _ =>
|
||||
{
|
||||
var options = Rules.Info["player"].Traits.Get<PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption
|
||||
@@ -425,7 +431,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (enableShroud != null)
|
||||
{
|
||||
enableShroud.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Shroud;
|
||||
enableShroud.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Shroud.HasValue || configurationDisabled();
|
||||
enableShroud.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Shroud.HasValue || configurationDisabled();
|
||||
enableShroud.OnClick = () => orderManager.IssueOrder(Order.Command(
|
||||
"shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud)));
|
||||
}
|
||||
@@ -434,7 +440,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (enableFog != null)
|
||||
{
|
||||
enableFog.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Fog;
|
||||
enableFog.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Fog.HasValue || configurationDisabled();
|
||||
enableFog.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Fog.HasValue || configurationDisabled();
|
||||
enableFog.OnClick = () => orderManager.IssueOrder(Order.Command(
|
||||
"fog {0}".F(!orderManager.LobbyInfo.GlobalSettings.Fog)));
|
||||
}
|
||||
@@ -533,25 +539,23 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
void UpdateCurrentMap()
|
||||
{
|
||||
var uid = orderManager.LobbyInfo.GlobalSettings.Map;
|
||||
if (preview.Uid == uid)
|
||||
if (Map.Uid == uid)
|
||||
return;
|
||||
|
||||
preview = Game.modData.MapCache[uid];
|
||||
if (preview.Status != MapStatus.Available)
|
||||
{
|
||||
if (Game.Settings.Game.AllowDownloading)
|
||||
{
|
||||
Game.DownloadMap(uid);
|
||||
Game.Debug("A new map has been downloaded...");
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException("Server's new map doesn't exist on your system and Downloading turned off");
|
||||
}
|
||||
Map = Game.modData.MapCache[uid];
|
||||
|
||||
// Restore default starting cash if the last map set it to something invalid
|
||||
var pri = Rules.Info["player"].Traits.Get<PlayerResourcesInfo>();
|
||||
if (!preview.Map.Options.StartingCash.HasValue && !pri.SelectableCash.Contains(orderManager.LobbyInfo.GlobalSettings.StartingCash))
|
||||
orderManager.IssueOrder(Order.Command("startingcash {0}".F(pri.DefaultCash)));
|
||||
if (Map.Status == MapStatus.Available)
|
||||
{
|
||||
// Tell the server that we have the map
|
||||
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
|
||||
|
||||
// Restore default starting cash if the last map set it to something invalid
|
||||
var pri = Rules.Info["player"].Traits.Get<PlayerResourcesInfo>();
|
||||
if (!Map.Map.Options.StartingCash.HasValue && !pri.SelectableCash.Contains(orderManager.LobbyInfo.GlobalSettings.StartingCash))
|
||||
orderManager.IssueOrder(Order.Command("startingcash {0}".F(pri.DefaultCash)));
|
||||
}
|
||||
else if (Game.Settings.Game.AllowDownloading)
|
||||
Game.modData.MapCache.QueryRemoteMapDetails(new [] { uid });
|
||||
}
|
||||
|
||||
void UpdatePlayerList()
|
||||
@@ -600,8 +604,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
LobbyUtils.SetupEditableColorWidget(template, slot, client, orderManager, colorPreview);
|
||||
LobbyUtils.SetupEditableFactionWidget(template, slot, client, orderManager, countryNames);
|
||||
LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, preview.SpawnPoints.Count);
|
||||
LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager);
|
||||
LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, Map);
|
||||
LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager, Map);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
148
OpenRA.Mods.RA/Widgets/Logic/LobbyMapPreviewLogic.cs
Normal file
148
OpenRA.Mods.RA/Widgets/Logic/LobbyMapPreviewLogic.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
public class LobbyMapPreviewLogic
|
||||
{
|
||||
[ObjectCreator.UseCtor]
|
||||
internal LobbyMapPreviewLogic(Widget widget, OrderManager orderManager, LobbyLogic lobby)
|
||||
{
|
||||
var available = widget.GetOrNull("MAP_AVAILABLE");
|
||||
if (available != null)
|
||||
{
|
||||
available.IsVisible = () => lobby.Map.Status == MapStatus.Available;
|
||||
|
||||
var preview = available.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||
preview.Preview = () => lobby.Map;
|
||||
preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi);
|
||||
preview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, lobby.Map);
|
||||
|
||||
var title = available.GetOrNull<LabelWidget>("MAP_TITLE");
|
||||
if (title != null)
|
||||
title.GetText = () => lobby.Map.Title;
|
||||
|
||||
var type = available.GetOrNull<LabelWidget>("MAP_TYPE");
|
||||
if (type != null)
|
||||
type.GetText = () => lobby.Map.Type;
|
||||
|
||||
var author = available.GetOrNull<LabelWidget>("MAP_AUTHOR");
|
||||
if (author != null)
|
||||
author.GetText = () => "Created by {0}".F(lobby.Map.Author);
|
||||
}
|
||||
|
||||
var download = widget.GetOrNull("MAP_DOWNLOADABLE");
|
||||
if (download != null)
|
||||
{
|
||||
download.IsVisible = () => lobby.Map.Status == MapStatus.DownloadAvailable;
|
||||
|
||||
var preview = download.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||
preview.Preview = () => lobby.Map;
|
||||
preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi);
|
||||
preview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, lobby.Map);
|
||||
|
||||
var title = download.GetOrNull<LabelWidget>("MAP_TITLE");
|
||||
if (title != null)
|
||||
title.GetText = () => lobby.Map.Title;
|
||||
|
||||
var type = download.GetOrNull<LabelWidget>("MAP_TYPE");
|
||||
if (type != null)
|
||||
type.GetText = () => lobby.Map.Type;
|
||||
|
||||
var author = download.GetOrNull<LabelWidget>("MAP_AUTHOR");
|
||||
if (author != null)
|
||||
author.GetText = () => "Created by {0}".F(lobby.Map.Author);
|
||||
|
||||
var install = download.GetOrNull<ButtonWidget>("MAP_INSTALL");
|
||||
if (install != null)
|
||||
install.OnClick = () => lobby.Map.Install();
|
||||
}
|
||||
|
||||
var progress = widget.GetOrNull("MAP_PROGRESS");
|
||||
if (progress != null)
|
||||
{
|
||||
progress.IsVisible = () => lobby.Map.Status != MapStatus.Available && lobby.Map.Status != MapStatus.DownloadAvailable;
|
||||
|
||||
var preview = progress.Get<MapPreviewWidget>("MAP_PREVIEW");
|
||||
preview.Preview = () => lobby.Map;
|
||||
preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi);
|
||||
preview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, lobby.Map);
|
||||
|
||||
var title = progress.GetOrNull<LabelWidget>("MAP_TITLE");
|
||||
if (title != null)
|
||||
title.GetText = () => lobby.Map.Title;
|
||||
|
||||
var type = progress.GetOrNull<LabelWidget>("MAP_TYPE");
|
||||
if (type != null)
|
||||
type.GetText = () => lobby.Map.Type;
|
||||
|
||||
var statusSearching = progress.GetOrNull("MAP_STATUS_SEARCHING");
|
||||
if (statusSearching != null)
|
||||
statusSearching.IsVisible = () => lobby.Map.Status == MapStatus.Searching;
|
||||
|
||||
var statusUnavailable = progress.GetOrNull("MAP_STATUS_UNAVAILABLE");
|
||||
if (statusUnavailable != null)
|
||||
statusUnavailable.IsVisible = () => lobby.Map.Status == MapStatus.Unavailable;
|
||||
|
||||
var statusError = progress.GetOrNull("MAP_STATUS_ERROR");
|
||||
if (statusError != null)
|
||||
statusError.IsVisible = () => lobby.Map.Status == MapStatus.DownloadError;
|
||||
|
||||
var statusDownloading = progress.GetOrNull<LabelWidget>("MAP_STATUS_DOWNLOADING");
|
||||
if (statusDownloading != null)
|
||||
{
|
||||
statusDownloading.IsVisible = () => lobby.Map.Status == MapStatus.Downloading;
|
||||
statusDownloading.GetText = () =>
|
||||
{
|
||||
if (lobby.Map.DownloadBytes == 0)
|
||||
return "Connecting...";
|
||||
|
||||
// Server does not provide the total file length
|
||||
if (lobby.Map.DownloadPercentage == 0)
|
||||
return "Downloading {0} kB".F(lobby.Map.DownloadBytes / 1024);
|
||||
|
||||
return "Downloading {0} kB ({1}%)".F(lobby.Map.DownloadBytes / 1024, lobby.Map.DownloadPercentage);
|
||||
};
|
||||
}
|
||||
|
||||
var retry = progress.GetOrNull<ButtonWidget>("MAP_RETRY");
|
||||
if (retry != null)
|
||||
{
|
||||
retry.IsVisible = () => lobby.Map.Status == MapStatus.DownloadError || lobby.Map.Status == MapStatus.Unavailable;
|
||||
retry.OnClick = () =>
|
||||
{
|
||||
if (lobby.Map.Status == MapStatus.DownloadError)
|
||||
lobby.Map.Install();
|
||||
else if (lobby.Map.Status == MapStatus.Unavailable)
|
||||
Game.modData.MapCache.QueryRemoteMapDetails(new [] { lobby.Map.Uid });
|
||||
};
|
||||
|
||||
retry.GetText = () => lobby.Map.Status == MapStatus.DownloadError ? "Retry Install" : "Retry Search";
|
||||
}
|
||||
|
||||
var progressbar = progress.GetOrNull<ProgressBarWidget>("MAP_PROGRESSBAR");
|
||||
if (progressbar != null)
|
||||
{
|
||||
progressbar.IsIndeterminate = () => lobby.Map.DownloadPercentage == 0;
|
||||
progressbar.GetPercentage = () => lobby.Map.DownloadPercentage;
|
||||
progressbar.IsVisible = () => !retry.IsVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,11 +363,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
factionflag.GetImageCollection = () => "flags";
|
||||
}
|
||||
|
||||
public static void SetupEditableTeamWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, int teamCount)
|
||||
public static void SetupEditableTeamWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, MapPreview map)
|
||||
{
|
||||
var dropdown = parent.Get<DropDownButtonWidget>("TEAM");
|
||||
dropdown.IsDisabled = () => s.LockTeam || orderManager.LocalClient.IsReady;
|
||||
dropdown.OnMouseDown = _ => ShowTeamDropDown(dropdown, c, orderManager, teamCount);
|
||||
dropdown.OnMouseDown = _ => ShowTeamDropDown(dropdown, c, orderManager, map.PlayerCount);
|
||||
dropdown.GetText = () => (c.Team == 0) ? "-" : c.Team.ToString();
|
||||
}
|
||||
|
||||
@@ -376,13 +376,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
parent.Get<LabelWidget>("TEAM").GetText = () => (c.Team == 0) ? "-" : c.Team.ToString();
|
||||
}
|
||||
|
||||
public static void SetupEditableReadyWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager)
|
||||
public static void SetupEditableReadyWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, MapPreview map)
|
||||
{
|
||||
var status = parent.Get<CheckboxWidget>("STATUS_CHECKBOX");
|
||||
status.IsChecked = () => orderManager.LocalClient.IsReady || c.Bot != null;
|
||||
status.IsVisible = () => true;
|
||||
status.IsDisabled = () => c.Bot != null;
|
||||
status.OnClick = () => orderManager.IssueOrder(Order.Command("ready"));
|
||||
status.IsDisabled = () => c.Bot != null || map.Status != MapStatus.Available;
|
||||
|
||||
var state = orderManager.LocalClient.IsReady ? Session.ClientState.NotReady : Session.ClientState.Ready;
|
||||
status.OnClick = () => orderManager.IssueOrder(Order.Command("state {0}".F(state)));
|
||||
}
|
||||
|
||||
public static void SetupReadyWidget(Widget parent, Session.Slot s, Session.Client c)
|
||||
|
||||
@@ -147,30 +147,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
List<Widget> rows = new List<Widget>();
|
||||
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
serverList.RemoveChildren();
|
||||
currentServer = null;
|
||||
|
||||
if (games == null)
|
||||
{
|
||||
searchStatus = SearchStatus.Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!games.Any())
|
||||
{
|
||||
searchStatus = SearchStatus.NoGames;
|
||||
return;
|
||||
}
|
||||
|
||||
currentServer = games.FirstOrDefault();
|
||||
searchStatus = SearchStatus.Hidden;
|
||||
|
||||
foreach (var row in rows)
|
||||
serverList.AddChild(row);
|
||||
});
|
||||
|
||||
foreach (var loop in games.OrderByDescending(g => g.CanJoin()).ThenByDescending(g => g.Players))
|
||||
{
|
||||
var game = loop;
|
||||
@@ -241,6 +217,34 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (!Filtered(game))
|
||||
rows.Add(item);
|
||||
}
|
||||
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
serverList.RemoveChildren();
|
||||
currentServer = null;
|
||||
|
||||
if (games == null)
|
||||
{
|
||||
searchStatus = SearchStatus.Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!games.Any())
|
||||
{
|
||||
searchStatus = SearchStatus.NoGames;
|
||||
return;
|
||||
}
|
||||
|
||||
currentServer = games.FirstOrDefault();
|
||||
searchStatus = SearchStatus.Hidden;
|
||||
|
||||
// Search for any unknown maps
|
||||
if (Game.Settings.Game.AllowDownloading)
|
||||
Game.modData.MapCache.QueryRemoteMapDetails(games.Where(g => !Filtered(g)).Select(g => g.Map));
|
||||
|
||||
foreach (var row in rows)
|
||||
serverList.AddChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
void OpenLobby()
|
||||
|
||||
45
mods/cnc/chrome/color-picker.yaml
Normal file
45
mods/cnc/chrome/color-picker.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
Background@COLOR_CHOOSER:
|
||||
Logic:ColorPickerLogic
|
||||
Background:panel-black
|
||||
Width:234
|
||||
Height:105
|
||||
Children:
|
||||
Background@HUEBG:
|
||||
Background:panel-black
|
||||
X:5
|
||||
Y:5
|
||||
Width:148
|
||||
Height:13
|
||||
Children:
|
||||
HueSlider@HUE:
|
||||
X:2
|
||||
Y:2
|
||||
Width:144
|
||||
Height:9
|
||||
Ticks:5
|
||||
Background@MIXERBG:
|
||||
Background:panel-black
|
||||
X:5
|
||||
Y:23
|
||||
Width:148
|
||||
Height:76
|
||||
Children:
|
||||
ColorMixer@MIXER:
|
||||
X:2
|
||||
Y:2
|
||||
Width:144
|
||||
Height:72
|
||||
ShpImage@FACT:
|
||||
X:153
|
||||
Y:1
|
||||
Width:80
|
||||
Height:73
|
||||
Image:fact
|
||||
Palette:colorpicker
|
||||
Button@RANDOM_BUTTON:
|
||||
Key:tab
|
||||
X:158
|
||||
Y:74
|
||||
Width:70
|
||||
Height:25
|
||||
Text:Random
|
||||
@@ -1,49 +1,3 @@
|
||||
Background@COLOR_CHOOSER:
|
||||
Logic:ColorPickerLogic
|
||||
Background:panel-black
|
||||
Width:234
|
||||
Height:105
|
||||
Children:
|
||||
Background@HUEBG:
|
||||
Background:panel-black
|
||||
X:5
|
||||
Y:5
|
||||
Width:148
|
||||
Height:13
|
||||
Children:
|
||||
HueSlider@HUE:
|
||||
X:2
|
||||
Y:2
|
||||
Width:144
|
||||
Height:9
|
||||
Ticks:5
|
||||
Background@MIXERBG:
|
||||
Background:panel-black
|
||||
X:5
|
||||
Y:23
|
||||
Width:148
|
||||
Height:76
|
||||
Children:
|
||||
ColorMixer@MIXER:
|
||||
X:2
|
||||
Y:2
|
||||
Width:144
|
||||
Height:72
|
||||
ShpImage@FACT:
|
||||
X:153
|
||||
Y:1
|
||||
Width:80
|
||||
Height:73
|
||||
Image:fact
|
||||
Palette:colorpicker
|
||||
Button@RANDOM_BUTTON:
|
||||
Key:tab
|
||||
X:158
|
||||
Y:74
|
||||
Width:70
|
||||
Height:25
|
||||
Text:Random
|
||||
|
||||
ScrollPanel@LABEL_DROPDOWN_TEMPLATE:
|
||||
Width:DROPDOWN_WIDTH
|
||||
Background:panel-black
|
||||
@@ -146,187 +100,3 @@ Container@CONFIRM_PROMPT:
|
||||
Width:140
|
||||
Height:35
|
||||
Text:Confirm
|
||||
|
||||
Background@KICK_CLIENT_DIALOG:
|
||||
X:15
|
||||
Y:30
|
||||
Width:501
|
||||
Height:219
|
||||
Logic:KickClientLogic
|
||||
Background:scrollpanel-bg
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:40
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@TEXTA:
|
||||
X:0
|
||||
Y:67
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:You may also apply a temporary ban, preventing
|
||||
Label@TEXTB:
|
||||
X:0
|
||||
Y:85
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:them from joining for the remainder of this game.
|
||||
Checkbox@PREVENT_REJOINING_CHECKBOX:
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:120
|
||||
Width:150
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Temporarily Ban
|
||||
Button@OK_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 + 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Kick
|
||||
Font:Bold
|
||||
Button@CANCEL_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 - 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Cancel
|
||||
Font:Bold
|
||||
|
||||
Background@KICK_SPECTATORS_DIALOG:
|
||||
X:15
|
||||
Y:30
|
||||
Width:501
|
||||
Height:219
|
||||
Logic:KickSpectatorsLogic
|
||||
Background:scrollpanel-bg
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:40
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text:Kick Spectators
|
||||
Label@TEXT:
|
||||
X:0
|
||||
Y:85
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Button@OK_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 + 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Ok
|
||||
Font:Bold
|
||||
Button@CANCEL_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 - 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Cancel
|
||||
Font:Bold
|
||||
|
||||
Background@LOBBY_OPTIONS_BIN:
|
||||
X:15
|
||||
Y:30
|
||||
Width:501
|
||||
Height:219
|
||||
Background:scrollpanel-bg
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:30
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text: Map Options
|
||||
Container:
|
||||
X:30
|
||||
Y:65
|
||||
Width: PARENT_RIGHT-60
|
||||
Height: PARENT_BOTTOM-75
|
||||
Children:
|
||||
Checkbox@SHROUD_CHECKBOX:
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Shroud
|
||||
Checkbox@FOG_CHECKBOX:
|
||||
Y:35
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Fog of War
|
||||
Checkbox@CRATES_CHECKBOX:
|
||||
X:160
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Crates Appear
|
||||
Checkbox@ALLYBUILDRADIUS_CHECKBOX:
|
||||
X:160
|
||||
Y:35
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Build off Ally ConYards
|
||||
Checkbox@ALLOWCHEATS_CHECKBOX:
|
||||
X:325
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Debug Menu
|
||||
Label@STARTINGCASH_DESC:
|
||||
X:10
|
||||
Y:72
|
||||
Width:70
|
||||
Height:25
|
||||
Font:Regular
|
||||
Text:Starting Cash:
|
||||
Align:Right
|
||||
DropDownButton@STARTINGCASH_DROPDOWNBUTTON:
|
||||
X:85
|
||||
Y:72
|
||||
Width:120
|
||||
Height:25
|
||||
Font:Regular
|
||||
Text:$5000
|
||||
Label@STARTINGUNITS_DESC:
|
||||
X:PARENT_RIGHT - WIDTH - 135
|
||||
Y:72
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Starting Units:
|
||||
Align:Right
|
||||
DropDownButton@STARTINGUNITS_DROPDOWNBUTTON:
|
||||
X:PARENT_RIGHT - WIDTH + 10
|
||||
Y:72
|
||||
Width:140
|
||||
Height:25
|
||||
Font:Regular
|
||||
Label@DIFFICULTY_DESC:
|
||||
X:PARENT_RIGHT - WIDTH - 135
|
||||
Y:107
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Mission Difficulty:
|
||||
Align:Right
|
||||
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
|
||||
X:PARENT_RIGHT - WIDTH + 10
|
||||
Y:107
|
||||
Width:140
|
||||
Height:25
|
||||
Font:Regular
|
||||
248
mods/cnc/chrome/lobby-dialogs.yaml
Normal file
248
mods/cnc/chrome/lobby-dialogs.yaml
Normal file
@@ -0,0 +1,248 @@
|
||||
Background@KICK_CLIENT_DIALOG:
|
||||
X:15
|
||||
Y:30
|
||||
Width:501
|
||||
Height:219
|
||||
Logic:KickClientLogic
|
||||
Background:scrollpanel-bg
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:40
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@TEXTA:
|
||||
X:0
|
||||
Y:67
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:You may also apply a temporary ban, preventing
|
||||
Label@TEXTB:
|
||||
X:0
|
||||
Y:85
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:them from joining for the remainder of this game.
|
||||
Checkbox@PREVENT_REJOINING_CHECKBOX:
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:120
|
||||
Width:150
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Temporarily Ban
|
||||
Button@OK_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 + 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Kick
|
||||
Font:Bold
|
||||
Button@CANCEL_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 - 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Cancel
|
||||
Font:Bold
|
||||
|
||||
Background@KICK_SPECTATORS_DIALOG:
|
||||
X:15
|
||||
Y:30
|
||||
Width:501
|
||||
Height:219
|
||||
Logic:KickSpectatorsLogic
|
||||
Background:scrollpanel-bg
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:40
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text:Kick Spectators
|
||||
Label@TEXT:
|
||||
X:0
|
||||
Y:85
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Button@OK_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 + 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Ok
|
||||
Font:Bold
|
||||
Button@CANCEL_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 - 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Cancel
|
||||
Font:Bold
|
||||
|
||||
Background@LOBBY_OPTIONS_BIN:
|
||||
X:15
|
||||
Y:30
|
||||
Width:501
|
||||
Height:219
|
||||
Background:scrollpanel-bg
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:30
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text: Map Options
|
||||
Container:
|
||||
X:30
|
||||
Y:65
|
||||
Width: PARENT_RIGHT-60
|
||||
Height: PARENT_BOTTOM-75
|
||||
Children:
|
||||
Checkbox@SHROUD_CHECKBOX:
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Shroud
|
||||
Checkbox@FOG_CHECKBOX:
|
||||
Y:35
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Fog of War
|
||||
Checkbox@CRATES_CHECKBOX:
|
||||
X:160
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Crates Appear
|
||||
Checkbox@ALLYBUILDRADIUS_CHECKBOX:
|
||||
X:160
|
||||
Y:35
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Build off Ally ConYards
|
||||
Checkbox@ALLOWCHEATS_CHECKBOX:
|
||||
X:325
|
||||
Width:230
|
||||
Height:20
|
||||
Font:Regular
|
||||
Text:Debug Menu
|
||||
Label@STARTINGCASH_DESC:
|
||||
X:10
|
||||
Y:72
|
||||
Width:70
|
||||
Height:25
|
||||
Font:Regular
|
||||
Text:Starting Cash:
|
||||
Align:Right
|
||||
DropDownButton@STARTINGCASH_DROPDOWNBUTTON:
|
||||
X:85
|
||||
Y:72
|
||||
Width:120
|
||||
Height:25
|
||||
Font:Regular
|
||||
Text:$5000
|
||||
Label@STARTINGUNITS_DESC:
|
||||
X:PARENT_RIGHT - WIDTH - 135
|
||||
Y:72
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Starting Units:
|
||||
Align:Right
|
||||
DropDownButton@STARTINGUNITS_DROPDOWNBUTTON:
|
||||
X:PARENT_RIGHT - WIDTH + 10
|
||||
Y:72
|
||||
Width:140
|
||||
Height:25
|
||||
Font:Regular
|
||||
Label@DIFFICULTY_DESC:
|
||||
X:PARENT_RIGHT - WIDTH - 135
|
||||
Y:107
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Mission Difficulty:
|
||||
Align:Right
|
||||
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
|
||||
X:PARENT_RIGHT - WIDTH + 10
|
||||
Y:107
|
||||
Width:140
|
||||
Height:25
|
||||
Font:Regular
|
||||
|
||||
Background@FORCE_START_DIALOG:
|
||||
X:15
|
||||
Y:30
|
||||
Width:501
|
||||
Height:219
|
||||
Background:scrollpanel-bg
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:40
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text: Start Game?
|
||||
Label@TEXTA:
|
||||
X:0
|
||||
Y:67
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:One or more players are not yet ready.
|
||||
Label@TEXTB:
|
||||
X:0
|
||||
Y:85
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:Are you sure that you want to force start the game?
|
||||
Container@KICK_WARNING:
|
||||
Width:PARENT_RIGHT
|
||||
Children:
|
||||
Label@KICK_WARNING_A:
|
||||
X:0
|
||||
Y:106
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text:One or more clients are missing the selected
|
||||
Label@KICK_WARNING_B:
|
||||
X:0
|
||||
Y:123
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text:map, and will be kicked from the server.
|
||||
Button@OK_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 + 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Start
|
||||
Font:Bold
|
||||
Button@CANCEL_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 - 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Cancel
|
||||
Font:Bold
|
||||
145
mods/cnc/chrome/lobby-mappreview.yaml
Normal file
145
mods/cnc/chrome/lobby-mappreview.yaml
Normal file
@@ -0,0 +1,145 @@
|
||||
Container@LOBBY_MAP_PREVIEW:
|
||||
Logic:LobbyMapPreviewLogic
|
||||
X:PARENT_RIGHT-15-WIDTH
|
||||
Y:30
|
||||
Width:194
|
||||
Height:250
|
||||
Children:
|
||||
Container@MAP_AVAILABLE:
|
||||
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_TYPE:
|
||||
Y:212
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:TinyBold
|
||||
Align:Center
|
||||
Label@MAP_AUTHOR:
|
||||
Y:225
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Container@MAP_DOWNLOADABLE:
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM
|
||||
Children:
|
||||
Background@MAP_BG:
|
||||
Width:PARENT_RIGHT
|
||||
Height:164
|
||||
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:167
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@MAP_TYPE:
|
||||
Y:184
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:TinyBold
|
||||
Align:Center
|
||||
Label@MAP_AUTHOR:
|
||||
Y:197
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Button@MAP_INSTALL:
|
||||
Y:224
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Text:Install Map
|
||||
Container@MAP_PROGRESS:
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM
|
||||
Children:
|
||||
Background@MAP_BG:
|
||||
Width:PARENT_RIGHT
|
||||
Height:164
|
||||
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:167
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@MAP_STATUS_SEARCHING:
|
||||
Y:197
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text: Searching OpenRA Resource Center...
|
||||
Container@MAP_STATUS_UNAVAILABLE:
|
||||
Width:PARENT_RIGHT
|
||||
Children:
|
||||
Label@a:
|
||||
Y:184
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text:This map was not found on the
|
||||
Label@b:
|
||||
Y:197
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text:OpenRA Resource Center
|
||||
Label@MAP_STATUS_ERROR:
|
||||
Y:197
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text:An error occurred during installation
|
||||
Label@MAP_STATUS_DOWNLOADING:
|
||||
Y:197
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
ProgressBar@MAP_PROGRESSBAR:
|
||||
Y:224
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Indeterminate:True
|
||||
Button@MAP_RETRY:
|
||||
Y:224
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
@@ -17,40 +17,9 @@ Container@SERVER_LOBBY:
|
||||
Height:500
|
||||
Background:panel-black
|
||||
Children:
|
||||
Background@MAP_BG:
|
||||
X:PARENT_RIGHT-15-WIDTH
|
||||
Y:30
|
||||
Width:194
|
||||
Height:194
|
||||
Background:panel-gray
|
||||
Children:
|
||||
MapPreview@MAP_PREVIEW:
|
||||
X:1
|
||||
Y:1
|
||||
Width:192
|
||||
Height:192
|
||||
TooltipContainer:TOOLTIP_CONTAINER
|
||||
Label@MAP_TITLE:
|
||||
X:PARENT_RIGHT-15-WIDTH
|
||||
Y:227
|
||||
Width:194
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@MAP_TYPE:
|
||||
X:PARENT_RIGHT-15-WIDTH
|
||||
Y:242
|
||||
Width:194
|
||||
Height:25
|
||||
Font:TinyBold
|
||||
Align:Center
|
||||
Label@MAP_AUTHOR:
|
||||
X:PARENT_RIGHT-15-WIDTH
|
||||
Y:255
|
||||
Width:194
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Container@MAP_PREVIEW_ROOT:
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM
|
||||
Container@LABEL_CONTAINER:
|
||||
X:20
|
||||
Y:5
|
||||
|
||||
@@ -79,8 +79,11 @@ ChromeLayout:
|
||||
mods/cnc/chrome/createserver.yaml
|
||||
mods/cnc/chrome/directconnect.yaml
|
||||
mods/cnc/chrome/lobby.yaml
|
||||
mods/cnc/chrome/lobby-mappreview.yaml
|
||||
mods/cnc/chrome/lobby-playerbin.yaml
|
||||
mods/cnc/chrome/lobby-dialogs.yaml
|
||||
mods/cnc/chrome/connection.yaml
|
||||
mods/cnc/chrome/color-picker.yaml
|
||||
mods/cnc/chrome/mapchooser.yaml
|
||||
mods/cnc/chrome/replaybrowser.yaml
|
||||
mods/cnc/chrome/ingame.yaml
|
||||
|
||||
@@ -69,6 +69,7 @@ ChromeLayout:
|
||||
mods/ra/chrome/settings.yaml
|
||||
mods/ra/chrome/credits.yaml
|
||||
mods/ra/chrome/lobby.yaml
|
||||
mods/ra/chrome/lobby-mappreview.yaml
|
||||
mods/d2k/chrome/lobby-playerbin.yaml
|
||||
mods/ra/chrome/lobby-dialogs.yaml
|
||||
mods/d2k/chrome/color-picker.yaml
|
||||
|
||||
@@ -179,3 +179,68 @@ Background@LOBBY_OPTIONS_BIN:
|
||||
Width:140
|
||||
Height:25
|
||||
Font:Regular
|
||||
|
||||
Background@FORCE_START_DIALOG:
|
||||
X:20
|
||||
Y:67
|
||||
Width:535
|
||||
Height:235
|
||||
Background:dialog3
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:40
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text: Start Game?
|
||||
Label@TEXTA:
|
||||
X:0
|
||||
Y:67
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:One or more players are not yet ready.
|
||||
Label@TEXTB:
|
||||
X:0
|
||||
Y:85
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Regular
|
||||
Align:Center
|
||||
Text:Are you sure that you want to force start the game?
|
||||
Container@KICK_WARNING:
|
||||
Width:PARENT_RIGHT
|
||||
Children:
|
||||
Label@KICK_WARNING_A:
|
||||
X:0
|
||||
Y:106
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text:One or more clients are missing the selected
|
||||
Label@KICK_WARNING_B:
|
||||
X:0
|
||||
Y:123
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text:map, and will be kicked from the server.
|
||||
Button@OK_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 + 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Start
|
||||
Font:Bold
|
||||
Button@CANCEL_BUTTON:
|
||||
X:(PARENT_RIGHT - WIDTH)/2 - 75
|
||||
Y:155
|
||||
Width:120
|
||||
Height:25
|
||||
Text:Cancel
|
||||
Font:Bold
|
||||
147
mods/ra/chrome/lobby-mappreview.yaml
Normal file
147
mods/ra/chrome/lobby-mappreview.yaml
Normal file
@@ -0,0 +1,147 @@
|
||||
Container@LOBBY_MAP_PREVIEW:
|
||||
Logic:LobbyMapPreviewLogic
|
||||
X:PARENT_RIGHT-20-WIDTH
|
||||
Y:67
|
||||
Width:214
|
||||
Height:250
|
||||
Children:
|
||||
Container@MAP_AVAILABLE:
|
||||
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_TYPE:
|
||||
Y:232
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:TinyBold
|
||||
Align:Center
|
||||
Label@MAP_AUTHOR:
|
||||
Y:245
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Container@MAP_DOWNLOADABLE:
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM
|
||||
Children:
|
||||
Background@MAP_BG:
|
||||
Width:PARENT_RIGHT
|
||||
Height:182
|
||||
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:185
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@MAP_TYPE:
|
||||
Y:202
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:TinyBold
|
||||
Align:Center
|
||||
Label@MAP_AUTHOR:
|
||||
Y:215
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Button@MAP_INSTALL:
|
||||
Y:242
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Text:Install Map
|
||||
Container@MAP_PROGRESS:
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM
|
||||
Children:
|
||||
Background@MAP_BG:
|
||||
Width:PARENT_RIGHT
|
||||
Height:182
|
||||
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:185
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@MAP_STATUS_SEARCHING:
|
||||
Y:215
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text: Searching OpenRA Resource Center...
|
||||
Container@MAP_STATUS_UNAVAILABLE:
|
||||
Width:PARENT_RIGHT
|
||||
Children:
|
||||
Label@a:
|
||||
Y:202
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text:This map was not found on the
|
||||
Label@b:
|
||||
Y:215
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text:OpenRA Resource Center
|
||||
Label@MAP_STATUS_ERROR:
|
||||
Y:215
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Text:An error occurred during installation
|
||||
Label@MAP_STATUS_DOWNLOADING:
|
||||
Y:215
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
ProgressBar@MAP_PROGRESSBAR:
|
||||
Y:242
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Indeterminate:True
|
||||
Button@MAP_RETRY:
|
||||
Y:242
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
@@ -13,40 +13,9 @@ Background@SERVER_LOBBY:
|
||||
Width:PARENT_RIGHT
|
||||
Height:20
|
||||
Font:Bold
|
||||
Background@MAP_BG:
|
||||
X:PARENT_RIGHT-20-WIDTH
|
||||
Y:67
|
||||
Width:214
|
||||
Height:214
|
||||
Background:dialog3
|
||||
Children:
|
||||
MapPreview@MAP_PREVIEW:
|
||||
X:2
|
||||
Y:2
|
||||
Width:210
|
||||
Height:210
|
||||
TooltipContainer:TOOLTIP_CONTAINER
|
||||
Label@MAP_TITLE:
|
||||
X:PARENT_RIGHT-20-WIDTH
|
||||
Y:282
|
||||
Width:214
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Label@MAP_TYPE:
|
||||
X:PARENT_RIGHT-20-WIDTH
|
||||
Y:297
|
||||
Width:214
|
||||
Height:25
|
||||
Font:TinyBold
|
||||
Align:Center
|
||||
Label@MAP_AUTHOR:
|
||||
X:PARENT_RIGHT-20-WIDTH
|
||||
Y:310
|
||||
Width:214
|
||||
Height:25
|
||||
Font:Tiny
|
||||
Align:Center
|
||||
Container@MAP_PREVIEW_ROOT:
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM
|
||||
Container@LABEL_CONTAINER:
|
||||
X:25
|
||||
Y:40
|
||||
|
||||
@@ -83,6 +83,7 @@ ChromeLayout:
|
||||
mods/ra/chrome/settings.yaml
|
||||
mods/ra/chrome/credits.yaml
|
||||
mods/ra/chrome/lobby.yaml
|
||||
mods/ra/chrome/lobby-mappreview.yaml
|
||||
mods/ra/chrome/lobby-playerbin.yaml
|
||||
mods/ra/chrome/lobby-dialogs.yaml
|
||||
mods/ra/chrome/color-picker.yaml
|
||||
|
||||
@@ -108,6 +108,7 @@ ChromeLayout:
|
||||
mods/ra/chrome/settings.yaml
|
||||
mods/ra/chrome/credits.yaml
|
||||
mods/ra/chrome/lobby.yaml
|
||||
mods/ra/chrome/lobby-mappreview.yaml
|
||||
mods/ra/chrome/lobby-playerbin.yaml
|
||||
mods/ra/chrome/lobby-dialogs.yaml
|
||||
mods/ts/chrome/color-picker.yaml
|
||||
|
||||
Reference in New Issue
Block a user