Remove runtime mod merging. Closes #3421.
This commit is contained in:
@@ -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:
|
||||
|
||||
4
INSTALL
4
INSTALL
@@ -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
|
||||
-------------
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace OpenRA.GameRules
|
||||
|
||||
public class GameSettings
|
||||
{
|
||||
public string[] Mods = { "ra" };
|
||||
public string Mod = "ra";
|
||||
|
||||
public bool ShowShellmap = true;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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.");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"));
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 =>
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user