From 486fa9a978f44356e9af6fed9d92c7a789dfde97 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 31 Dec 2010 13:20:32 +1300 Subject: [PATCH] Handshake mod versions and map. Bump the protocol version. --- OpenRA.Game/Network/Handshake.cs | 20 ++++++++++++ OpenRA.Game/Network/UnitOrders.cs | 46 +++++++++++++++++++++------ OpenRA.Game/Server/ProtocolVersion.cs | 2 +- OpenRA.Game/Server/Server.cs | 7 +++- 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/OpenRA.Game/Network/Handshake.cs b/OpenRA.Game/Network/Handshake.cs index 17dfa80def..a6e4b423f8 100644 --- a/OpenRA.Game/Network/Handshake.cs +++ b/OpenRA.Game/Network/Handshake.cs @@ -15,6 +15,26 @@ using OpenRA.FileFormats; namespace OpenRA.Network { + public class HandshakeRequest + { + [FieldLoader.Load] public string[] Mods; + [FieldLoader.Load] public string Map; + + public string Serialize() + { + var data = new List(); + data.Add(new MiniYamlNode("Handshake", FieldSaver.Save(this))); + return data.WriteToString(); + } + + public static HandshakeRequest Deserialize(string data) + { + var handshake = new HandshakeRequest(); + FieldLoader.Load(handshake, MiniYaml.FromString(data).First().Value); + return handshake; + } + } + public class HandshakeResponse { [FieldLoader.Load] public string[] Mods; diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index 4e646b20c7..ba92e895c5 100755 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -12,6 +12,7 @@ using System.Drawing; using System.Linq; using OpenRA.Traits; using System; +using OpenRA.FileFormats; namespace OpenRA.Network { @@ -100,18 +101,43 @@ namespace OpenRA.Network case "HandshakeRequest": { - // Check valid mods/versions - var serverInfo = Session.Deserialize(order.TargetString); - var serverMods = serverInfo.GlobalSettings.Mods; - var localMods = orderManager.LobbyInfo.GlobalSettings.Mods; + var request = HandshakeRequest.Deserialize(order.TargetString); - // TODO: Check that the map exists on the client + // Check valid mods/versions + var serverMods = request.Mods; + var localMods = orderManager.LobbyInfo.GlobalSettings.Mods; + + bool valid = true; + if (localMods.Length != serverMods.Length) + valid = false; + else + foreach (var m in serverMods) + { + var parts = m.Split('@'); + if (!localMods.Contains(parts[0])) + { + valid = false; + break; + } + if (parts[1] == "{DEV_VERSION}" || Mod.AllMods[parts[0]].Version == "{DEV_VERSION}") + continue; + + if (parts[1] != Mod.AllMods[parts[0]].Version) + { + valid = false; + break; + } + } + + if (!valid) + throw new InvalidOperationException("Mod/Version mismatch. Client: `{0}`, Server: `{1}`".F( + string.Join(",",localMods.Select(m => "{0}@{1}".F(m, Mod.AllMods[m].Version)).ToArray()), + string.Join(",",serverMods))); + + // Check that the map exists on the client + if (!Game.modData.AvailableMaps.ContainsKey(request.Map)) + throw new InvalidOperationException("Missing map {0}".F(request.Map)); - // Todo: Display a friendly dialog - if (serverMods.SymmetricDifference(localMods).Count() > 0) - throw new InvalidOperationException("Version mismatch. Client: `{0}`, Server: `{1}`" - .F(string.Join(",",localMods), string.Join(",",serverMods))); - var info = new Session.Client() { Name = Game.Settings.Player.Name, diff --git a/OpenRA.Game/Server/ProtocolVersion.cs b/OpenRA.Game/Server/ProtocolVersion.cs index b187d4ddfb..d7c2ef246c 100644 --- a/OpenRA.Game/Server/ProtocolVersion.cs +++ b/OpenRA.Game/Server/ProtocolVersion.cs @@ -13,6 +13,6 @@ namespace OpenRA.Server public static class ProtocolVersion { // you *must* increment this whenever you make an incompatible protocol change - public static readonly int Version = 6; + public static readonly int Version = 7; } } diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index a1d8c603c0..7c14b6af63 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -167,7 +167,12 @@ namespace OpenRA.Server preConns.Add(newConn); // Dispatch a handshake order - DispatchOrdersToClient(newConn, 0, 0, new ServerOrder("HandshakeRequest", lobbyInfo.Serialize()).Serialize()); + var request = new HandshakeRequest() + { + Map = lobbyInfo.GlobalSettings.Map, + Mods = lobbyInfo.GlobalSettings.Mods.Select(m => "{0}@{1}".F(m,Mod.AllMods[m].Version)).ToArray() + }; + DispatchOrdersToClient(newConn, 0, 0, new ServerOrder("HandshakeRequest", request.Serialize()).Serialize()); } catch (Exception) { DropClient(newConn); } }