From 621336afec1f3268efbc459e060ebb232c03fc17 Mon Sep 17 00:00:00 2001 From: Adrian Date: Sat, 23 Apr 2016 02:42:14 +0200 Subject: [PATCH 1/9] Small syntactic changes --- src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs | 9 ++++----- src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs b/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs index 096e920..a861480 100644 --- a/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs +++ b/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs @@ -31,15 +31,14 @@ namespace AdrianKousz.GenieEngine number = reader.ReadInt32(); result.Files = new PositionInfo() - .CreateList() - .Fill(number, () => { - return new PositionInfo { + .CreateArray(number) + .Fill(() => new PositionInfo { Size = reader.ReadInt32(), Offset = reader.ReadInt32(), Name = reader.ReadZString(255), Filename = reader.ReadZString(257), - }; - }) + } + ) .Map(x => { var file = new Campaign.CpnFile(); reader.BaseStream.Seek(x.Offset, SeekOrigin.Begin); diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs index 9d4d967..b07b5e2 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs @@ -33,7 +33,7 @@ namespace AdrianKousz.GenieEngine result.VersionString = reader.ReadString(4); reader.ReadInt32(); // Header Length result.Unknown1 = reader.ReadInt32(); - result.Timestamp = DateTimes.FromUnixTime(reader.ReadInt32()); + result.Timestamp = reader.ReadInt32().ToDateTime(); result.InstructionsUncompressed = reader.ReadZStringInt32(); result.Unknown2 = reader.ReadInt32(); result.PlayerCount = reader.ReadInt32(); From ad4bd15136274ee5176df8b45cbbdd830154d178 Mon Sep 17 00:00:00 2001 From: Adrian Date: Sat, 23 Apr 2016 02:42:51 +0200 Subject: [PATCH 2/9] Refactor commands for new CmdApp interface --- src/cmdapp/GenieEngineApp.csproj | 4 +- src/cmdapp/src/AddBitmapCommand.cs | 22 +++-------- src/cmdapp/src/BaseCommand.cs | 36 ----------------- src/cmdapp/src/Bmp2MapCommand.cs | 23 ++++------- src/cmdapp/src/CompressCommand.cs | 23 ++++------- src/cmdapp/src/ConvertCommand.cs | 23 ++++------- src/cmdapp/src/DecompressCommand.cs | 21 ++++------ src/cmdapp/src/DelBitmapCommand.cs | 21 +++------- src/cmdapp/src/DumpunitsCommand.cs | 15 +++----- src/cmdapp/src/ExtractCommand.cs | 14 +++---- src/cmdapp/src/FromJsonCommand.cs | 20 +++------- src/cmdapp/src/PackCommand.cs | 14 +++---- src/cmdapp/src/Program.cs | 60 ++++++++++++----------------- src/cmdapp/src/ToJsonCommand.cs | 20 +++------- 14 files changed, 93 insertions(+), 223 deletions(-) delete mode 100644 src/cmdapp/src/BaseCommand.cs diff --git a/src/cmdapp/GenieEngineApp.csproj b/src/cmdapp/GenieEngineApp.csproj index c09987b..ba65730 100644 --- a/src/cmdapp/GenieEngineApp.csproj +++ b/src/cmdapp/GenieEngineApp.csproj @@ -32,7 +32,6 @@ - @@ -66,12 +65,11 @@ - - ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + diff --git a/src/cmdapp/src/AddBitmapCommand.cs b/src/cmdapp/src/AddBitmapCommand.cs index c910fd9..a1d2669 100644 --- a/src/cmdapp/src/AddBitmapCommand.cs +++ b/src/cmdapp/src/AddBitmapCommand.cs @@ -1,13 +1,12 @@ using System.IO; using System.Drawing; -using System.Drawing.Imaging; using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class AddBitmapCommand : BaseCommand + public class AddBitmapCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var input = File.OpenRead(args[0])) using (var output = File.OpenWrite(args[1])) @@ -23,20 +22,11 @@ namespace AdrianKousz.GenieEngine GenieFile.Serialize(scn, output); } } - - override public int GetArgumentCount() + public AddBitmapCommand() { - return 3; - } - - override public string GetDescription() - { - return "Add a pregame bitmap"; - } - - override public string GetHelp() - { - return "Add a pregame bitmap to a scenario." + MinArgumentCount = 3; + Description = "Add a pregame bitmap"; + Help = "Add a pregame bitmap to a scenario." + "\nThe bitmap has to be indexed, otherwise, the game will probably crash." + "\nAdditionally, a game-specific palette will be used to display the image." + "\n" diff --git a/src/cmdapp/src/BaseCommand.cs b/src/cmdapp/src/BaseCommand.cs deleted file mode 100644 index 7976ded..0000000 --- a/src/cmdapp/src/BaseCommand.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using AdrianKousz.Util; - -namespace AdrianKousz.GenieEngine -{ - public class BaseCommand : ICommand - { - protected string[] args; - - virtual public string GetDescription() - { - return "(Empty description)"; - } - - virtual public string GetHelp() - { - return "(Empty help text)"; - } - - virtual public int GetArgumentCount() - { - return 1; - } - - virtual public void SetArguments(string[] args) - { - this.args = args; - } - - virtual public void Run() - { - foreach (var str in args) - Console.WriteLine(str); - } - } -} diff --git a/src/cmdapp/src/Bmp2MapCommand.cs b/src/cmdapp/src/Bmp2MapCommand.cs index 9946a28..935e959 100644 --- a/src/cmdapp/src/Bmp2MapCommand.cs +++ b/src/cmdapp/src/Bmp2MapCommand.cs @@ -1,13 +1,12 @@ -using System; -using System.IO; +using System.IO; using System.Drawing; using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class Bmp2MapCommand : BaseCommand + public class Bmp2MapCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var srcstream = File.OpenRead(args[0])) using (var outstream = File.OpenWrite(args[1])) @@ -23,19 +22,11 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public Bmp2MapCommand() { - return 4; - } - - override public string GetDescription() - { - return "Generate a scenario map based on bitmaps"; - } - - override public string GetHelp() - { - return "Generate a scenario map based on bitmaps with automatic forest generation." + MinArgumentCount = 4; + Description = "Generate a scenario map based on bitmaps"; + Help = "Generate a scenario map based on bitmaps with automatic forest generation." + "\n" + "\nTwo bitmaps need to be specified: One terrain map and one elevation map." + "\nBoth bitmaps need to be indexed or grayscale." diff --git a/src/cmdapp/src/CompressCommand.cs b/src/cmdapp/src/CompressCommand.cs index fbf0462..11123e5 100644 --- a/src/cmdapp/src/CompressCommand.cs +++ b/src/cmdapp/src/CompressCommand.cs @@ -1,10 +1,11 @@ using System.IO; +using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class CompressCommand : BaseCommand + public class CompressCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var input = File.OpenRead(args[0])) using (var output = File.OpenWrite(args[1])) @@ -13,23 +14,15 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public CompressCommand() { - return 2; - } - - override public string GetDescription() - { - return "Recompress a decompressed scenario file"; - } - - override public string GetHelp() - { - return "Recompress a previously decompressed scenario file." + MinArgumentCount = 2; + Description = "Recompress a decompressed scenario file"; + Help = "Recompress a previously decompressed scenario file." + "\n" + "\nParameters:" + "\n " - ; + ; } } } diff --git a/src/cmdapp/src/ConvertCommand.cs b/src/cmdapp/src/ConvertCommand.cs index 723b9a4..199438a 100644 --- a/src/cmdapp/src/ConvertCommand.cs +++ b/src/cmdapp/src/ConvertCommand.cs @@ -1,12 +1,11 @@ -using System; -using System.IO; +using System.IO; using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class ConvertCommand : BaseCommand + public class ConvertCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var srcstream = File.OpenRead(args[0])) using (var outstream = File.OpenWrite(args[1])) @@ -33,19 +32,11 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public ConvertCommand() { - return 3; - } - - override public string GetDescription() - { - return "Convert AOE1 scenario"; - } - - override public string GetHelp() - { - return "Convert AOE1 scenario to AOE2" + MinArgumentCount = 3; + Description = "Convert AOE1 scenario"; + Help = "Convert AOE1 scenario to AOE2" + "\n" + "\nThe converter needs an existing AOE2 scenario to start with." + "\n" diff --git a/src/cmdapp/src/DecompressCommand.cs b/src/cmdapp/src/DecompressCommand.cs index c21b301..c6a9181 100644 --- a/src/cmdapp/src/DecompressCommand.cs +++ b/src/cmdapp/src/DecompressCommand.cs @@ -1,10 +1,11 @@ using System.IO; +using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class DecompressCommand : BaseCommand + public class DecompressCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var input = File.OpenRead(args[0])) using (var output = File.OpenWrite(args[1])) @@ -13,19 +14,11 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public DecompressCommand() { - return 2; - } - - override public string GetDescription() - { - return "Decompress a scenario file"; - } - - override public string GetHelp() - { - return "Decompress a scenario file for hex editing." + MinArgumentCount = 2; + Description = "Decompress a scenario file"; + Help = "Decompress a scenario file for hex editing." + "\n" + "\nParameters:" + "\n " diff --git a/src/cmdapp/src/DelBitmapCommand.cs b/src/cmdapp/src/DelBitmapCommand.cs index 63e5f5c..20d5e64 100644 --- a/src/cmdapp/src/DelBitmapCommand.cs +++ b/src/cmdapp/src/DelBitmapCommand.cs @@ -1,12 +1,11 @@ using System.IO; -using System.Drawing; using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class DelBitmapCommand : BaseCommand + public class DelBitmapCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var input = File.OpenRead(args[0])) using (var output = File.OpenWrite(args[1])) @@ -21,19 +20,11 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public DelBitmapCommand() { - return 2; - } - - override public string GetDescription() - { - return "Remove the pregame bitmap"; - } - - override public string GetHelp() - { - return "Remove the pregame bitmap from a scenario." + MinArgumentCount = 2; + Description = "Remove the pregame bitmap"; + Help = "Remove the pregame bitmap from a scenario." + "\n" + "\nParameters:" + "\n " diff --git a/src/cmdapp/src/DumpunitsCommand.cs b/src/cmdapp/src/DumpunitsCommand.cs index 56eca5e..958220e 100644 --- a/src/cmdapp/src/DumpunitsCommand.cs +++ b/src/cmdapp/src/DumpunitsCommand.cs @@ -1,13 +1,12 @@ using System; using System.IO; -using System.Collections.Generic; using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class DumpunitsCommand : BaseCommand + public class DumpunitsCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { Scenario scn; using (var input = File.OpenRead(args[0])) @@ -30,14 +29,10 @@ namespace AdrianKousz.GenieEngine }); } - override public int GetArgumentCount() + public DumpunitsCommand() { - return 1; - } - - override public string GetDescription() - { - return "Dump units and map tiles below"; + MinArgumentCount = 1; + Description = "Dump units and underlying map tiles"; } } } diff --git a/src/cmdapp/src/ExtractCommand.cs b/src/cmdapp/src/ExtractCommand.cs index 514d895..23d0275 100644 --- a/src/cmdapp/src/ExtractCommand.cs +++ b/src/cmdapp/src/ExtractCommand.cs @@ -4,9 +4,9 @@ using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class ExtractCommand : BaseCommand + public class ExtractCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var file = File.OpenRead(args[0])) { @@ -22,14 +22,10 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public ExtractCommand() { - return 1; - } - - override public string GetDescription() - { - return "Extract files from campaign file"; + MinArgumentCount = 1; + Description = "Extract files from campaign file"; } } } diff --git a/src/cmdapp/src/FromJsonCommand.cs b/src/cmdapp/src/FromJsonCommand.cs index 7ad9ce8..641e0d8 100644 --- a/src/cmdapp/src/FromJsonCommand.cs +++ b/src/cmdapp/src/FromJsonCommand.cs @@ -4,9 +4,9 @@ using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class FromJsonCommand : BaseCommand + public class FromJsonCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var input = File.OpenRead(args[0])) using (var reader = input.GetReader()) @@ -18,19 +18,11 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public FromJsonCommand() { - return 2; - } - - override public string GetDescription() - { - return "Convert a JSON file to a scenario"; - } - - override public string GetHelp() - { - return "Read a Scenario structure formatted as JSON and save it as a Scenario." + MinArgumentCount = 2; + Description = "Convert a JSON file to a scenario"; + Help = "Read a Scenario structure formatted as JSON and save it as a Scenario." + "\n" + "\nParameters:" + "\n " diff --git a/src/cmdapp/src/PackCommand.cs b/src/cmdapp/src/PackCommand.cs index 57acae8..3f2aee8 100644 --- a/src/cmdapp/src/PackCommand.cs +++ b/src/cmdapp/src/PackCommand.cs @@ -4,9 +4,9 @@ using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class PackCommand : BaseCommand + public class PackCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { var files = new List(); for (var i = 2; i < args.Length; i++) { @@ -33,14 +33,10 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public PackCommand() { - return 3; - } - - override public string GetDescription() - { - return "Pack files into a campaign file"; + MinArgumentCount = 3; + Description = "Pack files into a campaign file"; } } } diff --git a/src/cmdapp/src/Program.cs b/src/cmdapp/src/Program.cs index 346cafd..f3f0d77 100644 --- a/src/cmdapp/src/Program.cs +++ b/src/cmdapp/src/Program.cs @@ -1,51 +1,39 @@ -using AdrianKousz.Util; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Windows.Forms; +using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class Program : IApp + public class Program { public static void Main(string[] args) { System.Threading.Thread.CurrentThread.Name = "main"; Log.SetUncaughtExceptionHandler(); - if (System.Diagnostics.Debugger.IsAttached) { - debug(); - return; - } - - new CmdApp(new Program(), args).Run(); + new CmdApp.Builder() + .Header("Scenario Editor") + .NoArg(new MessageBoxCommand()) + .Add("convert", new ConvertCommand()) + .Add("bmp2map", new Bmp2MapCommand()) + .Add("addbmp", new AddBitmapCommand()) + .Add("delbmp", new DelBitmapCommand()) + .Add("compress", new CompressCommand()) + .Add("decompress", new DecompressCommand()) + .Add("tojson", new ToJsonCommand()) + .Add("fromjson", new FromJsonCommand()) + .Add("dumpunits", new DumpunitsCommand()) + .Add("extract", new ExtractCommand()) + .Add("pack", new PackCommand()) + .Build() + .Run(args); } - public string GetHeader() + private class MessageBoxCommand : CmdApp.Command { - return "Scenario Editor"; - } - - public IDictionary> GetCommands() - { - var result = new Dictionary>(); - result.Add("convert", new ConvertCommand()); - result.Add("bmp2map", new Bmp2MapCommand()); - result.Add("addbmp", new AddBitmapCommand()); - result.Add("delbmp", new DelBitmapCommand()); - result.Add("compress", new CompressCommand()); - result.Add("decompress", new DecompressCommand()); - result.Add("tojson", new ToJsonCommand()); - result.Add("fromjson", new FromJsonCommand()); - result.Add("dumpunits", new DumpunitsCommand()); - result.Add("extract", new ExtractCommand()); - result.Add("pack", new PackCommand()); - return result; - } - - private static void debug() - { - var fn = ""; - using (var istream = System.IO.File.OpenRead(fn)) { - var scn = GenieFile.Deserialize(istream); - System.Diagnostics.Debugger.Break(); // Great to inspect scn + public override void Run(string[] args) + { + MessageBox.Show("Start the program on the command line like \n> GenieEdit.exe help"); } } } diff --git a/src/cmdapp/src/ToJsonCommand.cs b/src/cmdapp/src/ToJsonCommand.cs index 50805c7..7c3b6e9 100644 --- a/src/cmdapp/src/ToJsonCommand.cs +++ b/src/cmdapp/src/ToJsonCommand.cs @@ -4,9 +4,9 @@ using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class ToJsonCommand : BaseCommand + public class ToJsonCommand : CmdApp.Command { - override public void Run() + override public void Run(string[] args) { using (var input = File.OpenRead(args[0])) using (var output = File.OpenWrite(args[1])) @@ -18,19 +18,11 @@ namespace AdrianKousz.GenieEngine } } - override public int GetArgumentCount() + public ToJsonCommand() { - return 2; - } - - override public string GetDescription() - { - return "Convert a scenario to a JSON file"; - } - - override public string GetHelp() - { - return "Save a Scenario structure formatted as JSON." + MinArgumentCount = 2; + Description = "Convert a scenario to a JSON file"; + Help = "Save a Scenario structure formatted as JSON." + "\n" + "\nParameters:" + "\n " From 5a19ea7103b19fca7f967cc3f8fd7320fe59a805 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 25 Apr 2016 17:09:12 +0200 Subject: [PATCH 3/9] Small fix * Use specific bool reading/writing methods * Fix reading of ResourceCopies --- .../ScnSerializerReader.cs | 16 ++++++------- .../ScnSerializerWriter.cs | 24 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs index b07b5e2..fb07801 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs @@ -65,8 +65,8 @@ namespace AdrianKousz.GenieEngine } result.PlayerSettings.ForEach(x => { - x.Active = reader.ReadBoolean(); - x.Human = reader.ReadBoolean(); + x.Active = reader.ReadBooleanInt32(); + x.Human = reader.ReadBooleanInt32(); x.Civ = reader.ReadInt32(); x.UnknownInfo = reader.ReadInt32(); }); @@ -110,7 +110,7 @@ namespace AdrianKousz.GenieEngine result.Cinematics.FilenameLoss = reader.ReadStringInt16(); result.Cinematics.FilenameBitmap = reader.ReadStringInt16(); - var hasBitmap = reader.ReadBoolean(); + var hasBitmap = reader.ReadBooleanInt32(); result.Cinematics.BitmapWidth = reader.ReadInt32(); result.Cinematics.BitmapHeight = reader.ReadInt32(); @@ -166,13 +166,13 @@ namespace AdrianKousz.GenieEngine result.GlobalVictory = factory.MakeGlobalVictory(); - result.GlobalVictory.RequireConquest = reader.ReadBoolean(); + result.GlobalVictory.RequireConquest = reader.ReadBooleanInt32(); result.GlobalVictory.Ruins = reader.ReadInt32(); result.GlobalVictory.Artifacts = reader.ReadInt32(); result.GlobalVictory.Discovery = reader.ReadInt32(); result.GlobalVictory.PercentExplored = reader.ReadInt32(); result.GlobalVictory.Unknown = reader.ReadInt32(); - result.GlobalVictory.RequireAllCustom = reader.ReadBoolean(); + result.GlobalVictory.RequireAllCustom = reader.ReadBooleanInt32(); result.GlobalVictory.Mode = reader.ReadInt32(); result.GlobalVictory.Score = reader.ReadInt32(); result.GlobalVictory.Time = reader.ReadInt32(); @@ -188,7 +188,7 @@ namespace AdrianKousz.GenieEngine ReadSeparator(reader, "Player Environment"); result.PlayerSettings.ForEach(x => { - x.AlliedVictory = reader.ReadBoolean(); + x.AlliedVictory = reader.ReadBooleanInt32(); }); if (Version >= 1.15f) number = (Scenario.NumPlayers * ( 20 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/; @@ -232,9 +232,9 @@ namespace AdrianKousz.GenieEngine x.ResourceGold = reader.ReadSingle(); x.ResourceStone = reader.ReadSingle(); if (Version >= 1.18f) { - x.ResourceOre = reader.ReadInt32(); + x.ResourceOre = reader.ReadSingle(); if (Version < 1.3f) { - x.UnknownResource = reader.ReadInt32(); + x.UnknownResource = reader.ReadSingle(); } } if (Version >= 1.22f) { diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs index 082a0f3..d3b7a9e 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs @@ -23,7 +23,7 @@ namespace AdrianKousz.GenieEngine // Uncompressed header writer.WriteStringRaw(value.VersionString); - writer.Write((int)UncompressedHeaderLength); + writer.Write((System.Int32)UncompressedHeaderLength); writer.Write(value.Unknown1); writer.Write((System.Int32)DateTimes.ToUnixTime(value.Timestamp)); writer.WriteZStringInt32(value.InstructionsUncompressed); @@ -53,8 +53,8 @@ namespace AdrianKousz.GenieEngine } value.PlayerSettings.ForEach(x => { - writer.Write(x.Active); - writer.Write(x.Human); + writer.WriteBooleanInt32(x.Active); + writer.WriteBooleanInt32(x.Human); writer.Write(x.Civ); writer.Write(x.UnknownInfo); }); @@ -96,7 +96,7 @@ namespace AdrianKousz.GenieEngine var hasBitmap = value.Cinematics.RawBitmap.Length > 0; - writer.Write(hasBitmap); + writer.WriteBooleanInt32(hasBitmap); writer.Write(value.Cinematics.BitmapWidth); writer.Write(value.Cinematics.BitmapHeight); writer.Write(value.Cinematics.BitmapUnknown); @@ -113,9 +113,9 @@ namespace AdrianKousz.GenieEngine }); value.PlayerSettings.ForEach(x => { - writer.Write((int)writer.GetByteCount(x.ScriptAI)); - writer.Write((int)writer.GetByteCount(x.ScriptCTY)); - writer.Write((int)writer.GetByteCount(x.ScriptPER)); + writer.Write((System.Int32)writer.GetByteCount(x.ScriptAI)); + writer.Write((System.Int32)writer.GetByteCount(x.ScriptCTY)); + writer.Write((System.Int32)writer.GetByteCount(x.ScriptPER)); writer.WriteStringRaw(x.ScriptAI); writer.WriteStringRaw(x.ScriptCTY); writer.WriteStringRaw(x.ScriptPER); @@ -148,13 +148,13 @@ namespace AdrianKousz.GenieEngine // Diplomacy - writer.Write(value.GlobalVictory.RequireConquest); + writer.WriteBooleanInt32(value.GlobalVictory.RequireConquest); writer.Write(value.GlobalVictory.Ruins); writer.Write(value.GlobalVictory.Artifacts); writer.Write(value.GlobalVictory.Discovery); writer.Write(value.GlobalVictory.PercentExplored); writer.Write(value.GlobalVictory.Unknown); - writer.Write(value.GlobalVictory.RequireAllCustom); + writer.WriteBooleanInt32(value.GlobalVictory.RequireAllCustom); writer.Write(value.GlobalVictory.Mode); writer.Write(value.GlobalVictory.Score); writer.Write(value.GlobalVictory.Time); @@ -172,7 +172,7 @@ namespace AdrianKousz.GenieEngine WriteSeparator(writer, "Player Environment"); value.PlayerSettings.ForEach(x => { - writer.Write(x.AlliedVictory); + writer.WriteBooleanInt32(x.AlliedVictory); }); writer.Write(value.RawDisables); @@ -203,7 +203,7 @@ namespace AdrianKousz.GenieEngine // ResourceCopies - writer.Write((int)value.Units.Length); + writer.Write((System.Int32)value.Units.Count); value.ResourceCopies.ForEach(x => { writer.Write(x.ResourceFood); @@ -224,7 +224,7 @@ namespace AdrianKousz.GenieEngine // Units value.Units.ForEach(x => { - writer.Write((int)x.Count); + writer.Write((System.Int32)x.Count); x.ForEach(y => { writer.Write(y.PosX); writer.Write(y.PosY); From 01a17394966a53192f28972125e0367a271030a3 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 25 Apr 2016 17:11:21 +0200 Subject: [PATCH 4/9] Fix scenario compression --- src/lib/AdrianKousz.GenieEngine/GenieFile.cs | 29 ++++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/lib/AdrianKousz.GenieEngine/GenieFile.cs b/src/lib/AdrianKousz.GenieEngine/GenieFile.cs index cb8a40e..87981ad 100644 --- a/src/lib/AdrianKousz.GenieEngine/GenieFile.cs +++ b/src/lib/AdrianKousz.GenieEngine/GenieFile.cs @@ -101,13 +101,29 @@ namespace AdrianKousz.GenieEngine return new ExtendedBinaryWriter(new NonDisposingStreamWrapper(stream), Scenario.Encoding); } - public static void ScenarioCompression(Stream input, Stream output, bool decompress) + public static void ScenarioDecompress(Stream input, Stream output) { - var mode = decompress ? CompressionMode.Decompress : CompressionMode.Compress; + CopyHeader(input, output); - byte[] buffer; + using (var comp = new DeflateStream(input, CompressionMode.Decompress)) + { + comp.CopyTo(output); + } + } - buffer = input.ReadBytes(8); + public static void ScenarioCompress(Stream input, Stream output) + { + CopyHeader(input, output); + + using (var comp = new DeflateStream(output, CompressionMode.Compress)) + { + input.CopyTo(comp); + } + } + + private static void CopyHeader(Stream input, Stream output) + { + var buffer = input.ReadBytes(8); output.Write(buffer); var headerLength = buffer[4] @@ -118,11 +134,6 @@ namespace AdrianKousz.GenieEngine buffer = input.ReadBytes(headerLength); output.Write(buffer); - - using (var comp = new DeflateStream(input, mode)) - { - comp.CopyTo(output); - } } #endregion From 11f9804f240e8d539e420a651801f49356571359 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 25 Apr 2016 17:11:49 +0200 Subject: [PATCH 5/9] Fix scenario compression commands --- src/cmdapp/src/CompressCommand.cs | 2 +- src/cmdapp/src/DecompressCommand.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmdapp/src/CompressCommand.cs b/src/cmdapp/src/CompressCommand.cs index 11123e5..2098e7b 100644 --- a/src/cmdapp/src/CompressCommand.cs +++ b/src/cmdapp/src/CompressCommand.cs @@ -10,7 +10,7 @@ namespace AdrianKousz.GenieEngine using (var input = File.OpenRead(args[0])) using (var output = File.OpenWrite(args[1])) { - GenieFile.ScenarioCompression(input, output, false); + GenieFile.ScenarioCompress(input, output); } } diff --git a/src/cmdapp/src/DecompressCommand.cs b/src/cmdapp/src/DecompressCommand.cs index c6a9181..e35325e 100644 --- a/src/cmdapp/src/DecompressCommand.cs +++ b/src/cmdapp/src/DecompressCommand.cs @@ -10,7 +10,7 @@ namespace AdrianKousz.GenieEngine using (var input = File.OpenRead(args[0])) using (var output = File.OpenWrite(args[1])) { - GenieFile.ScenarioCompression(input, output, true); + GenieFile.ScenarioDecompress(input, output); } } From e580e0d8ed25421b98f2f4606cac6a48f35e43b7 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 25 Apr 2016 17:13:59 +0200 Subject: [PATCH 6/9] Add reading of PlayerSettings2 Additionally: * Reorder fields in Scenario for more convenient serialization order in JSON * Use lists instead of arrays --- .../AdrianKousz.GenieEngine/IScnFactory.cs | 3 +- src/lib/AdrianKousz.GenieEngine/Scenario.cs | 93 ++++++++++++------- .../ScnDefaultFactory.cs | 50 ++++++---- .../ScnSerializerReader.cs | 42 +++++++-- .../ScnSerializerWriter.cs | 36 ++++++- src/lib/AssemblyInfo.cs | 2 +- 6 files changed, 162 insertions(+), 64 deletions(-) diff --git a/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs b/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs index eee1a25..1ce19b5 100644 --- a/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs +++ b/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs @@ -4,10 +4,11 @@ { Scenario MakeScenario(); Scenario.ScnPlayerSettings MakePlayerSettings(); + Scenario.ScnResourceCopy MakeResourceCopy(); + Scenario.ScnPlayerSettings2 MakePlayerSettings2(); Scenario.ScnMessages MakeMessages(); Scenario.ScnCinematics MakeCinematics(); Scenario.ScnGlobalVictory MakeGlobalVictory(); - Scenario.ScnResourceCopy MakeResourceCopy(); Scenario.ScnMap MakeMap(); Scenario.ScnUnit MakeUnit(); } diff --git a/src/lib/AdrianKousz.GenieEngine/Scenario.cs b/src/lib/AdrianKousz.GenieEngine/Scenario.cs index 3a9666b..6ace629 100644 --- a/src/lib/AdrianKousz.GenieEngine/Scenario.cs +++ b/src/lib/AdrianKousz.GenieEngine/Scenario.cs @@ -22,30 +22,30 @@ namespace AdrianKousz.GenieEngine public String Filename; public DateTime Timestamp; public String InstructionsUncompressed; - public Int32 NextId; public Int32 PlayerCount; + + public IList PlayerSettings; + public IList ResourceCopies; + public IList PlayerSettings2; + public ScnMessages Messages; public ScnCinematics Cinematics; public ScnGlobalVictory GlobalVictory; + public ScnMap Map; + public IList> Units; - public ScnPlayerSettings[] PlayerSettings; - public ScnResourceCopy[] ResourceCopies; - public IList[] Units; - - // NOTE: Raw byte arrays that do not have a parser (yet?) - public Byte[] RawIndividualVictory; - public Byte[] RawDisables; - public Byte[] RawRemaining; - - // NOTE: Unknown values public Int32 Unknown1; public Int32 Unknown2; public Int32 Unknown3; public Byte Unknown4; public Single Unknown5; + public Byte[] RawIndividualVictory; + public Byte[] RawDisables; + public Byte[] RawRemaining; + public class ScnPlayerSettings { public const Int32 ExpectedUnknownInfo = 4; @@ -55,16 +55,10 @@ namespace AdrianKousz.GenieEngine public Int32 NameStringID; public Boolean Active; public Boolean Human; - public Int32 Civ; - public Int32 UnknownInfo; - - public String FilenameAI; - public String FilenameCTY; - public String FilenamePER; - public String ScriptAI; - public String ScriptCTY; - public String ScriptPER; public Byte AIType; + public Int32 Civ; + public Int32 StartingAge; + public Int32 UnknownInfo; public Int32 ResourceWood; public Int32 ResourceFood; @@ -73,9 +67,51 @@ namespace AdrianKousz.GenieEngine public Int32 ResourceOre; public Int32 UnknownResource; - public Int32[] Diplomacy; public Boolean AlliedVictory; - public Int32 StartingAge; + public Int32[] Diplomacy; + + public String FilenameAI; + public String FilenameCTY; + public String FilenamePER; + public String ScriptAI; + public String ScriptCTY; + public String ScriptPER; + } + + public class ScnResourceCopy + { + public const Single ExpectedUnknownResource = 0; + + public Single ResourceGold; + public Single ResourceWood; + public Single ResourceFood; + public Single ResourceStone; + public Single ResourceOre; + public Single UnknownResource; + public Single PopulationLimit; + } + + public class ScnPlayerSettings2 + { + public String Name; + + public Single CameraX; + public Single CameraY; + public Int16 UnknownX; + public Int16 UnknownY; + public Int32 Color; + public Byte AlliedVictory; + public Stance[] Stances; + + public Single Unknown1; + public Int32 Unknown2; + public Byte[] Unknown; + + public class Stance + { + public Byte Stance1; + public Int32 Stance2; + } } public class ScnMessages @@ -127,19 +163,6 @@ namespace AdrianKousz.GenieEngine public Int32 Unknown; } - public class ScnResourceCopy - { - public const Single ExpectedUnknownResource = 0; - - public Single ResourceGold; - public Single ResourceWood; - public Single ResourceFood; - public Single ResourceStone; - public Single ResourceOre; - public Single UnknownResource; - public Single PopulationLimit; - } - public class ScnMap { public Int32 CameraX; diff --git a/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs b/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs index 3fa4e47..1d4c71e 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs @@ -32,13 +32,10 @@ namespace AdrianKousz.GenieEngine result.Cinematics = MakeCinematics(); result.GlobalVictory = MakeGlobalVictory(); result.Map = MakeMap(); - result.ResourceCopies = new Scenario.ScnResourceCopy[Scenario.NumPlayerSections - 1] - .Fill(MakeResourceCopy); - result.PlayerSettings = new Scenario.ScnPlayerSettings[Scenario.NumPlayers] - .Fill(MakePlayerSettings); - result.Units = new List[Scenario.NumPlayerSections] - .Fill(); - + result.PlayerSettings = result.PlayerSettings.NewList().Fill(Scenario.NumPlayers, MakePlayerSettings); + result.ResourceCopies = result.ResourceCopies.NewList().Fill(Scenario.NumPlayerSections - 1, MakeResourceCopy); + result.PlayerSettings2 = result.PlayerSettings2.NewList().Fill(Scenario.NumPlayerSections - 1, MakePlayerSettings2); + result.Units = MakeUnitList(Scenario.NumPlayerSections); } return result; @@ -63,6 +60,25 @@ namespace AdrianKousz.GenieEngine return result; } + public Scenario.ScnResourceCopy MakeResourceCopy() + { + // AOE2 standard + var result = new Scenario.ScnResourceCopy(); + result.UnknownResource = Scenario.ScnResourceCopy.ExpectedUnknownResource; + result.ResourceFood = 200; + result.ResourceWood = 200; + result.ResourceGold = 100; + result.ResourceStone = 200; + result.PopulationLimit = 75; + return result; + } + + public Scenario.ScnPlayerSettings2 MakePlayerSettings2() + { + var result = new Scenario.ScnPlayerSettings2(); + return result; + } + public Scenario.ScnMessages MakeMessages() { var result = new Scenario.ScnMessages(); @@ -101,19 +117,6 @@ namespace AdrianKousz.GenieEngine return result; } - public Scenario.ScnResourceCopy MakeResourceCopy() - { - // AOE2 standard - var result = new Scenario.ScnResourceCopy(); - result.UnknownResource = Scenario.ScnResourceCopy.ExpectedUnknownResource; - result.ResourceFood = 200; - result.ResourceWood = 200; - result.ResourceGold = 100; - result.ResourceStone = 200; - result.PopulationLimit = 75; - return result; - } - public Scenario.ScnMap MakeMap() { var result = new Scenario.ScnMap(); @@ -135,6 +138,13 @@ namespace AdrianKousz.GenieEngine result.GarrisonnedInId = -1; return result; } + + public static IList> MakeUnitList(int count = Scenario.NumPlayerSections) + { + IList> result = new List>() + .Fill(count, () => (IList)new List()); + return result; + } } } diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs index fb07801..1ae13ad 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs @@ -49,8 +49,7 @@ namespace AdrianKousz.GenieEngine result.VersionNumber = reader.ReadSingle(); Version = result.VersionNumber; - result.PlayerSettings = new Scenario.ScnPlayerSettings[Scenario.NumPlayers] - .Fill(factory.MakePlayerSettings); + result.PlayerSettings = result.PlayerSettings.NewList().Fill(Scenario.NumPlayers, factory.MakePlayerSettings); // PlayerSettings 1 @@ -223,8 +222,7 @@ namespace AdrianKousz.GenieEngine number = reader.ReadInt32(); - result.ResourceCopies = new Scenario.ScnResourceCopy[number - 1] - .Fill(factory.MakeResourceCopy); + result.ResourceCopies = result.ResourceCopies.NewList().Fill(number - 1, factory.MakeResourceCopy); result.ResourceCopies.ForEach(x => { x.ResourceFood = reader.ReadSingle(); @@ -244,7 +242,7 @@ namespace AdrianKousz.GenieEngine // Units - result.Units = new List[number].Fill(); + result.Units = ScnDefaultFactory.MakeUnitList(number); result.Units.ForEach(x => { var count = reader.ReadInt32(); @@ -265,7 +263,39 @@ namespace AdrianKousz.GenieEngine }); }); - // More Player Settings and Triggers + // PlayerSettings2 + + number = reader.ReadInt32(); + + result.PlayerSettings2 = result.PlayerSettings2.NewList().Fill(number - 1, factory.MakePlayerSettings2); + + result.PlayerSettings2.ForEach(x => { + x.Name = reader.ReadZStringInt16(); + x.CameraX = reader.ReadSingle(); + x.CameraY = reader.ReadSingle(); + x.UnknownX = reader.ReadInt16(); + x.UnknownY = reader.ReadInt16(); + x.AlliedVictory = reader.ReadByte(); + number = reader.ReadInt16(); + x.Stances = new Scenario.ScnPlayerSettings2.Stance[number].Fill(); + x.Stances.ForEach(y => { y.Stance1 = reader.ReadByte(); }); + x.Stances.ForEach(y => { y.Stance2 = reader.ReadInt32(); }); + if (Version >= 1.18f) { + x.Color = reader.ReadInt32(); + } + + x.Unknown1 = reader.ReadSingle(); + x.Unknown2 = reader.ReadInt32(); + + if (x.Unknown1 == 1.0f || x.Unknown1 == 2.0f) { + x.Unknown = reader.ReadBytes(1 + (int)x.Unknown1 * 8 + x.Unknown2 * 44); + } else { + var msg = string.Format("Numbers {0}/{1} for {2}", x.Unknown1, x.Unknown2, x.Name); + throw new System.NotImplementedException(msg); + } + }); + + // Triggers var bytestream = new MemoryStream(); reader.BaseStream.CopyTo(bytestream); diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs index d3b7a9e..972462f 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs @@ -17,6 +17,8 @@ namespace AdrianKousz.GenieEngine public void Write(ExtendedBinaryWriter writer, Scenario value) { + EnsureValid(value); + var Version = value.VersionNumber; var UncompressedHeaderLength = 20 + writer.GetZByteCount(value.InstructionsUncompressed); @@ -240,7 +242,31 @@ namespace AdrianKousz.GenieEngine }); }); - // More Player Settings and Triggers + // PlayerSettings2 + + writer.Write((System.Int32)(value.PlayerSettings2.Count + 1)); + + value.PlayerSettings2.ForEach(x => { + writer.WriteZStringInt16(x.Name); + writer.Write(x.CameraX); + writer.Write(x.CameraY); + writer.Write(x.UnknownX); + writer.Write(x.UnknownY); + writer.Write(x.AlliedVictory); + writer.Write((System.Int16)x.Stances.Length); + x.Stances.ForEach(y => { writer.Write(y.Stance1); }); + x.Stances.ForEach(y => { writer.Write(y.Stance2); }); + if (Version >= 1.18f) { + writer.Write(x.Color); + } + + writer.Write(x.Unknown1); + writer.Write(x.Unknown2); + + writer.Write(x.Unknown); + }); + + // Triggers writer.Write(value.RawRemaining); @@ -256,6 +282,14 @@ namespace AdrianKousz.GenieEngine { writer.Write(Scenario.Separator); } + + private void EnsureValid(Scenario value) + { + if (value.PlayerSettings.Count != Scenario.NumPlayers) + throw new System.InvalidOperationException("PlayerSettings.Count != 16"); + if (value.Units.Count - 1 != value.ResourceCopies.Count) + throw new System.InvalidOperationException("Conflicting unit and resource copy count"); + } } } diff --git a/src/lib/AssemblyInfo.cs b/src/lib/AssemblyInfo.cs index bbd4456..416259d 100644 --- a/src/lib/AssemblyInfo.cs +++ b/src/lib/AssemblyInfo.cs @@ -2,4 +2,4 @@ [assembly: AssemblyTitle("ScenLib")] [assembly: AssemblyDescription("Read and write scenario data from Genie Engine games")] -[assembly: AssemblyVersion("0.5")] +[assembly: AssemblyVersion("0.6")] From e1af13f4a9e4b136d85f6f83658acd1346675bdb Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 26 Apr 2016 00:56:26 +0200 Subject: [PATCH 7/9] Rename ConvertCommandHelper --- src/cmdapp/GenieEngineApp.csproj | 2 +- src/cmdapp/src/{CopymapConverter.cs => ConvertCommandHelper.cs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/cmdapp/src/{CopymapConverter.cs => ConvertCommandHelper.cs} (100%) diff --git a/src/cmdapp/GenieEngineApp.csproj b/src/cmdapp/GenieEngineApp.csproj index ba65730..da8f000 100644 --- a/src/cmdapp/GenieEngineApp.csproj +++ b/src/cmdapp/GenieEngineApp.csproj @@ -38,13 +38,13 @@ - + diff --git a/src/cmdapp/src/CopymapConverter.cs b/src/cmdapp/src/ConvertCommandHelper.cs similarity index 100% rename from src/cmdapp/src/CopymapConverter.cs rename to src/cmdapp/src/ConvertCommandHelper.cs From e56d02ae182fe28f65c1a2872af7876387b50834 Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 26 Apr 2016 15:16:34 +0200 Subject: [PATCH 8/9] Rename Resources2 --- .../CpnSerializerReader.cs | 13 ++++++------- src/lib/AdrianKousz.GenieEngine/IScnFactory.cs | 2 +- src/lib/AdrianKousz.GenieEngine/Scenario.cs | 18 +++++++++--------- .../ScnDefaultFactory.cs | 16 ++++++++-------- .../ScnSerializerReader.cs | 16 ++++++++-------- .../ScnSerializerWriter.cs | 16 ++++++++-------- 6 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs b/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs index a861480..994678f 100644 --- a/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs +++ b/src/lib/AdrianKousz.GenieEngine/CpnSerializerReader.cs @@ -33,12 +33,11 @@ namespace AdrianKousz.GenieEngine result.Files = new PositionInfo() .CreateArray(number) .Fill(() => new PositionInfo { - Size = reader.ReadInt32(), - Offset = reader.ReadInt32(), - Name = reader.ReadZString(255), - Filename = reader.ReadZString(257), - } - ) + Size = reader.ReadInt32(), + Offset = reader.ReadInt32(), + Name = reader.ReadZString(255), + Filename = reader.ReadZString(257), + }) .Map(x => { var file = new Campaign.CpnFile(); reader.BaseStream.Seek(x.Offset, SeekOrigin.Begin); @@ -47,7 +46,7 @@ namespace AdrianKousz.GenieEngine file.Filename = x.Filename; return file; }) - .ToArray(); + .ToList(); return result; } diff --git a/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs b/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs index 1ce19b5..6197f00 100644 --- a/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs +++ b/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs @@ -4,7 +4,7 @@ { Scenario MakeScenario(); Scenario.ScnPlayerSettings MakePlayerSettings(); - Scenario.ScnResourceCopy MakeResourceCopy(); + Scenario.ScnResource2 MakeResources2(); Scenario.ScnPlayerSettings2 MakePlayerSettings2(); Scenario.ScnMessages MakeMessages(); Scenario.ScnCinematics MakeCinematics(); diff --git a/src/lib/AdrianKousz.GenieEngine/Scenario.cs b/src/lib/AdrianKousz.GenieEngine/Scenario.cs index 6ace629..54fe077 100644 --- a/src/lib/AdrianKousz.GenieEngine/Scenario.cs +++ b/src/lib/AdrianKousz.GenieEngine/Scenario.cs @@ -26,7 +26,7 @@ namespace AdrianKousz.GenieEngine public Int32 PlayerCount; public IList PlayerSettings; - public IList ResourceCopies; + public IList Resources2; public IList PlayerSettings2; public ScnMessages Messages; @@ -78,16 +78,16 @@ namespace AdrianKousz.GenieEngine public String ScriptPER; } - public class ScnResourceCopy + public class ScnResource2 { - public const Single ExpectedUnknownResource = 0; + public const Single ExpectedUnknown = 0; - public Single ResourceGold; - public Single ResourceWood; - public Single ResourceFood; - public Single ResourceStone; - public Single ResourceOre; - public Single UnknownResource; + public Single Wood; + public Single Food; + public Single Gold; + public Single Stone; + public Single Ore; + public Single Unknown; public Single PopulationLimit; } diff --git a/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs b/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs index 1d4c71e..3a19c69 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs @@ -33,7 +33,7 @@ namespace AdrianKousz.GenieEngine result.GlobalVictory = MakeGlobalVictory(); result.Map = MakeMap(); result.PlayerSettings = result.PlayerSettings.NewList().Fill(Scenario.NumPlayers, MakePlayerSettings); - result.ResourceCopies = result.ResourceCopies.NewList().Fill(Scenario.NumPlayerSections - 1, MakeResourceCopy); + result.Resources2 = result.Resources2.NewList().Fill(Scenario.NumPlayerSections - 1, MakeResources2); result.PlayerSettings2 = result.PlayerSettings2.NewList().Fill(Scenario.NumPlayerSections - 1, MakePlayerSettings2); result.Units = MakeUnitList(Scenario.NumPlayerSections); } @@ -60,15 +60,15 @@ namespace AdrianKousz.GenieEngine return result; } - public Scenario.ScnResourceCopy MakeResourceCopy() + public Scenario.ScnResource2 MakeResources2() { // AOE2 standard - var result = new Scenario.ScnResourceCopy(); - result.UnknownResource = Scenario.ScnResourceCopy.ExpectedUnknownResource; - result.ResourceFood = 200; - result.ResourceWood = 200; - result.ResourceGold = 100; - result.ResourceStone = 200; + var result = new Scenario.ScnResource2(); + result.Unknown = Scenario.ScnResource2.ExpectedUnknown; + result.Food = 200; + result.Wood = 200; + result.Gold = 100; + result.Stone = 200; result.PopulationLimit = 75; return result; } diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs index 1ae13ad..98f34d1 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs @@ -222,17 +222,17 @@ namespace AdrianKousz.GenieEngine number = reader.ReadInt32(); - result.ResourceCopies = result.ResourceCopies.NewList().Fill(number - 1, factory.MakeResourceCopy); + result.Resources2 = result.Resources2.NewList().Fill(number - 1, factory.MakeResources2); - result.ResourceCopies.ForEach(x => { - x.ResourceFood = reader.ReadSingle(); - x.ResourceWood = reader.ReadSingle(); - x.ResourceGold = reader.ReadSingle(); - x.ResourceStone = reader.ReadSingle(); + result.Resources2.ForEach(x => { + x.Food = reader.ReadSingle(); + x.Wood = reader.ReadSingle(); + x.Gold = reader.ReadSingle(); + x.Stone = reader.ReadSingle(); if (Version >= 1.18f) { - x.ResourceOre = reader.ReadSingle(); + x.Ore = reader.ReadSingle(); if (Version < 1.3f) { - x.UnknownResource = reader.ReadSingle(); + x.Unknown = reader.ReadSingle(); } } if (Version >= 1.22f) { diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs index 972462f..6a59590 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs @@ -207,15 +207,15 @@ namespace AdrianKousz.GenieEngine writer.Write((System.Int32)value.Units.Count); - value.ResourceCopies.ForEach(x => { - writer.Write(x.ResourceFood); - writer.Write(x.ResourceWood); - writer.Write(x.ResourceGold); - writer.Write(x.ResourceStone); + value.Resources2.ForEach(x => { + writer.Write(x.Food); + writer.Write(x.Wood); + writer.Write(x.Gold); + writer.Write(x.Stone); if (Version >= 1.18f) { - writer.Write(x.ResourceOre); + writer.Write(x.Ore); if (Version < 1.3f) { - writer.Write(x.UnknownResource); + writer.Write(x.Unknown); } } if (Version >= 1.22f) { @@ -287,7 +287,7 @@ namespace AdrianKousz.GenieEngine { if (value.PlayerSettings.Count != Scenario.NumPlayers) throw new System.InvalidOperationException("PlayerSettings.Count != 16"); - if (value.Units.Count - 1 != value.ResourceCopies.Count) + if (value.Units.Count - 1 != value.Resources2.Count) throw new System.InvalidOperationException("Conflicting unit and resource copy count"); } } From d2960720bdd7420ba6bd795068b599db75df79fa Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 26 Apr 2016 15:17:34 +0200 Subject: [PATCH 9/9] Update command line app * bmp2map: Assign unit IDs * bmp2map: Check bitmap dimensions * bmp2map, convert: Change random tree frame code * convert: Insert values from src to ref, instead of vice-versa (more robust) * convert: Move buildings is better * convert: Small API changes * convert/dumpunits: Correct rounding for tile position underneath a unit * dumpunits: List player number for each unit --- src/cmdapp/src/BitmapHelpers.cs | 34 +++++++---- src/cmdapp/src/Bmp2MapCommand.cs | 2 +- src/cmdapp/src/ConvertCommand.cs | 39 +++++++++---- src/cmdapp/src/ConvertCommandHelper.cs | 81 ++++++++++++-------------- src/cmdapp/src/DumpunitsCommand.cs | 11 ++-- 5 files changed, 93 insertions(+), 74 deletions(-) diff --git a/src/cmdapp/src/BitmapHelpers.cs b/src/cmdapp/src/BitmapHelpers.cs index f4dc23a..0e6a026 100644 --- a/src/cmdapp/src/BitmapHelpers.cs +++ b/src/cmdapp/src/BitmapHelpers.cs @@ -9,25 +9,24 @@ namespace AdrianKousz.GenieEngine { public static class BitmapHelpers { - public static unsafe void FillMap(Scenario scn, Bitmap bmp, Bitmap bmp2) + public static unsafe void FillMap(Scenario scn, Bitmap bmp1, Bitmap bmp2) { - using (var ubmp = new UnsafeBitmap(bmp)) + using (var ubmp1 = new UnsafeBitmap(bmp1)) using (var ubmp2 = new UnsafeBitmap(bmp2)) { var factory = new ScnDefaultFactory(); - Check(ubmp); - Check(ubmp2); + EnsureValid(ubmp1, ubmp2); - var ptr = ubmp.Scan0; - var last = ptr + ubmp.Stride * ubmp.Height; + var ptr1 = ubmp1.Scan0; + var last1 = ptr1 + ubmp1.Stride * ubmp1.Height; var ptr2 = ubmp2.Scan0; var last2 = ptr2 + ubmp2.Stride * ubmp2.Height; var map = factory.MakeMap(); - map.SizeX = ubmp.Width; - map.SizeY = ubmp.Height; + map.SizeX = ubmp1.Width; + map.SizeY = ubmp1.Height; map.LinearTiles = new Scenario.ScnMap.Tile[map.SizeX * map.SizeY]; var gaiaunits = new List(); @@ -41,26 +40,37 @@ namespace AdrianKousz.GenieEngine treemapping[20] = 349; var i = 0; - while (ptr < last && ptr2 < last2) { - var treeid = treemapping[*ptr]; + var id = 0; + while (ptr1 < last1 && ptr2 < last2) { + var treeid = treemapping[*ptr1]; if (treeid != 0) { var unit = factory.MakeUnit(); var posy = i / map.SizeX; var posx = i - (posy * map.SizeX); + unit.Id = id++; unit.UnitId = treeid; unit.PosX = posx + 0.5f; unit.PosY = posy + 0.5f; - unit.Rotation = (short)Util.Math.Rand(0, 13); + unit.Rotation = unit.InitialFrame = (short)Util.Math.Rand(0, 14); gaiaunits.Add(unit); } - map.LinearTiles[i++] = new Scenario.ScnMap.Tile(*ptr++, (byte)(*ptr2++ / 37), 0); + map.LinearTiles[i++] = new Scenario.ScnMap.Tile(*ptr1++, (byte)(*ptr2++ / 40), 0); } + scn.NextId = id; scn.Map = map; scn.Units[0] = gaiaunits; } } + private static void EnsureValid(UnsafeBitmap ubmp1, UnsafeBitmap ubmp2) + { + if (ubmp1.Width != ubmp2.Width || ubmp1.Height != ubmp2.Height) + throw new ArgumentException("Bitmaps have unequal dimensions"); + Check(ubmp1); + Check(ubmp2); + } + private static void Check(UnsafeBitmap ubmp) { if (ubmp.PixelFormat != PixelFormat.Format8bppIndexed) diff --git a/src/cmdapp/src/Bmp2MapCommand.cs b/src/cmdapp/src/Bmp2MapCommand.cs index 935e959..42d94da 100644 --- a/src/cmdapp/src/Bmp2MapCommand.cs +++ b/src/cmdapp/src/Bmp2MapCommand.cs @@ -31,7 +31,7 @@ namespace AdrianKousz.GenieEngine + "\nTwo bitmaps need to be specified: One terrain map and one elevation map." + "\nBoth bitmaps need to be indexed or grayscale." + "\nThe index/gray values of the first bitmap are translated directly to a terrain ID." - + "\nThe index/gray values of the second bitmap are divided by 37 to generate elevations 0-6." + + "\nThe index/gray values of the second bitmap are divided by 40 to generate elevations 0-6." + "\n" + "\nParameters:" + "\n " diff --git a/src/cmdapp/src/ConvertCommand.cs b/src/cmdapp/src/ConvertCommand.cs index 199438a..69acae3 100644 --- a/src/cmdapp/src/ConvertCommand.cs +++ b/src/cmdapp/src/ConvertCommand.cs @@ -14,21 +14,38 @@ namespace AdrianKousz.GenieEngine var refscn = GenieFile.Deserialize(refstream); var srcscn = GenieFile.Deserialize(srcstream); - srcscn.VersionString = refscn.VersionString; - srcscn.VersionNumber = refscn.VersionNumber; - srcscn.RawIndividualVictory = refscn.RawIndividualVictory; - srcscn.RawDisables = refscn.RawDisables; - srcscn.RawRemaining = refscn.RawRemaining; + refscn.Filename = srcscn.Filename; + refscn.InstructionsUncompressed = srcscn.InstructionsUncompressed; + refscn.NextId = srcscn.NextId; + refscn.PlayerCount = srcscn.PlayerCount; - srcscn.PlayerSettings.ForEach(x => { - x.FilenameAI = x.FilenameCTY = x.FilenamePER = "RandomGame"; - x.ScriptAI = x.ScriptCTY = x.ScriptPER = ""; + refscn.PlayerSettings = srcscn.PlayerSettings; + refscn.Resources2 = srcscn.Resources2; + refscn.Messages = srcscn.Messages; + refscn.Cinematics = srcscn.Cinematics; + refscn.GlobalVictory = srcscn.GlobalVictory; + + refscn.Map = srcscn.Map; + refscn.Units = srcscn.Units; + + refscn.PlayerSettings.ForEach(x => { + x.NameStringID = -1; + x.FilenameAI = "RandomGame"; x.FilenameCTY = ""; x.FilenamePER = ""; + x.ScriptAI = ""; x.ScriptCTY = ""; x.ScriptPER = ""; }); - var converter = new CopymapConverter(); - converter.Convert(srcscn); + Enumerables.ForBoth(refscn.PlayerSettings2, srcscn.PlayerSettings2, (r, s) => { + r.Name = s.Name; + r.CameraX = s.CameraX; + r.CameraY = s.CameraY; + r.AlliedVictory = s.AlliedVictory; + r.Stances = s.Stances; + }); - GenieFile.Serialize(srcscn, outstream); + var converter = new ConvertCommandHelper(); + converter.Convert(refscn); + + GenieFile.Serialize(refscn, outstream); } } diff --git a/src/cmdapp/src/ConvertCommandHelper.cs b/src/cmdapp/src/ConvertCommandHelper.cs index d2d74f3..5404e62 100644 --- a/src/cmdapp/src/ConvertCommandHelper.cs +++ b/src/cmdapp/src/ConvertCommandHelper.cs @@ -4,44 +4,20 @@ using AdrianKousz.Util; namespace AdrianKousz.GenieEngine { - public class CopymapConverter + public class ConvertCommandHelper { public void Convert(Scenario scn) { - scn.Units = ChangeUnits_AOE1_AOE2(scn.Units); - MoveUnits_AOE1_AOE2(scn.Units); - ChangeTiles_AOE1_AOE2(scn.Units, scn.Map); - RandomizeTrees_AOE2(scn.Units); - } - - /** - * Some buildings are not the same size. - * They need to be moved by half a unit. - */ - private void MoveUnits_AOE1_AOE2(IList[] units) - { - var mapping = new int[] { - // Towers - 79, 199, 69, 278, - // Other Buildings - 109, 68, 103, - }; - units.ForEach(list => { - list.ForEach(unit => { - mapping.ForEach(buildingid => { - if (unit.UnitId == buildingid) { - unit.PosX -= 0.5f; - unit.PosY -= 0.5f; - } - }); - }); - }); + ChangeUnits_AOE1_AOE2(scn); + MoveUnits_AOE1_AOE2(scn); + ChangeTiles_AOE1_AOE2(scn); + RandomizeTrees_AOE2(scn); } /** * Simple mapping of unit IDs */ - private List[] ChangeUnits_AOE1_AOE2(IList[] units) + private void ChangeUnits_AOE1_AOE2(Scenario scn) { var mapping = new short[] { // Resources @@ -141,26 +117,43 @@ namespace AdrianKousz.GenieEngine 129, 129, }.ToDictionary(); - var result = units.Map(list => { - return list + scn.Units = scn.Units.Map(list => { + return (IList)list .Filter(unit => mapping.ContainsKey(unit.UnitId)) - .ForEach(unit => { - unit.UnitId = mapping[unit.UnitId]; - }).ToList(); - }).ToArray(); + .Map(unit => { + unit.UnitId = mapping[unit.UnitId]; + return unit; + }) + .ToList(); + }).ToList(); + } - return result; + /** + * Some buildings are not the same size. + * They need to be moved by half a unit. + */ + private void MoveUnits_AOE1_AOE2(Scenario scn) + { + var minus = new int[] { 79, 68, 562, }; + var plus = new int[] { 109, }; + scn.Units.ForEach(list => { + list.ForEach(unit => { + minus.ForEach(buildingid => { if (unit.UnitId != buildingid) return; unit.PosX -= 0.5f; unit.PosY -= 0.5f; }); + plus.ForEach(buildingid => { if (unit.UnitId != buildingid) return; unit.PosX += 0.5f; unit.PosY += 0.5f; }); + }); + }); } /** * Farms need to be converted including the underlying terrain. */ - private void ChangeTiles_AOE1_AOE2(IList[] units, Scenario.ScnMap map) + private void ChangeTiles_AOE1_AOE2(Scenario scn) { - units.ForEach(list => { + var map = scn.Map; + scn.Units.ForEach(list => { list.ForEach(unit => { - var posx = (int)(unit.PosX - 0.5); - var posy = (int)(unit.PosY - 0.5); + var posx = (int)unit.PosX; + var posy = (int)unit.PosY; var linearpos = posy * map.SizeX + posx; if (false) { // switch @@ -191,16 +184,16 @@ namespace AdrianKousz.GenieEngine * Forests would contain the same tree graphic * without this function */ - private void RandomizeTrees_AOE2(IList[] units) + private void RandomizeTrees_AOE2(Scenario scn) { var treeids = new int[] { 411, 351, 414, 350, 348, 349, }; - units.ForEach(list => { + scn.Units.ForEach(list => { list.ForEach(unit => { treeids.ForEach(treeid => { if (unit.UnitId == treeid) { - unit.Rotation = (short)Util.Math.Rand(0, 13); // Whats the maximum? + unit.Rotation = unit.InitialFrame = (short)Util.Math.Rand(0, 14); } }); }); diff --git a/src/cmdapp/src/DumpunitsCommand.cs b/src/cmdapp/src/DumpunitsCommand.cs index 958220e..a13f17c 100644 --- a/src/cmdapp/src/DumpunitsCommand.cs +++ b/src/cmdapp/src/DumpunitsCommand.cs @@ -14,18 +14,17 @@ namespace AdrianKousz.GenieEngine scn = GenieFile.Deserialize(input); } - Console.WriteLine("{0,-8} {1,-8} {2,-8} {3}", "ID", "UnitID", "TileID", "Position"); + Console.WriteLine("{0,-8} {1,-8} {2,-8} {3,-8} {4}", "Player", "ID", "UnitID", "TileID", "Position"); Console.WriteLine(); var i = 0; scn.Units.ForEach(list => { - Console.WriteLine("Units of player {0}:", i++); list.ForEach(unit => { - var tilex = (int)(unit.PosX - 0.5); - var tiley = (int)(unit.PosY - 0.5); + var tilex = (int)unit.PosX; + var tiley = (int)unit.PosY; var tile = scn.Map.LinearTiles[tiley * scn.Map.SizeX + tilex]; - Console.WriteLine("{0,-8} {1,-8} {2,-8} ({3,6:0.##},{4,6:0.##})", unit.Id, unit.UnitId, tile.Id, unit.PosX, unit.PosY); + Console.WriteLine("{0,-8} {1,-8} {2,-8} {3,-8} ({4,6:0.##},{5,6:0.##})", i, unit.Id, unit.UnitId, tile.Id, unit.PosX, unit.PosY); }); - Console.WriteLine(); + i++; }); }