From 982dc159cfa236acad46d171693aa07b1bf22005 Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 18 Feb 2016 02:04:49 +0100 Subject: [PATCH 1/2] Library refactoring 2 * IScnFactory change * Deep or shallow generation in default factory * Some fixes in ScnSerializerWriter --- .../AdrianKousz.GenieEngine/IScnFactory.cs | 6 ++-- .../ScnDefaultFactory.cs | 20 ++++++++---- .../ScnSerializerWriter.cs | 31 +++++++++++-------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs b/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs index 76a9590..2a36fe3 100644 --- a/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs +++ b/src/lib/AdrianKousz.GenieEngine/IScnFactory.cs @@ -9,9 +9,9 @@ namespace AdrianKousz.GenieEngine Scenario.ScnPlayerSettings MakePlayerSettings(); Scenario.ScnMessages MakeMessages(); Scenario.ScnCinematics MakeCinematics(); - Scenario.ScnGlobalVictory MakeGlobalVictoryInfo(); - Scenario.ScnResourceCopy MakeResourceCopyInfo(); + Scenario.ScnGlobalVictory MakeGlobalVictory(); + Scenario.ScnResourceCopy MakeResourceCopy(); Scenario.ScnMap MakeMap(); - Scenario.ScnUnit MakeUnitInfo(); + Scenario.ScnUnit MakeUnit(); } } diff --git a/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs b/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs index 8c10e7c..b346e09 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnDefaultFactory.cs @@ -27,10 +27,19 @@ namespace AdrianKousz.GenieEngine result.Timestamp = System.DateTime.Now; result.PlayerCount = 2; - result.Messages = MakeMessages(); - result.Cinematics = MakeCinematics(); - result.GlobalVictory = MakeGlobalVictory(); - result.Map = MakeMap(); + if (deep) { + result.Messages = MakeMessages(); + 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(); + + } return result; } @@ -53,8 +62,7 @@ namespace AdrianKousz.GenieEngine result.ResourceGold = 100; result.ResourceStone = 100; result.StartingAge = -1; - result.Diplomacy = new int[Scenario.NumPlayers]; - result.Diplomacy.Fill(3); + result.Diplomacy = new int[Scenario.NumPlayers].Fill(3); return result; } diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs index 706f78f..5212be2 100644 --- a/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerWriter.cs @@ -36,7 +36,7 @@ namespace AdrianKousz.GenieEngine var originalWriter = writer; var compressedPart = new MemoryStream(); var comp = new DeflateStream(compressedPart, CompressionMode.Compress); - writer = new ExtendedBinaryWriter(comp, writer.Encoding); + writer = new ExtendedBinaryWriter(comp, originalWriter.Encoding); writer.Write(value.NextId); writer.Write(value.VersionNumber); @@ -54,10 +54,10 @@ namespace AdrianKousz.GenieEngine } value.PlayerSettings.ForEach(x => { - writer.WriteStringPadded(x.Active); - writer.WriteStringPadded(x.Human); - writer.WriteStringPadded(x.Civ); - writer.WriteStringPadded(x.UnknownInfo); + writer.Write(x.Active); + writer.Write(x.Human); + writer.Write(x.Civ); + writer.Write(x.UnknownInfo); }); writer.Write(value.Unknown3); @@ -125,11 +125,13 @@ namespace AdrianKousz.GenieEngine writer.WriteStringRaw(x.ScriptPER); }); - value.PlayerSettings.ForEach(x => { - writer.Write(x.AIType); - }); + if (Version >= 1.18f) { + value.PlayerSettings.ForEach(x => { + writer.Write(x.AIType); + }); + } - WriteSeperator(writer, "Resources"); + WriteSeparator(writer, "Resources"); // Resources @@ -146,7 +148,7 @@ namespace AdrianKousz.GenieEngine } }); - WriteSeperator(writer, "Victory"); + WriteSeparator(writer, "Victory"); // Diplomacy @@ -171,7 +173,7 @@ namespace AdrianKousz.GenieEngine writer.Write(value.RawIndividualVictory); - WriteSeperator(writer, "Player Environment"); + WriteSeparator(writer, "Player Environment"); value.PlayerSettings.ForEach(x => { writer.Write(x.AlliedVictory); @@ -183,7 +185,7 @@ namespace AdrianKousz.GenieEngine writer.Write(x.StartingAge); }); - WriteSeperator(writer, "Map"); + WriteSeparator(writer, "Map"); // Map @@ -246,12 +248,15 @@ namespace AdrianKousz.GenieEngine writer.Write(value.RawRemaining); + // End of writing + writer.Dispose(); comp.Dispose(); + compressedPart.Dispose(); originalWriter.Write(compressedPart.ToArray()); } - public void WriteSeperator(ExtendedBinaryWriter writer, string name) + public void WriteSeparator(ExtendedBinaryWriter writer, string name) { writer.Write(Scenario.Separator); } From 7694fb0c030db92f92d8f0e9d07265756e4dae70 Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 18 Feb 2016 02:05:30 +0100 Subject: [PATCH 2/2] Library refactoring 3 Add ScnSerializerReader --- .../ScnSerializerReader.cs | 292 ++++++++++++++++++ src/lib/GenieEngineLib.csproj | 1 + 2 files changed, 293 insertions(+) create mode 100644 src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs diff --git a/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs new file mode 100644 index 0000000..7e6ce29 --- /dev/null +++ b/src/lib/AdrianKousz.GenieEngine/ScnSerializerReader.cs @@ -0,0 +1,292 @@ +using System.IO; +using System.IO.Compression; +using System.Collections.Generic; +using AdrianKousz.Util; + +namespace AdrianKousz.GenieEngine +{ + public class ScnSerializerReader + { + private IScnFactory factory; + + public static ScnSerializerReader CreateDefault() + { + var factory = new ScnDefaultFactory(); + return new ScnSerializerReader(factory); + } + + private ScnSerializerReader(IScnFactory factory) + { + this.factory = factory; + } + + public Scenario ReadScenario(ExtendedBinaryReader reader) + { + var Version = 0f; + var number = 0; + var result = factory is ScnDefaultFactory + ? factory.MakeScenario(false) + : factory.MakeScenario(); + + // Uncompressed header + + result.VersionString = reader.ReadString(4); + reader.ReadInt32(); // Header Length + result.Unknown1 = reader.ReadInt32(); + result.Timestamp = DateTimes.FromUnixTime(reader.ReadInt32()); + result.InstructionsUncompressed = reader.ReadZStringInt32(); + result.Unknown2 = reader.ReadInt32(); + result.PlayerCount = reader.ReadInt32(); + + // Compression starts + + var originalReader = reader; + var compressedPart = new NonDisposingStreamWrapper(reader.BaseStream); + var comp = new DeflateStream(compressedPart, CompressionMode.Decompress); + reader = new ExtendedBinaryReader(comp, originalReader.Encoding); + + result.NextId = reader.ReadInt32(); + result.VersionNumber = reader.ReadSingle(); + Version = result.VersionNumber; + + result.PlayerSettings = new Scenario.ScnPlayerSettings[Scenario.NumPlayers] + .Fill(factory.MakePlayerSettings); + + // PlayerSettings 1 + + result.PlayerSettings.ForEach(x => { + x.Name = reader.ReadZString(256); + }); + + if (Version >= 1.18f) { + result.PlayerSettings.ForEach(x => { + x.NameStringID = reader.ReadInt32(); + }); + } + + result.PlayerSettings.ForEach(x => { + x.Active = reader.ReadBoolean(); + x.Human = reader.ReadBoolean(); + x.Civ = reader.ReadInt32(); + x.UnknownInfo = reader.ReadInt32(); + }); + + result.Unknown3 = reader.ReadInt32(); + result.Unknown4 = reader.ReadSByte(); + result.Unknown5 = reader.ReadSingle(); + + result.Filename = reader.ReadStringInt16(); + + // Messages + + result.Messages = factory.MakeMessages(); + + if (Version >= 1.18f) { + result.Messages.InstructionsStringID = reader.ReadInt32(); + result.Messages.HintsStringID = reader.ReadInt32(); + result.Messages.VictoryStringID = reader.ReadInt32(); + result.Messages.LossStringID = reader.ReadInt32(); + result.Messages.HistoryStringID = reader.ReadInt32(); + } + if (Version >= 1.22f) { + result.Messages.ScoutsStringID = reader.ReadInt32(); + } + + result.Messages.Instructions = reader.ReadZStringInt16(); + result.Messages.Hints = reader.ReadZStringInt16(); + result.Messages.Victory = reader.ReadZStringInt16(); + result.Messages.Loss = reader.ReadZStringInt16(); + result.Messages.History = reader.ReadZStringInt16(); + if (Version >= 1.22f) { + result.Messages.Scouts = reader.ReadZStringInt16(); + } + + // Cinematics + + result.Cinematics = factory.MakeCinematics(); + + result.Cinematics.FilenamePregame = reader.ReadStringInt16(); + result.Cinematics.FilenameVictory = reader.ReadStringInt16(); + result.Cinematics.FilenameLoss = reader.ReadStringInt16(); + result.Cinematics.FilenameBitmap = reader.ReadStringInt16(); + + var hasBitmap = reader.ReadBoolean(); + + result.Cinematics.BitmapWidth = reader.ReadInt32(); + result.Cinematics.BitmapHeight = reader.ReadInt32(); + result.Cinematics.BitmapUnknown = reader.ReadInt16(); + + if (hasBitmap) { + result.Cinematics.RawBitmap = BitmapUtil.ReadRawBitmap(reader.BaseStream); + } + + // PlayerSettings 2 + + result.PlayerSettings.ForEach(x => { + x.FilenameAI = reader.ReadStringInt16(); + x.FilenameCTY = reader.ReadStringInt16(); + x.FilenamePER = reader.ReadStringInt16(); + }); + + result.PlayerSettings.ForEach(x => { + var l1 = reader.ReadInt32(); + var l2 = reader.ReadInt32(); + var l3 = reader.ReadInt32(); + x.ScriptAI = reader.ReadString(l1); + x.ScriptCTY = reader.ReadString(l2); + x.ScriptPER = reader.ReadString(l3); + }); + + if (Version >= 1.18f) { + result.PlayerSettings.ForEach(x => { + x.AIType = reader.ReadSByte(); + }); + } + + ReadSeparator(reader, "Resources"); + + // Resources + + result.PlayerSettings.ForEach(x => { + x.ResourceGold = reader.ReadInt32(); + x.ResourceWood = reader.ReadInt32(); + x.ResourceFood = reader.ReadInt32(); + x.ResourceStone = reader.ReadInt32(); + if (Version >= 1.18f) { + x.ResourceOre = reader.ReadInt32(); + if (Version < 1.3f) { + x.UnknownResource = reader.ReadInt32(); + } + } + }); + + ReadSeparator(reader, "Victory"); + + // Diplomacy + + result.GlobalVictory = factory.MakeGlobalVictory(); + + result.GlobalVictory.RequireConquest = reader.ReadBoolean(); + 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.Mode = reader.ReadInt32(); + result.GlobalVictory.Score = reader.ReadInt32(); + result.GlobalVictory.Time = reader.ReadInt32(); + + // PlayerSettings 3 + + result.PlayerSettings.ForEach(x => { + x.Diplomacy = new int[Scenario.NumPlayers].Fill(reader.ReadInt32()); + }); + + result.RawIndividualVictory = reader.ReadBytes(11520); + + ReadSeparator(reader, "Player Environment"); + + result.PlayerSettings.ForEach(x => { + x.AlliedVictory = reader.ReadInt32(); + }); + + if (Version >= 1.15f) number = (Scenario.NumPlayers * ( 20 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/; + if (Version >= 1.18f) number = (Scenario.NumPlayers * (3 /*Lengths*/ + 80 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/; + if (Version >= 1.30f) number = (Scenario.NumPlayers * (3 /*Lengths*/ + 180 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/; + result.RawDisables = reader.ReadBytes(number); + + result.PlayerSettings.ForEach(x => { + x.StartingAge = reader.ReadInt32(); + }); + + ReadSeparator("Map"); + + // Map + + result.Map = factory.MakeMap(); + + if (Version >= 1.18f) { + result.Map.CameraX = reader.ReadInt32(); + result.Map.CameraY = reader.ReadInt32(); + } + if (Version >= 1.22f) { + result.Map.GeneratorId = reader.ReadInt32(); + } + result.Map.SizeX = reader.ReadInt32(); + result.Map.SizeY = reader.ReadInt32(); + + result.Map.LinearTiles = new Scenario.ScnMap.Tile[result.Map.SizeX * result.Map.SizeY] + .Fill(() => new Scenario.ScnMap.Tile(reader.ReadSByte(), reader.ReadSByte(), reader.ReadSByte())); + + // ResourceCopies + + number = reader.ReadInt32(); + + result.ResourceCopies = new Scenario.ScnResourceCopy[number - 1] + .Fill(factory.MakeResourceCopy); + + result.ResourceCopies.ForEach(x => { + x.ResourceFood = reader.ReadSingle(); + x.ResourceWood = reader.ReadSingle(); + x.ResourceGold = reader.ReadSingle(); + x.ResourceStone = reader.ReadSingle(); + if (Version >= 1.18f) { + x.ResourceOre = reader.ReadInt32(); + if (Version < 1.3f) { + x.UnknownResource = reader.ReadInt32(); + } + } + if (Version >= 1.22f) { + x.PopulationLimit = reader.ReadSingle(); + } + }); + + // Units + + result.Units = new List[number].Fill(); + + result.Units.ForEach(x => { + var count = reader.ReadInt32(); + x.Fill(() => { + var unit = factory.MakeUnit(); + unit.PosX = reader.ReadSingle(); + unit.PosY = reader.ReadSingle(); + unit.Unknown1 = reader.ReadSingle(); + unit.Id = reader.ReadInt32(); + unit.UnitId = reader.ReadInt16(); + unit.Unknown2 = reader.ReadSByte(); + unit.Rotation = reader.ReadSingle(); + if (Version >= 1.18f) { + unit.InitialFrame = reader.ReadInt16(); + unit.GarrisonnedInId = reader.ReadInt32(); + } + return unit; + }, count); + }); + + // More Player Settings and Triggers + + var bytestream = new MemoryStream(); + reader.BaseStream.CopyTo(bytestream); + result.RawRemaining = bytestream.ToArray(); + + // End of reading + + reader.Dispose(); + comp.Dispose(); + compressedPart.Dispose(); + return result; + } + + public void ReadSeparator(ExtendedBinaryReader reader, string name) { + int v = reader.ReadInt32(); + if (v != Scenario.Separator) { + var msg = "Separator \"{0}\" = {1}"; + msg = string.Format(msg, name, v); + throw new InvalidDataException(msg); + } + } + } +} + diff --git a/src/lib/GenieEngineLib.csproj b/src/lib/GenieEngineLib.csproj index 4b7bceb..816f6d7 100644 --- a/src/lib/GenieEngineLib.csproj +++ b/src/lib/GenieEngineLib.csproj @@ -43,6 +43,7 @@ +