Remove runtime mod merging. Closes #3421.

This commit is contained in:
Paul Chote
2013-10-06 12:44:20 +13:00
parent 4d893cb1f2
commit 6d6d1e230b
35 changed files with 143 additions and 186 deletions

View File

@@ -76,11 +76,13 @@ NEW:
Added modifier support to hotkeys.
Fixed a desync related to projectile contrails.
Fixed corrupted replays (which would immediately desync).
Removed runtime mod merging.
Build system and packages:
Added GeoIP to Makefile so it is installed properly.
Added desktop shortcut creation support to the Makefile and Windows installer.
COPYING and CHANGELOG are now shipped on all platforms.
Fixed 'make docs' crashing when the game assets are not installed.
Renamed Game.Mods launch argument to Game.Mod.
Mod / Custom map compatibility:
Mods can now include traits from TD and D2K in RA.
New sections MapFolders and Translations added to mod.yaml.
@@ -99,6 +101,7 @@ NEW:
Removed traits from World: SpatialBins.
Added InvalidTargets property to weapons.
Added modifier support for build palette hotkeys.
The Requires: option for inheriting from a parent mod has been removed. Mods can directly reference the parent mod files instead.
20130915:
All mods:

View File

@@ -29,8 +29,8 @@ or build it from the command-line with MSBuild.
Copy both the native DLLs from .\packaging\windows
and the CLI images from .\thirdparty to the main folder.
Run the game with `OpenRA.Game.exe Game.Mods=ra` for Red Alert
or `OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
Run the game with `OpenRA.Game.exe Game.Mod=ra` for Red Alert
or `OpenRA.Game.exe Game.Mod=cnc` for Command & Conquer
Debian/Ubuntu
-------------

View File

@@ -50,8 +50,8 @@ namespace OpenRA.Editor
FileSystem.LoadFromManifest(Game.modData.Manifest);
Rules.LoadRules(Game.modData.Manifest, new Map());
var mod = Game.modData.Manifest.Mods[0];
Text = "{0} Mod Version: {1} - OpenRA Editor".F(Mod.AllMods[mod].Title, Mod.AllMods[mod].Version);
var mod = Game.modData.Manifest.Mod;
Text = "{0} Mod Version: {1} - OpenRA Editor".F(mod.Title, mod.Version);
loadedMapName = null;
};

View File

@@ -18,8 +18,9 @@ namespace OpenRA.FileFormats
public class Manifest
{
public readonly Mod Mod;
public readonly string[]
Mods, Folders, MapFolders, Rules, ServerTraits,
Folders, MapFolders, Rules, ServerTraits,
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
Weapons, Voices, Notifications, Music, Movies, Translations, TileSets,
ChromeMetrics, PackageContents;
@@ -30,12 +31,13 @@ namespace OpenRA.FileFormats
public readonly Dictionary<string, Pair<string,int>> Fonts;
public readonly int TileSize = 24;
public Manifest(string[] mods)
public Manifest(string mod)
{
Mods = mods;
var yaml = new MiniYaml(null, mods
.Select(m => MiniYaml.FromFile("mods{0}{1}{0}mod.yaml".F(Path.DirectorySeparatorChar, m)))
.Aggregate(MiniYaml.MergeLiberal)).NodesDict;
var path = new [] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
Mod = FieldLoader.Load<Mod>(yaml["Metadata"]);
Mod.Id = mod;
// TODO: Use fieldloader
Folders = YamlList(yaml, "Folders");

View File

@@ -21,7 +21,6 @@ namespace OpenRA.FileFormats
public string Description;
public string Version;
public string Author;
public string Requires;
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
@@ -45,12 +44,5 @@ namespace OpenRA.FileFormats
}
return ret;
}
public string[] WithPrerequisites()
{
return Id.Iterate(m => AllMods[m].Requires)
.TakeWhile(m => m != null)
.ToArray();
}
}
}

View File

@@ -255,18 +255,6 @@ namespace OpenRA
}
}
public static Dictionary<String, Mod> CurrentMods
{
get
{
// Initialization hasn't completed yet
if (Mod.AllMods == null || modData == null)
return null;
return Mod.AllMods.Where(k => modData.Manifest.Mods.Contains(k.Key)).ToDictionary(k => k.Key, k => k.Value);
}
}
static Modifiers modifiers;
public static Modifiers GetModifierKeys() { return modifiers; }
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
@@ -328,7 +316,8 @@ namespace OpenRA
Console.WriteLine("Available mods:");
foreach(var mod in Mod.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
InitializeWithMods(Settings.Game.Mods);
InitializeWithMod(Settings.Game.Mod);
if (Settings.Server.DiscoverNatDevices)
{
@@ -338,7 +327,7 @@ namespace OpenRA
}
}
public static void InitializeWithMods(string[] mods)
public static void InitializeWithMod(string mod)
{
// Clear static state if we have switched mods
LobbyInfoChanged = () => {};
@@ -353,17 +342,18 @@ namespace OpenRA
if (orderManager != null)
orderManager.Dispose();
// Discard any invalid mods, set RA as default
var mm = mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray();
if (mm.Length == 0) mm = new[] { "ra" };
Console.WriteLine("Loading mods: {0}", mm.JoinWith(","));
Settings.Game.Mods = mm;
// Fall back to RA if the mod doesn't exist
if (!Mod.AllMods.ContainsKey(mod))
mod = "ra";
Console.WriteLine("Loading mod: {0}", mod);
Settings.Game.Mod = mod;
Sound.StopMusic();
Sound.StopVideo();
Sound.Initialize();
modData = new ModData(mm);
modData = new ModData(mod);
Renderer.InitializeFonts(modData.Manifest);
modData.InitializeLoaders();
@@ -480,8 +470,7 @@ namespace OpenRA
public static void CreateServer(ServerSettings settings)
{
server = new Server.Server(new IPEndPoint(IPAddress.Any, settings.ListenPort),
Settings.Game.Mods, settings, modData);
server = new Server.Server(new IPEndPoint(IPAddress.Any, settings.ListenPort), settings, modData);
}
public static int CreateLocalServer(string map)
@@ -494,8 +483,7 @@ namespace OpenRA
AllowPortForward = false
};
server = new Server.Server(new IPEndPoint(IPAddress.Loopback, 0),
Settings.Game.Mods, settings, modData);
server = new Server.Server(new IPEndPoint(IPAddress.Loopback, 0), settings, modData);
return server.Port;
}
@@ -509,16 +497,19 @@ namespace OpenRA
{
try
{
var mod = CurrentMods.First().Value.Id;
var dirPath = "{1}maps{0}{2}".F(Path.DirectorySeparatorChar, Platform.SupportDir, mod);
if(!Directory.Exists(dirPath))
var mod = Game.modData.Manifest.Mod;
var dirPath = new [] { Platform.SupportDir, "maps", mod.Id }.Aggregate(Path.Combine);
if (!Directory.Exists(dirPath))
Directory.CreateDirectory(dirPath);
var mapPath = "{1}{0}{2}".F(Path.DirectorySeparatorChar, dirPath, mapHash+".oramap");
var mapPath = Path.Combine(dirPath, mapHash+".oramap");
Console.Write("Trying to download map to {0} ... ".F(mapPath));
WebClient webClient = new WebClient();
webClient.DownloadFile(Game.Settings.Game.MapRepository + mapHash, mapPath);
Game.modData.AvailableMaps.Add(mapHash, new Map(mapPath));
Console.WriteLine("done");
return true;
}
catch (WebException e)

View File

@@ -124,7 +124,7 @@ namespace OpenRA.GameRules
public class GameSettings
{
public string[] Mods = { "ra" };
public string Mod = "ra";
public bool ShowShellmap = true;

View File

@@ -50,13 +50,13 @@ namespace OpenRA
return dirsWithMaps.Concat(Directory.GetFiles(dir, "*.oramap"));
}
public ModData(params string[] mods)
public ModData(string mod)
{
Languages = new string[0];
Manifest = new Manifest(mods);
Manifest = new Manifest(mod);
ObjectCreator = new ObjectCreator(Manifest);
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value);
LoadScreen.Init(Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value));
LoadScreen.Init(Manifest, Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value));
LoadScreen.Display();
WidgetLoader = new WidgetLoader(this);
@@ -149,9 +149,7 @@ namespace OpenRA
Dictionary<string, Map> FindMaps()
{
var paths = Manifest.MapFolders.SelectMany(f => FindMapsIn(f));
var ret = new Dictionary<string, Map>();
foreach (var path in paths)
{
try
@@ -177,7 +175,7 @@ namespace OpenRA
public interface ILoadScreen
{
void Init(Dictionary<string, string> info);
void Init(Manifest m, Dictionary<string, string> info);
void Display();
void StartGame();
}

View File

@@ -21,49 +21,47 @@ namespace OpenRA.Network
public readonly int State = 0;
public readonly int Players = 0;
public readonly string Map = null;
public readonly string[] Mods = { };
// Retained name compatibility with the master server
public readonly string Mods = "";
public readonly int TTL = 0;
public Dictionary<string, string> UsefulMods
{
get
{
return Mods
.Where(v => v.Contains('@'))
.ToDictionary(v => v.Split('@')[0], v => v.Split('@')[1]);
}
}
static bool AreVersionsCompatible(string a, string b)
{
if (Game.Settings.Debug.IgnoreVersionMismatch)
return true;
return a == b;
}
public bool CanJoin()
{
//"waiting for players"
// "waiting for players"
if (State != 1)
return false;
// Mods won't match if there are a different number
if (Game.CurrentMods.Count != Mods.Count())
if (!CompatibleVersion())
return false;
// Don't have the map locally
if (!Game.modData.AvailableMaps.ContainsKey(Map))
if (!Game.Settings.Game.AllowDownloading)
return false;
// TODO: We allow joining, then drop on game start if the map isn't available
if (!Game.modData.AvailableMaps.ContainsKey(Map) && !Game.Settings.Game.AllowDownloading)
return false;
return CompatibleVersion();
return true;
}
public bool CompatibleVersion()
{
return UsefulMods.All(m => Game.CurrentMods.ContainsKey(m.Key)
&& AreVersionsCompatible(m.Value, Game.CurrentMods[m.Key].Version));
// Invalid game listing - we require one entry of id@version
var modVersion = Mods.Split('@');
if (modVersion.Length != 2)
return false;
var mod = Game.modData.Manifest.Mod;
// Different mod
// TODO: Allow mod switch when joining server
if (modVersion[0] != mod.Id)
return false;
// Same mod, but different version
if (modVersion[1] != mod.Version && !Game.Settings.Debug.IgnoreVersionMismatch)
return false;
return true;
}
}
}

View File

@@ -16,7 +16,8 @@ namespace OpenRA.Network
{
public class HandshakeRequest
{
public string[] Mods;
public string Mod;
public string Version;
public string Map;
public string Serialize()
@@ -36,7 +37,8 @@ namespace OpenRA.Network
public class HandshakeResponse
{
public string[] Mods;
public string Mod;
public string Version;
public string Password;
[FieldLoader.Ignore] public Session.Client Client;
@@ -44,7 +46,7 @@ namespace OpenRA.Network
{
var data = new List<MiniYamlNode>();
data.Add( new MiniYamlNode( "Handshake", null,
new string[]{ "Mods", "Password" }.Select( p => FieldSaver.SaveField(this, p) ).ToList() ) );
new string[]{ "Mod", "Version", "Password" }.Select( p => FieldSaver.SaveField(this, p) ).ToList() ) );
data.Add(new MiniYamlNode("Client", FieldSaver.Save(Client)));
return data.WriteToString();

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Network
readonly SyncReport syncReport;
readonly FrameData frameData = new FrameData();
public Session LobbyInfo = new Session(Game.Settings.Game.Mods);
public Session LobbyInfo = new Session();
public Session.Client LocalClient { get { return LobbyInfo.ClientWithIndex(Connection.LocalClientId); } }
public World world;

View File

@@ -34,7 +34,8 @@ namespace OpenRA.Network
void StartSavingReplay(byte[] initialContent)
{
var filename = chooseFilename();
var dir = new[] { Platform.SupportDir, "Replays", WidgetUtils.ActiveModId(), WidgetUtils.ActiveModVersion() }.Aggregate(Path.Combine);
var mod = Game.modData.Manifest.Mod;
var dir = new[] { Platform.SupportDir, "Replays", mod.Id, mod.Version }.Aggregate(Path.Combine);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Network
{
try
{
var session = new Session(Game.Settings.Game.Mods);
var session = new Session();
var ys = MiniYaml.FromString(data);
foreach (var y in ys)
@@ -123,10 +123,9 @@ namespace OpenRA.Network
{
public string ServerName;
public string Map;
public string[] Mods = { "ra" }; // mod names
public int OrderLatency = 3; // net tick frames (x 120 = ms)
public int OrderLatency = 3; // net tick frames (x 120 = ms)
public int RandomSeed = 0;
public bool FragileAlliances = false; // Allow diplomatic stance changes after game start.
public bool FragileAlliances = false; // Allow diplomatic stance changes after game start.
public bool AllowCheats = false;
public bool Dedicated;
public string Difficulty;
@@ -140,12 +139,6 @@ namespace OpenRA.Network
public string GameUid;
}
public Session(string[] mods)
{
this.GlobalSettings.Mods = mods.ToArray();
this.GlobalSettings.GameUid = Guid.NewGuid().ToString();
}
public string Serialize()
{
var clientData = new List<MiniYamlNode>();

View File

@@ -178,8 +178,8 @@ namespace OpenRA.Network
{
if (r.Frame == frame)
{
var mod = Game.modData.Manifest.Mod;
Log.Write("sync", "Player: {0} ({1} {2} {3})", Game.Settings.Player.Name, Platform.CurrentPlatform, Environment.OSVersion, Platform.RuntimeVersion);
var mod = Game.CurrentMods.First().Value;
Log.Write("sync", "Game ID: {0} (Mod: {1} at Version {2})", orderManager.LobbyInfo.GlobalSettings.GameUid, mod.Title, mod.Version);
Log.Write("sync", "Sync for net frame {0} -------------", r.Frame);
Log.Write("sync", "SharedRandom: {0} (#{1})", r.SyncedRandom, r.TotalCount);

View File

@@ -119,9 +119,14 @@ namespace OpenRA.Network
case "HandshakeRequest":
{
var request = HandshakeRequest.Deserialize(order.TargetString);
var localMods = orderManager.LobbyInfo.GlobalSettings.Mods.Select(m => "{0}@{1}".F(m, Mod.AllMods[m].Version)).ToArray();
// TODO: Switch to the server's mod if we have it
// Otherwise send the handshake with our current settings and let the server reject us
var mod = Game.modData.Manifest.Mod;
// Check that the map exists on the client
// TODO: This will behave badly if joining a server with a different mod
// This needs to occur *after* joining the server
if (!Game.modData.AvailableMaps.ContainsKey(request.Map))
{
if (Game.Settings.Game.AllowDownloading)
@@ -144,7 +149,8 @@ namespace OpenRA.Network
var response = new HandshakeResponse()
{
Client = info,
Mods = localMods,
Mod = mod.Id,
Version = mod.Version,
Password = orderManager.Password
};

View File

@@ -95,7 +95,7 @@ namespace OpenRA.Server
t.GameEnded(this);
}
public Server(IPEndPoint endpoint, string[] mods, ServerSettings settings, ModData modData)
public Server(IPEndPoint endpoint, ServerSettings settings, ModData modData)
{
Log.AddChannel("server", "server.log");
@@ -117,7 +117,7 @@ namespace OpenRA.Server
foreach (var trait in modData.Manifest.ServerTraits)
serverTraits.Add(modData.ObjectCreator.CreateObject<ServerTrait>(trait));
LobbyInfo = new Session(mods);
LobbyInfo = new Session();
LobbyInfo.GlobalSettings.RandomSeed = randomSeed;
LobbyInfo.GlobalSettings.Map = settings.Map;
LobbyInfo.GlobalSettings.ServerName = settings.Name;
@@ -127,10 +127,7 @@ namespace OpenRA.Server
foreach (var t in serverTraits.WithInterface<INotifyServerStart>())
t.ServerStarted(this);
Log.Write("server", "Initial mods: ");
foreach (var m in LobbyInfo.GlobalSettings.Mods)
Log.Write("server", "- {0}", m);
Log.Write("server", "Initial mod: {0}", ModData.Manifest.Mod.Id);
Log.Write("server", "Initial map: {0}", LobbyInfo.GlobalSettings.Map);
new Thread(_ =>
@@ -226,9 +223,11 @@ namespace OpenRA.Server
// Dispatch a handshake order
var request = new HandshakeRequest()
{
Map = LobbyInfo.GlobalSettings.Map,
Mods = LobbyInfo.GlobalSettings.Mods.Select(m => "{0}@{1}".F(m, Mod.AllMods[m].Version)).ToArray()
Mod = ModData.Manifest.Mod.Id,
Version = ModData.Manifest.Mod.Version,
Map = LobbyInfo.GlobalSettings.Map
};
DispatchOrdersToClient(newConn, 0, 0, new ServerOrder("HandshakeRequest", request.Serialize()).Serialize());
}
catch (Exception e)
@@ -282,13 +281,7 @@ namespace OpenRA.Server
else
client.Color = HSLColor.FromRGB(255, 255, 255);
// Check that the client has compatible mods
var mods = handshake.Mods;
var validMod = mods.All(m => m.Contains('@')) && // valid format
mods.Count() == Game.CurrentMods.Count() && // same number
mods.Select(m => Pair.New(m.Split('@')[0], m.Split('@')[1])).All(kv => Game.CurrentMods.ContainsKey(kv.First));
if (!validMod)
if (ModData.Manifest.Mod.Id != handshake.Mod)
{
Log.Write("server", "Rejected connection from {0}; mods do not match.",
newConn.socket.RemoteEndPoint);
@@ -298,10 +291,7 @@ namespace OpenRA.Server
return;
}
var validVersion = mods.Select(m => Pair.New(m.Split('@')[0], m.Split('@')[1])).All(
kv => kv.Second == Game.CurrentMods[kv.First].Version);
if (!validVersion && !LobbyInfo.GlobalSettings.AllowVersionMismatch)
if (ModData.Manifest.Mod.Version != handshake.Version && !LobbyInfo.GlobalSettings.AllowVersionMismatch)
{
Log.Write("server", "Rejected connection from {0}; Not running the same version.",
newConn.socket.RemoteEndPoint);
@@ -338,13 +328,14 @@ namespace OpenRA.Server
// Send initial ping
SendOrderTo(newConn, "Ping", Environment.TickCount.ToString());
if (File.Exists("{0}motd_{1}.txt".F(Platform.SupportDir, LobbyInfo.GlobalSettings.Mods[0])))
var motdPath = Path.Combine(Platform.SupportDir, "motd_{0}.txt".F(ModData.Manifest.Mod.Id));
if (File.Exists(motdPath))
{
var motd = File.ReadAllText("{0}motd_{1}.txt".F(Platform.SupportDir, LobbyInfo.GlobalSettings.Mods[0]));
var motd = System.IO.File.ReadAllText(motdPath);
SendOrderTo(newConn, "Message", motd);
}
if (mods.Any(m => m.Contains("{DEV_VERSION}")))
if (handshake.Mod == "{DEV_VERSION}")
SendMessage("{0} is running an unversioned development build, ".F(client.Name) +
"and may desynchronize the game state if they have incompatible rules.");

View File

@@ -47,9 +47,9 @@ namespace OpenRA
{
Log.AddChannel("exception", "exception.log");
if (Game.CurrentMods != null)
if (Game.modData != null)
{
var mod = Game.CurrentMods.First().Value;
var mod = Game.modData.Manifest.Mod;
Log.Write("exception", "{0} Mod at Version {1}", mod.Title, mod.Version);
}

View File

@@ -225,24 +225,6 @@ namespace OpenRA.Widgets
public static Action Once( Action a ) { return () => { if (a != null) { a(); a = null; } }; }
public static string ActiveModVersion()
{
var mod = Game.modData.Manifest.Mods[0];
return Mod.AllMods[mod].Version;
}
public static string ActiveModTitle()
{
var mod = Game.modData.Manifest.Mods[0];
return Mod.AllMods[mod].Title;
}
public static string ActiveModId()
{
var mod = Game.modData.Manifest.Mods[0];
return Mod.AllMods[mod].Id;
}
public static string ChooseInitialMap(string map)
{
var availableMaps = Game.modData.AvailableMaps;

View File

@@ -70,9 +70,7 @@ namespace OpenRA.Irc
var command = split[0];
if (command.EqualsIC("VERSION"))
{
var mod = Game.CurrentMods.Values.FirstOrDefault();
if (mod == null)
return;
var mod = Game.modData.Manifest.Mod;
Instance.CtcpRespond(l.Prefix.Nickname, command, "{0}: {1}".F(mod.Title, mod.Version));
}
};

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Lint
try
{
var options = args.Where(a => a.StartsWith("-"));
var mods = args.Where(a => !options.Contains(a)).ToArray();
var mod = args.Where(a => !options.Contains(a)).First();
var verbose = options.Contains("-v") || options.Contains("--verbose");
@@ -44,7 +44,7 @@ namespace OpenRA.Lint
FieldLoader.UnknownFieldAction = (s, f) => EmitError("FieldLoader: Missing field `{0}` on `{1}`".F(s, f.Name));
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
Game.modData = new ModData(mods);
Game.modData = new ModData(mod);
Rules.LoadRules(Game.modData.Manifest, new Map());
foreach (var customPassType in Game.modData.ObjectCreator

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.Cnc
Renderer r;
NullInputHandler nih = new NullInputHandler();
public void Init(Dictionary<string, string> info)
public void Init(Manifest m, Dictionary<string, string> info)
{
loadInfo = info;
@@ -63,6 +63,8 @@ namespace OpenRA.Mods.Cnc
brightBlock = new Sprite(s, new Rectangle(320, 0, 16, 35), TextureChannel.Alpha);
dimBlock = new Sprite(s, new Rectangle(336, 0, 16, 35), TextureChannel.Alpha);
versionText = m.Mod.Version;
}
bool setup;
@@ -93,7 +95,6 @@ namespace OpenRA.Mods.Cnc
loadingPos = new float2((bounds.Width - loadingFont.Measure(loadingText).X) / 2, barY);
versionFont = r.Fonts["Regular"];
versionText = WidgetUtils.ActiveModVersion();
var versionSize = versionFont.Measure(versionText);
versionPos = new float2(bounds.Width - 107 - versionSize.X / 2, 115 - versionSize.Y / 2);

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
var mpe = world.WorldActor.Trait<CncMenuPaletteEffect>();
mpe.Fade(CncMenuPaletteEffect.EffectType.Desaturated);
menu.Get<LabelWidget>("VERSION_LABEL").GetText = WidgetUtils.ActiveModVersion;
menu.Get<LabelWidget>("VERSION_LABEL").Text = Game.modData.Manifest.Mod.Version;
bool hideButtons = false;
menu.Get("MENU_BUTTONS").IsVisible = () => !hideButtons;

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
{
try
{
var path = new string[] { Platform.SupportDir, "Content", WidgetUtils.ActiveModId() }.Aggregate(Path.Combine);
var path = new string[] { Platform.SupportDir, "Content", Game.modData.Manifest.Mod.Id }.Aggregate(Path.Combine);
FileSystem.Mount(Path.Combine(path, "scores.mix"));
FileSystem.Mount(Path.Combine(path, "transit.mix"));

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
.Fade(CncMenuPaletteEffect.EffectType.Desaturated);
rootMenu = widget.Get("MENU_BACKGROUND");
rootMenu.Get<LabelWidget>("VERSION_LABEL").GetText = WidgetUtils.ActiveModVersion;
rootMenu.Get<LabelWidget>("VERSION_LABEL").Text = Game.modData.Manifest.Mod.Version;
// Menu buttons
var mainMenu = widget.Get("MAIN_MENU");

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA
Sprite stripe, logo;
string[] messages;
public void Init(Dictionary<string, string> info)
public void Init(Manifest m, Dictionary<string, string> info)
{
this.info = info;

View File

@@ -9,13 +9,14 @@
#endregion
using System.Collections.Generic;
using OpenRA.FileFormats;
using OpenRA.Widgets;
namespace OpenRA.Mods.RA
{
public class NullLoadScreen : ILoadScreen
{
public void Init(Dictionary<string, string> info) {}
public void Init(Manifest m, Dictionary<string, string> info) {}
public void Display()
{

View File

@@ -50,6 +50,7 @@ namespace OpenRA.Mods.RA.Server
lastPing = Environment.TickCount;
isBusy = true;
var mod = server.ModData.Manifest.Mod;
Action a = () =>
{
try
@@ -60,14 +61,13 @@ namespace OpenRA.Mods.RA.Server
using (var wc = new WebClient())
{
wc.Proxy = null;
wc.DownloadData(
wc.DownloadData(
server.Settings.MasterServer + url.F(
server.Settings.ExternalPort, Uri.EscapeUriString(server.Settings.Name),
(int)server.State,
server.LobbyInfo.Clients.Where(c1 => c1.Bot == null).Count(),
server.LobbyInfo.Clients.Where(c1 => c1.Bot != null).Count(),
Game.CurrentMods.Select(f => "{0}@{1}".F(f.Key, f.Value.Version)).JoinWith(","),
"{0}@{1}".F(mod.Id, mod.Version),
server.LobbyInfo.GlobalSettings.Map,
server.Map.PlayerCount));

View File

@@ -99,14 +99,16 @@ namespace OpenRA.Mods.RA.Widgets.Logic
template = panel.Get<ScrollItemWidget>("ASSET_TEMPLATE");
PopulateAssetList();
var palette = (WidgetUtils.ActiveModId() == "d2k") ? "d2k.pal" : "egopal.pal";
// TODO: Horrible hack
var modID = Game.modData.Manifest.Mod.Id;
var palette = (modID == "d2k") ? "d2k.pal" : "egopal.pal";
panel.Get<ButtonWidget>("EXPORT_BUTTON").OnClick = () =>
{
var ExtractGameFiles = new string[][]
{
new string[] {"--extract", WidgetUtils.ActiveModId(), palette, "--userdir"},
new string[] {"--extract", WidgetUtils.ActiveModId(), "{0}.shp".F(spriteImage.Image), "--userdir"},
new string[] {"--extract", modID, palette, "--userdir"},
new string[] {"--extract", modID, "{0}.shp".F(spriteImage.Image), "--userdir"},
};
var ExportToPng = new string[][]
@@ -131,11 +133,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var ExtractGameFilesList = new List<string[]>();
var ExportToPngList = new List<string[]>();
ExtractGameFilesList.Add(new string[] { "--extract", WidgetUtils.ActiveModId(), palette, "--userdir"} );
ExtractGameFilesList.Add(new string[] { "--extract", modID, palette, "--userdir"} );
foreach (var shp in AvailableShps)
{
ExtractGameFilesList.Add(new string[] { "--extract", WidgetUtils.ActiveModId(), shp, "--userdir" } );
ExtractGameFilesList.Add(new string[] { "--extract", modID, shp, "--userdir" } );
ExportToPngList.Add(new string[] { "--png", Platform.SupportDir+shp, Platform.SupportDir+palette } );
Console.WriteLine(Platform.SupportDir+shp);
}
@@ -148,7 +150,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
{ "ExtractGameFiles", ExtractGameFiles },
{ "ExportToPng", ExportToPng },
{ "ImportFromPng", ImportFromPng}
{ "ImportFromPng", ImportFromPng }
};
Ui.OpenWindow("CONVERT_ASSETS_PANEL", args);

View File

@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
// Save the package to a temp file
var file = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
var dest = new string[] { Platform.SupportDir, "Content", Game.modData.Manifest.Mods[0] }.Aggregate(Path.Combine);
var dest = new string[] { Platform.SupportDir, "Content", Game.modData.Manifest.Mod.Id }.Aggregate(Path.Combine);
Action<DownloadProgressChangedEventArgs> onDownloadProgress = i =>
{

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var versionLabel = Ui.Root.GetOrNull<LabelWidget>("VERSION_LABEL");
if (versionLabel != null)
versionLabel.GetText = WidgetUtils.ActiveModVersion;
versionLabel.Text = Game.modData.Manifest.Mod.Version;
widget.Get<ButtonWidget>("MAINMENU_BUTTON_JOIN").OnClick = () => OpenGamePanel("JOINSERVER_BG");
widget.Get<ButtonWidget>("MAINMENU_BUTTON_CREATE").OnClick = () => OpenGamePanel("CREATESERVER_BG");

View File

@@ -26,10 +26,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var modList = panel.Get<ScrollPanelWidget>("MOD_LIST");
var loadButton = panel.Get<ButtonWidget>("LOAD_BUTTON");
loadButton.OnClick = () => LoadMod(currentMod.Id, onSwitch);
loadButton.IsDisabled = () => currentMod.Id == Game.CurrentMods.Keys.First();
loadButton.IsDisabled = () => currentMod.Id == Game.modData.Manifest.Mod.Id;
panel.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
currentMod = Mod.AllMods[Game.modData.Manifest.Mods[0]];
currentMod = Game.modData.Manifest.Mod;
// Mod list
var modTemplate = modList.Get<ScrollItemWidget>("MOD_TEMPLATE");
@@ -47,13 +47,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
void LoadMod(string mod, Action onSwitch)
{
var mods = Mod.AllMods[mod].WithPrerequisites();
Game.RunAfterTick(() =>
{
Ui.CloseWindow();
onSwitch();
Game.InitializeWithMods(mods);
Game.InitializeWithMod(mod);
});
}
}

View File

@@ -28,11 +28,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
panel.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
var rl = panel.Get<ScrollPanelWidget>("REPLAY_LIST");
var dir = new[] { Platform.SupportDir, "Replays", WidgetUtils.ActiveModId(), WidgetUtils.ActiveModVersion() }.Aggregate(Path.Combine);
var template = panel.Get<ScrollItemWidget>("REPLAY_TEMPLATE");
var mod = Game.modData.Manifest.Mod;
var dir = new[] { Platform.SupportDir, "Replays", mod.Id, mod.Version }.Aggregate(Path.Combine);
rl.RemoveChildren();
if (Directory.Exists(dir))
{

View File

@@ -149,17 +149,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
return (game == null) ? null : Game.modData.FindMapByUid(game.Map);
}
static string GenerateModLabel(KeyValuePair<string,string> mod)
public static string GenerateModLabel(GameServer s)
{
if (Mod.AllMods.ContainsKey(mod.Key))
return "{0} ({1})".F(Mod.AllMods[mod.Key].Title, mod.Value);
Mod mod;
var modVersion = s.Mods.Split('@');
return "Unknown Mod: {0}".F(mod.Key);
}
if (modVersion.Length == 2 && Mod.AllMods.TryGetValue(modVersion[0], out mod))
return "{0} ({1})".F(mod.Title, modVersion[1]);
public static string GenerateModsLabel(GameServer s)
{
return s.UsefulMods.Select(m => GenerateModLabel(m)).JoinWith("\n");
return "Unknown mod: {0}".F(s.Mods);
}
bool Filtered(GameServer game)
@@ -237,7 +235,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
ip.GetText = () => game.Address;
var version = item.Get<LabelWidget>("VERSION");
version.GetText = () => GenerateModsLabel(game);
version.GetText = () => GenerateModLabel(game);
version.IsVisible = () => !game.CompatibleVersion();
var location = item.Get<LabelWidget>("LOCATION");

View File

@@ -176,12 +176,12 @@ namespace OpenRA.Utility
public static void ConvertTmpToPng(string[] args)
{
var mods = args[1].Split(',');
var mod = args[1];
var theater = args[2];
var templateNames = args.Skip(3);
var shadowIndex = new int[] { 3, 4 };
var manifest = new Manifest(mods);
var manifest = new Manifest(mod);
FileSystem.LoadFromManifest(manifest);
var tileset = manifest.TileSets.Select(a => new TileSet(a))
@@ -225,10 +225,10 @@ namespace OpenRA.Utility
public static void ExtractFiles(string[] args)
{
var mods = args[1].Split(',');
var mod = args[1];
var files = args.Skip(2);
var manifest = new Manifest(mods);
var manifest = new Manifest(mod);
FileSystem.LoadFromManifest(manifest);
foreach (var f in files)

View File

@@ -9,7 +9,7 @@ AdvertiseOnline="False"
Map="ba403f6bcb4cae934335b78be42f714992b3a71a"
while true; do
mono --debug OpenRA.Game.exe Game.Mods=$Mod Server.Dedicated=$Dedicated Server.DedicatedLoop=$DedicatedLoop \
mono --debug OpenRA.Game.exe Game.Mod=$Mod Server.Dedicated=$Dedicated Server.DedicatedLoop=$DedicatedLoop \
Server.Name=$Name Server.ListenPort=$ListenPort Server.ExternalPort=$ExternalPort \
Server.AdvertiseOnline=$AdvertiseOnline Server.Map=$Map
done