Skip to content

Commit

Permalink
Remove runtime mod merging. Closes #3421.
Browse files Browse the repository at this point in the history
  • Loading branch information
pchote committed Nov 14, 2013
1 parent 4d893cb commit 6d6d1e2
Show file tree
Hide file tree
Showing 35 changed files with 143 additions and 186 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
Expand Up @@ -76,11 +76,13 @@ NEW:
Added modifier support to hotkeys. Added modifier support to hotkeys.
Fixed a desync related to projectile contrails. Fixed a desync related to projectile contrails.
Fixed corrupted replays (which would immediately desync). Fixed corrupted replays (which would immediately desync).
Removed runtime mod merging.
Build system and packages: Build system and packages:
Added GeoIP to Makefile so it is installed properly. Added GeoIP to Makefile so it is installed properly.
Added desktop shortcut creation support to the Makefile and Windows installer. Added desktop shortcut creation support to the Makefile and Windows installer.
COPYING and CHANGELOG are now shipped on all platforms. COPYING and CHANGELOG are now shipped on all platforms.
Fixed 'make docs' crashing when the game assets are not installed. Fixed 'make docs' crashing when the game assets are not installed.
Renamed Game.Mods launch argument to Game.Mod.
Mod / Custom map compatibility: Mod / Custom map compatibility:
Mods can now include traits from TD and D2K in RA. Mods can now include traits from TD and D2K in RA.
New sections MapFolders and Translations added to mod.yaml. New sections MapFolders and Translations added to mod.yaml.
Expand All @@ -99,6 +101,7 @@ NEW:
Removed traits from World: SpatialBins. Removed traits from World: SpatialBins.
Added InvalidTargets property to weapons. Added InvalidTargets property to weapons.
Added modifier support for build palette hotkeys. 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: 20130915:
All mods: All mods:
Expand Down
4 changes: 2 additions & 2 deletions INSTALL
Expand Up @@ -29,8 +29,8 @@ or build it from the command-line with MSBuild.
Copy both the native DLLs from .\packaging\windows Copy both the native DLLs from .\packaging\windows
and the CLI images from .\thirdparty to the main folder. and the CLI images from .\thirdparty to the main folder.


Run the game with `OpenRA.Game.exe Game.Mods=ra` for Red Alert Run the game with `OpenRA.Game.exe Game.Mod=ra` for Red Alert
or `OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer or `OpenRA.Game.exe Game.Mod=cnc` for Command & Conquer


Debian/Ubuntu Debian/Ubuntu
------------- -------------
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Editor/Form1.cs
Expand Up @@ -50,8 +50,8 @@ public Form1(string[] args)
FileSystem.LoadFromManifest(Game.modData.Manifest); FileSystem.LoadFromManifest(Game.modData.Manifest);
Rules.LoadRules(Game.modData.Manifest, new Map()); Rules.LoadRules(Game.modData.Manifest, new Map());
var mod = Game.modData.Manifest.Mods[0]; var mod = Game.modData.Manifest.Mod;
Text = "{0} Mod Version: {1} - OpenRA Editor".F(Mod.AllMods[mod].Title, Mod.AllMods[mod].Version); Text = "{0} Mod Version: {1} - OpenRA Editor".F(mod.Title, mod.Version);
loadedMapName = null; loadedMapName = null;
}; };
Expand Down
14 changes: 8 additions & 6 deletions OpenRA.FileFormats/Manifest.cs
Expand Up @@ -18,8 +18,9 @@ namespace OpenRA.FileFormats


public class Manifest public class Manifest
{ {
public readonly Mod Mod;
public readonly string[] public readonly string[]
Mods, Folders, MapFolders, Rules, ServerTraits, Folders, MapFolders, Rules, ServerTraits,
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout, Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
Weapons, Voices, Notifications, Music, Movies, Translations, TileSets, Weapons, Voices, Notifications, Music, Movies, Translations, TileSets,
ChromeMetrics, PackageContents; ChromeMetrics, PackageContents;
Expand All @@ -30,12 +31,13 @@ public class Manifest
public readonly Dictionary<string, Pair<string,int>> Fonts; public readonly Dictionary<string, Pair<string,int>> Fonts;
public readonly int TileSize = 24; public readonly int TileSize = 24;


public Manifest(string[] mods) public Manifest(string mod)
{ {
Mods = mods; var path = new [] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
var yaml = new MiniYaml(null, mods var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
.Select(m => MiniYaml.FromFile("mods{0}{1}{0}mod.yaml".F(Path.DirectorySeparatorChar, m)))
.Aggregate(MiniYaml.MergeLiberal)).NodesDict; Mod = FieldLoader.Load<Mod>(yaml["Metadata"]);
Mod.Id = mod;


// TODO: Use fieldloader // TODO: Use fieldloader
Folders = YamlList(yaml, "Folders"); Folders = YamlList(yaml, "Folders");
Expand Down
8 changes: 0 additions & 8 deletions OpenRA.FileFormats/Mod.cs
Expand Up @@ -21,7 +21,6 @@ public class Mod
public string Description; public string Description;
public string Version; public string Version;
public string Author; public string Author;
public string Requires;


public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray()); public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());


Expand All @@ -45,12 +44,5 @@ public class Mod
} }
return ret; return ret;
} }

public string[] WithPrerequisites()
{
return Id.Iterate(m => AllMods[m].Requires)
.TakeWhile(m => m != null)
.ToArray();
}
} }
} }
47 changes: 19 additions & 28 deletions OpenRA.Game/Game.cs
Expand Up @@ -255,18 +255,6 @@ public static bool IsHost
} }
} }


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; static Modifiers modifiers;
public static Modifiers GetModifierKeys() { return modifiers; } public static Modifiers GetModifierKeys() { return modifiers; }
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; } internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
Expand Down Expand Up @@ -328,7 +316,8 @@ internal static void Initialize(Arguments args)
Console.WriteLine("Available mods:"); Console.WriteLine("Available mods:");
foreach(var mod in Mod.AllMods) foreach(var mod in Mod.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); 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) if (Settings.Server.DiscoverNatDevices)
{ {
Expand All @@ -338,7 +327,7 @@ internal static void Initialize(Arguments args)
} }
} }


public static void InitializeWithMods(string[] mods) public static void InitializeWithMod(string mod)
{ {
// Clear static state if we have switched mods // Clear static state if we have switched mods
LobbyInfoChanged = () => {}; LobbyInfoChanged = () => {};
Expand All @@ -353,17 +342,18 @@ public static void InitializeWithMods(string[] mods)
if (orderManager != null) if (orderManager != null)
orderManager.Dispose(); orderManager.Dispose();


// Discard any invalid mods, set RA as default // Fall back to RA if the mod doesn't exist
var mm = mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray(); if (!Mod.AllMods.ContainsKey(mod))
if (mm.Length == 0) mm = new[] { "ra" }; mod = "ra";
Console.WriteLine("Loading mods: {0}", mm.JoinWith(","));
Settings.Game.Mods = mm; Console.WriteLine("Loading mod: {0}", mod);
Settings.Game.Mod = mod;


Sound.StopMusic(); Sound.StopMusic();
Sound.StopVideo(); Sound.StopVideo();
Sound.Initialize(); Sound.Initialize();


modData = new ModData(mm); modData = new ModData(mod);
Renderer.InitializeFonts(modData.Manifest); Renderer.InitializeFonts(modData.Manifest);
modData.InitializeLoaders(); modData.InitializeLoaders();


Expand Down Expand Up @@ -480,8 +470,7 @@ public static T CreateObject<T>( string name )


public static void CreateServer(ServerSettings settings) public static void CreateServer(ServerSettings settings)
{ {
server = new Server.Server(new IPEndPoint(IPAddress.Any, settings.ListenPort), server = new Server.Server(new IPEndPoint(IPAddress.Any, settings.ListenPort), settings, modData);
Settings.Game.Mods, settings, modData);
} }


public static int CreateLocalServer(string map) public static int CreateLocalServer(string map)
Expand All @@ -494,8 +483,7 @@ public static int CreateLocalServer(string map)
AllowPortForward = false AllowPortForward = false
}; };


server = new Server.Server(new IPEndPoint(IPAddress.Loopback, 0), server = new Server.Server(new IPEndPoint(IPAddress.Loopback, 0), settings, modData);
Settings.Game.Mods, settings, modData);


return server.Port; return server.Port;
} }
Expand All @@ -509,16 +497,19 @@ public static bool DownloadMap(string mapHash)
{ {
try try
{ {
var mod = CurrentMods.First().Value.Id; var mod = Game.modData.Manifest.Mod;
var dirPath = "{1}maps{0}{2}".F(Path.DirectorySeparatorChar, Platform.SupportDir, mod); var dirPath = new [] { Platform.SupportDir, "maps", mod.Id }.Aggregate(Path.Combine);
if(!Directory.Exists(dirPath)) if (!Directory.Exists(dirPath))
Directory.CreateDirectory(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)); Console.Write("Trying to download map to {0} ... ".F(mapPath));

WebClient webClient = new WebClient(); WebClient webClient = new WebClient();
webClient.DownloadFile(Game.Settings.Game.MapRepository + mapHash, mapPath); webClient.DownloadFile(Game.Settings.Game.MapRepository + mapHash, mapPath);
Game.modData.AvailableMaps.Add(mapHash, new Map(mapPath)); Game.modData.AvailableMaps.Add(mapHash, new Map(mapPath));
Console.WriteLine("done"); Console.WriteLine("done");

return true; return true;
} }
catch (WebException e) catch (WebException e)
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Game/GameRules/Settings.cs
Expand Up @@ -124,7 +124,7 @@ public class PlayerSettings


public class GameSettings public class GameSettings
{ {
public string[] Mods = { "ra" }; public string Mod = "ra";


public bool ShowShellmap = true; public bool ShowShellmap = true;


Expand Down
10 changes: 4 additions & 6 deletions OpenRA.Game/ModData.cs
Expand Up @@ -50,13 +50,13 @@ public static IEnumerable<string> FindMapsIn(string dir)
return dirsWithMaps.Concat(Directory.GetFiles(dir, "*.oramap")); return dirsWithMaps.Concat(Directory.GetFiles(dir, "*.oramap"));
} }


public ModData(params string[] mods) public ModData(string mod)
{ {
Languages = new string[0]; Languages = new string[0];
Manifest = new Manifest(mods); Manifest = new Manifest(mod);
ObjectCreator = new ObjectCreator(Manifest); ObjectCreator = new ObjectCreator(Manifest);
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value); 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(); LoadScreen.Display();
WidgetLoader = new WidgetLoader(this); WidgetLoader = new WidgetLoader(this);


Expand Down Expand Up @@ -149,9 +149,7 @@ public Map PrepareMap(string uid)
Dictionary<string, Map> FindMaps() Dictionary<string, Map> FindMaps()
{ {
var paths = Manifest.MapFolders.SelectMany(f => FindMapsIn(f)); var paths = Manifest.MapFolders.SelectMany(f => FindMapsIn(f));

var ret = new Dictionary<string, Map>(); var ret = new Dictionary<string, Map>();

foreach (var path in paths) foreach (var path in paths)
{ {
try try
Expand All @@ -177,7 +175,7 @@ public Map FindMapByUid(string uid)


public interface ILoadScreen public interface ILoadScreen
{ {
void Init(Dictionary<string, string> info); void Init(Manifest m, Dictionary<string, string> info);
void Display(); void Display();
void StartGame(); void StartGame();
} }
Expand Down
54 changes: 26 additions & 28 deletions OpenRA.Game/Network/GameServer.cs
Expand Up @@ -21,49 +21,47 @@ public class GameServer
public readonly int State = 0; public readonly int State = 0;
public readonly int Players = 0; public readonly int Players = 0;
public readonly string Map = null; public readonly string Map = null;
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) // Retained name compatibility with the master server
{ public readonly string Mods = "";
if (Game.Settings.Debug.IgnoreVersionMismatch) public readonly int TTL = 0;
return true;

return a == b;
}


public bool CanJoin() public bool CanJoin()
{ {
//"waiting for players" // "waiting for players"
if (State != 1) if (State != 1)
return false; return false;


// Mods won't match if there are a different number if (!CompatibleVersion())
if (Game.CurrentMods.Count != Mods.Count())
return false; return false;


// Don't have the map locally // Don't have the map locally
if (!Game.modData.AvailableMaps.ContainsKey(Map)) // TODO: We allow joining, then drop on game start if the map isn't available
if (!Game.Settings.Game.AllowDownloading) if (!Game.modData.AvailableMaps.ContainsKey(Map) && !Game.Settings.Game.AllowDownloading)
return false; return false;


return CompatibleVersion(); return true;
} }


public bool CompatibleVersion() public bool CompatibleVersion()
{ {
return UsefulMods.All(m => Game.CurrentMods.ContainsKey(m.Key) // Invalid game listing - we require one entry of id@version
&& AreVersionsCompatible(m.Value, Game.CurrentMods[m.Key].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;
} }
} }
} }
8 changes: 5 additions & 3 deletions OpenRA.Game/Network/Handshake.cs
Expand Up @@ -16,7 +16,8 @@ namespace OpenRA.Network
{ {
public class HandshakeRequest public class HandshakeRequest
{ {
public string[] Mods; public string Mod;
public string Version;
public string Map; public string Map;


public string Serialize() public string Serialize()
Expand All @@ -36,15 +37,16 @@ public static HandshakeRequest Deserialize(string data)


public class HandshakeResponse public class HandshakeResponse
{ {
public string[] Mods; public string Mod;
public string Version;
public string Password; public string Password;
[FieldLoader.Ignore] public Session.Client Client; [FieldLoader.Ignore] public Session.Client Client;


public string Serialize() public string Serialize()
{ {
var data = new List<MiniYamlNode>(); var data = new List<MiniYamlNode>();
data.Add( new MiniYamlNode( "Handshake", null, 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))); data.Add(new MiniYamlNode("Client", FieldSaver.Save(Client)));


return data.WriteToString(); return data.WriteToString();
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Game/Network/OrderManager.cs
Expand Up @@ -20,7 +20,7 @@ public class OrderManager : IDisposable
readonly SyncReport syncReport; readonly SyncReport syncReport;
readonly FrameData frameData = new FrameData(); 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 Session.Client LocalClient { get { return LobbyInfo.ClientWithIndex(Connection.LocalClientId); } }
public World world; public World world;


Expand Down
3 changes: 2 additions & 1 deletion OpenRA.Game/Network/ReplayRecorderConnection.cs
Expand Up @@ -34,7 +34,8 @@ public ReplayRecorderConnection(IConnection inner, Func<string> chooseFilename)
void StartSavingReplay(byte[] initialContent) void StartSavingReplay(byte[] initialContent)
{ {
var filename = chooseFilename(); 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)) if (!Directory.Exists(dir))
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
Expand Down

0 comments on commit 6d6d1e2

Please sign in to comment.