Compare commits
2 Commits
3cb2c123f2
...
7694fb0c03
Author | SHA1 | Date |
---|---|---|
Adrian | 7694fb0c03 | |
Adrian | 982dc159cf |
|
@ -9,9 +9,9 @@ namespace AdrianKousz.GenieEngine
|
||||||
Scenario.ScnPlayerSettings MakePlayerSettings();
|
Scenario.ScnPlayerSettings MakePlayerSettings();
|
||||||
Scenario.ScnMessages MakeMessages();
|
Scenario.ScnMessages MakeMessages();
|
||||||
Scenario.ScnCinematics MakeCinematics();
|
Scenario.ScnCinematics MakeCinematics();
|
||||||
Scenario.ScnGlobalVictory MakeGlobalVictoryInfo();
|
Scenario.ScnGlobalVictory MakeGlobalVictory();
|
||||||
Scenario.ScnResourceCopy MakeResourceCopyInfo();
|
Scenario.ScnResourceCopy MakeResourceCopy();
|
||||||
Scenario.ScnMap MakeMap();
|
Scenario.ScnMap MakeMap();
|
||||||
Scenario.ScnUnit MakeUnitInfo();
|
Scenario.ScnUnit MakeUnit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,19 @@ namespace AdrianKousz.GenieEngine
|
||||||
result.Timestamp = System.DateTime.Now;
|
result.Timestamp = System.DateTime.Now;
|
||||||
result.PlayerCount = 2;
|
result.PlayerCount = 2;
|
||||||
|
|
||||||
|
if (deep) {
|
||||||
result.Messages = MakeMessages();
|
result.Messages = MakeMessages();
|
||||||
result.Cinematics = MakeCinematics();
|
result.Cinematics = MakeCinematics();
|
||||||
result.GlobalVictory = MakeGlobalVictory();
|
result.GlobalVictory = MakeGlobalVictory();
|
||||||
result.Map = MakeMap();
|
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.ScnUnit>[Scenario.NumPlayerSections]
|
||||||
|
.Fill();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -53,8 +62,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
result.ResourceGold = 100;
|
result.ResourceGold = 100;
|
||||||
result.ResourceStone = 100;
|
result.ResourceStone = 100;
|
||||||
result.StartingAge = -1;
|
result.StartingAge = -1;
|
||||||
result.Diplomacy = new int[Scenario.NumPlayers];
|
result.Diplomacy = new int[Scenario.NumPlayers].Fill(3);
|
||||||
result.Diplomacy.Fill(3);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<Scenario.ScnUnit>[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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
var originalWriter = writer;
|
var originalWriter = writer;
|
||||||
var compressedPart = new MemoryStream();
|
var compressedPart = new MemoryStream();
|
||||||
var comp = new DeflateStream(compressedPart, CompressionMode.Compress);
|
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.NextId);
|
||||||
writer.Write(value.VersionNumber);
|
writer.Write(value.VersionNumber);
|
||||||
|
@ -54,10 +54,10 @@ namespace AdrianKousz.GenieEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
value.PlayerSettings.ForEach(x => {
|
value.PlayerSettings.ForEach(x => {
|
||||||
writer.WriteStringPadded(x.Active);
|
writer.Write(x.Active);
|
||||||
writer.WriteStringPadded(x.Human);
|
writer.Write(x.Human);
|
||||||
writer.WriteStringPadded(x.Civ);
|
writer.Write(x.Civ);
|
||||||
writer.WriteStringPadded(x.UnknownInfo);
|
writer.Write(x.UnknownInfo);
|
||||||
});
|
});
|
||||||
|
|
||||||
writer.Write(value.Unknown3);
|
writer.Write(value.Unknown3);
|
||||||
|
@ -125,11 +125,13 @@ namespace AdrianKousz.GenieEngine
|
||||||
writer.WriteStringRaw(x.ScriptPER);
|
writer.WriteStringRaw(x.ScriptPER);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (Version >= 1.18f) {
|
||||||
value.PlayerSettings.ForEach(x => {
|
value.PlayerSettings.ForEach(x => {
|
||||||
writer.Write(x.AIType);
|
writer.Write(x.AIType);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
WriteSeperator(writer, "Resources");
|
WriteSeparator(writer, "Resources");
|
||||||
|
|
||||||
// Resources
|
// Resources
|
||||||
|
|
||||||
|
@ -146,7 +148,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
WriteSeperator(writer, "Victory");
|
WriteSeparator(writer, "Victory");
|
||||||
|
|
||||||
// Diplomacy
|
// Diplomacy
|
||||||
|
|
||||||
|
@ -171,7 +173,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
writer.Write(value.RawIndividualVictory);
|
writer.Write(value.RawIndividualVictory);
|
||||||
|
|
||||||
WriteSeperator(writer, "Player Environment");
|
WriteSeparator(writer, "Player Environment");
|
||||||
|
|
||||||
value.PlayerSettings.ForEach(x => {
|
value.PlayerSettings.ForEach(x => {
|
||||||
writer.Write(x.AlliedVictory);
|
writer.Write(x.AlliedVictory);
|
||||||
|
@ -183,7 +185,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
writer.Write(x.StartingAge);
|
writer.Write(x.StartingAge);
|
||||||
});
|
});
|
||||||
|
|
||||||
WriteSeperator(writer, "Map");
|
WriteSeparator(writer, "Map");
|
||||||
|
|
||||||
// Map
|
// Map
|
||||||
|
|
||||||
|
@ -246,12 +248,15 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
writer.Write(value.RawRemaining);
|
writer.Write(value.RawRemaining);
|
||||||
|
|
||||||
|
// End of writing
|
||||||
|
|
||||||
writer.Dispose();
|
writer.Dispose();
|
||||||
comp.Dispose();
|
comp.Dispose();
|
||||||
|
compressedPart.Dispose();
|
||||||
originalWriter.Write(compressedPart.ToArray());
|
originalWriter.Write(compressedPart.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteSeperator(ExtendedBinaryWriter writer, string name)
|
public void WriteSeparator(ExtendedBinaryWriter writer, string name)
|
||||||
{
|
{
|
||||||
writer.Write(Scenario.Separator);
|
writer.Write(Scenario.Separator);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<Compile Include="AdrianKousz.GenieEngine\IScnFactory.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\IScnFactory.cs" />
|
||||||
<Compile Include="AdrianKousz.GenieEngine\ScnSerializerWriter.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\ScnSerializerWriter.cs" />
|
||||||
<Compile Include="AdrianKousz.GenieEngine\Scenario.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\Scenario.cs" />
|
||||||
|
<Compile Include="AdrianKousz.GenieEngine\ScnSerializerReader.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue