diff --git a/OpenRa.FileFormats/Session.cs b/OpenRa.FileFormats/Session.cs index e378d876e5..1d0ddd45bc 100644 --- a/OpenRa.FileFormats/Session.cs +++ b/OpenRa.FileFormats/Session.cs @@ -30,7 +30,7 @@ namespace OpenRa.FileFormats public class Global { public string Map = "scm12ea.ini"; - public string[] Mods = {}; // filename:sha1 pairs. + public string[] Packages = {}; // filename:sha1 pairs. public int OrderLatency = 3; } } diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index 814c9524d1..75a4c7ed86 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -382,20 +382,24 @@ namespace OpenRa.Game // todo: if we don't have all the resources, we don't want to do this yet. + if (Game.orderManager.FramesAhead != LobbyInfo.GlobalSettings.OrderLatency + && !Game.orderManager.GameStarted) + { + Game.orderManager.FramesAhead = LobbyInfo.GlobalSettings.OrderLatency; + Game.chat.AddLine(Color.White, "Server", + "Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency)); + } + + PackageDownloader.SetPackageList(LobbyInfo.GlobalSettings.Packages); + if (!PackageDownloader.IsIdle()) + return; + if (mapName != LobbyInfo.GlobalSettings.Map) { chat.AddLine(Color.White, "Debug", "Map change {0} -> {1}".F(mapName, session.GlobalSettings.Map)); ChangeMap(LobbyInfo.GlobalSettings.Map); } - - if (Game.orderManager.FramesAhead != LobbyInfo.GlobalSettings.OrderLatency - && !Game.orderManager.GameStarted) - { - Game.orderManager.FramesAhead = LobbyInfo.GlobalSettings.OrderLatency; - Game.chat.AddLine(Color.White, "Server", - "Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency)); - } } public static void StartGame() diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index d3c6ee66cf..f6c2dd173a 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -117,6 +117,7 @@ + diff --git a/OpenRa.Game/Orders/UnitOrders.cs b/OpenRa.Game/Orders/UnitOrders.cs index 1a23ff7f8e..92c2110aad 100644 --- a/OpenRa.Game/Orders/UnitOrders.cs +++ b/OpenRa.Game/Orders/UnitOrders.cs @@ -60,6 +60,11 @@ namespace OpenRa.Game.Orders Game.SyncLobbyInfo(order.TargetString); break; } + case "FileChunk": + { + PackageDownloader.ReceiveChunk(order.TargetString); + break; + } default: { diff --git a/OpenRa.Game/PackageDownloader.cs b/OpenRa.Game/PackageDownloader.cs new file mode 100644 index 0000000000..3e79ba3459 --- /dev/null +++ b/OpenRa.Game/PackageDownloader.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.FileFormats; +using System.IO; +using System.Security.Cryptography; + +namespace OpenRa.Game +{ + static class PackageDownloader + { + static string[] allPackages = { }; + static List missingPackages = new List(); + static string currentPackage = null; + static MemoryStream content = null; + + public static void SetPackageList(string[] packages) + { + allPackages = packages; + missingPackages = allPackages.Where(p => !HavePackage(p)).ToList(); + + if (currentPackage == null || !missingPackages.Contains(currentPackage)) + BeginDownload(); + } + + public static void ReceiveChunk(string data) + { + + } + + static void BeginDownload() + { + if (missingPackages.Count == 0) + { // we're finished downloading resources! + currentPackage = null; + return; + } + + currentPackage = missingPackages[0]; + missingPackages.RemoveAt(0); + + content = new MemoryStream(); + } + + static void EndDownload() + { + File.WriteAllBytes(currentPackage.Split(':')[0], content.ToArray()); + currentPackage = null; + + BeginDownload(); + } + + public static bool IsIdle() + { + return currentPackage == null + && missingPackages.Count == 0; + } + + static bool HavePackage(string p) + { + var parts = p.Split(':'); + return File.Exists(parts[0]) && CalculateSHA1(parts[0]) == parts[1]; + } + + public static string CalculateSHA1(string filename) + { + using (var csp = SHA1.Create()) + return new string(csp.ComputeHash(File.ReadAllBytes(filename)) + .SelectMany(a => a.ToString("x2")).ToArray()); + } + } +}