Campaign support and bitmap to map conversion in application
* Full Campaign reading/writing support * Convert bitmaps to maps * Command arguments reordering: input and output are always first * Adapt usage of utils API
This commit is contained in:
parent
48929d1fbf
commit
9cc13f0e8d
10 changed files with 222 additions and 41 deletions
|
@ -19,15 +19,16 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\..\bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="src\Program.cs" />
|
||||
|
@ -42,6 +43,9 @@
|
|||
<Compile Include="src\ConvertCommand.cs" />
|
||||
<Compile Include="src\AddBitmapCommand.cs" />
|
||||
<Compile Include="src\DelBitmapCommand.cs" />
|
||||
<Compile Include="src\PackCommand.cs" />
|
||||
<Compile Include="src\Bmp2MapCommand.cs" />
|
||||
<Compile Include="src\BitmapHelpers.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
|
|
@ -10,8 +10,8 @@ namespace AdrianKousz.GenieEngine
|
|||
override public void Run()
|
||||
{
|
||||
using (var input = File.OpenRead(args[0]))
|
||||
using (var bmpstream = File.OpenRead(args[1]))
|
||||
using (var output = File.OpenWrite(args[2]))
|
||||
using (var output = File.OpenWrite(args[1]))
|
||||
using (var bmpstream = File.OpenRead(args[2]))
|
||||
{
|
||||
var scn = GenieFile.Deserialize<Scenario>(input);
|
||||
var bmp = (Bitmap)Image.FromStream(bmpstream);
|
||||
|
@ -41,7 +41,7 @@ namespace AdrianKousz.GenieEngine
|
|||
+ "\nAdditionally, a game-specific palette will be used to display the image."
|
||||
+ "\n"
|
||||
+ "\nParameters:"
|
||||
+ "\n<input scenario> <bitmap> <output scenario>"
|
||||
+ "\n<input scenario> <output scenario> <bitmap>"
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
73
src/cmdapp/src/BitmapHelpers.cs
Normal file
73
src/cmdapp/src/BitmapHelpers.cs
Normal file
|
@ -0,0 +1,73 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using AdrianKousz.Util;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public static class BitmapHelpers
|
||||
{
|
||||
public static unsafe void FillMap(Scenario scn, Bitmap bmp, Bitmap bmp2)
|
||||
{
|
||||
using (var ubmp = new UnsafeBitmap(bmp))
|
||||
using (var ubmp2 = new UnsafeBitmap(bmp2))
|
||||
{
|
||||
var factory = new ScnDefaultFactory();
|
||||
|
||||
Check(ubmp);
|
||||
Check(ubmp2);
|
||||
|
||||
var ptr = ubmp.Scan0;
|
||||
var last = ptr + ubmp.Stride * ubmp.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.LinearTiles = new Scenario.ScnMap.Tile[map.SizeX * map.SizeY];
|
||||
|
||||
var gaiaunits = new List<Scenario.ScnUnit>();
|
||||
|
||||
var treemapping = new short[256];
|
||||
treemapping[10] = 411;
|
||||
treemapping[13] = 351;
|
||||
treemapping[17] = 414;
|
||||
treemapping[18] = 348;
|
||||
treemapping[19] = 350;
|
||||
treemapping[20] = 349;
|
||||
|
||||
var i = 0;
|
||||
while (ptr < last && ptr2 < last2) {
|
||||
var treeid = treemapping[*ptr];
|
||||
if (treeid != 0) {
|
||||
var unit = factory.MakeUnit();
|
||||
var posy = i / map.SizeX;
|
||||
var posx = i - (posy * map.SizeX);
|
||||
unit.UnitId = treeid;
|
||||
unit.PosX = posx + 0.5f;
|
||||
unit.PosY = posy + 0.5f;
|
||||
unit.Rotation = (short)Util.Math.Rand(0, 13);
|
||||
gaiaunits.Add(unit);
|
||||
}
|
||||
map.LinearTiles[i++] = new Scenario.ScnMap.Tile(*ptr++, (byte)(*ptr2++ / 37), 0);
|
||||
}
|
||||
|
||||
scn.Map = map;
|
||||
scn.Units[0] = gaiaunits;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Check(UnsafeBitmap ubmp)
|
||||
{
|
||||
if (ubmp.PixelFormat != PixelFormat.Format8bppIndexed)
|
||||
throw new ArgumentException("Unsupported PixelFormat");
|
||||
if (ubmp.Stride != ubmp.Width)
|
||||
throw new NotImplementedException("bmpbit.Stride != bmpbit.Width");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
51
src/cmdapp/src/Bmp2MapCommand.cs
Normal file
51
src/cmdapp/src/Bmp2MapCommand.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using AdrianKousz.Util;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class Bmp2MapCommand : BaseCommand
|
||||
{
|
||||
override public void Run()
|
||||
{
|
||||
using (var srcstream = File.OpenRead(args[0]))
|
||||
using (var outstream = File.OpenWrite(args[1]))
|
||||
using (var bmpstream = File.OpenRead(args[2]))
|
||||
using (var bmp2stream = File.OpenRead(args[3]))
|
||||
{
|
||||
var bmp = (Bitmap)Image.FromStream(bmpstream);
|
||||
var bmp2 = (Bitmap)Image.FromStream(bmp2stream);
|
||||
|
||||
var scn = GenieFile.Deserialize<Scenario>(srcstream);
|
||||
BitmapHelpers.FillMap(scn, bmp, bmp2);
|
||||
GenieFile.Serialize(scn, outstream);
|
||||
}
|
||||
}
|
||||
|
||||
override public int GetArgumentCount()
|
||||
{
|
||||
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."
|
||||
+ "\n"
|
||||
+ "\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."
|
||||
+ "\n"
|
||||
+ "\nParameters:"
|
||||
+ "\n<input scenario> <output scenario> <terrain bitmap> <elevation bitmap>"
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,9 @@ namespace AdrianKousz.GenieEngine
|
|||
{
|
||||
override public void Run()
|
||||
{
|
||||
using (var refstream = File.OpenRead(args[0]))
|
||||
using (var srcstream = File.OpenRead(args[1]))
|
||||
using (var outstream = File.OpenWrite(args[2]))
|
||||
using (var srcstream = File.OpenRead(args[0]))
|
||||
using (var outstream = File.OpenWrite(args[1]))
|
||||
using (var refstream = File.OpenRead(args[2]))
|
||||
{
|
||||
var refscn = GenieFile.Deserialize<Scenario>(refstream);
|
||||
var srcscn = GenieFile.Deserialize<Scenario>(srcstream);
|
||||
|
@ -50,7 +50,7 @@ namespace AdrianKousz.GenieEngine
|
|||
+ "\nThe converter needs an existing AOE2 scenario to start with."
|
||||
+ "\n"
|
||||
+ "\nParameters:"
|
||||
+ "\n<AOE2 reference scenario> <AOE1 scenario> <output scenario>"
|
||||
+ "\n<AOE1 scenario> <output scenario> <AOE2 reference scenario>"
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace AdrianKousz.GenieEngine
|
|||
// Other Buildings
|
||||
109, 68, 103,
|
||||
};
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
mapping.ForEach((k, buildingid) => {
|
||||
units.ForEach(list => {
|
||||
list.ForEach(unit => {
|
||||
mapping.ForEach(buildingid => {
|
||||
if (unit.UnitId == buildingid) {
|
||||
unit.PosX -= 0.5f;
|
||||
unit.PosY -= 0.5f;
|
||||
|
@ -43,7 +43,7 @@ namespace AdrianKousz.GenieEngine
|
|||
*/
|
||||
private List<Scenario.ScnUnit>[] ChangeUnits_AOE1_AOE2(IList<Scenario.ScnUnit>[] units)
|
||||
{
|
||||
var array = new int[] {
|
||||
var mapping = new short[] {
|
||||
// Resources
|
||||
66, 66,
|
||||
59, 59,
|
||||
|
@ -139,22 +139,15 @@ namespace AdrianKousz.GenieEngine
|
|||
114, 114,
|
||||
121, 121,
|
||||
129, 129,
|
||||
};
|
||||
var mapping = new Dictionary<short, short>();
|
||||
var ai = 0;
|
||||
while (ai < array.Length)
|
||||
mapping.Add((short)array[ai++], (short)array[ai++]);
|
||||
}.ToDictionary();
|
||||
|
||||
var result = new List<Scenario.ScnUnit>[Scenario.NumPlayerSections].Fill();
|
||||
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
if (mapping.ContainsKey(unit.UnitId)) {
|
||||
unit.UnitId = mapping[unit.UnitId];
|
||||
result[i].Add(unit);
|
||||
}
|
||||
});
|
||||
});
|
||||
var result = units.Map(list => {
|
||||
return list
|
||||
.Filter(unit => mapping.ContainsKey(unit.UnitId))
|
||||
.ForEach(unit => {
|
||||
unit.UnitId = mapping[unit.UnitId];
|
||||
}).ToList();
|
||||
}).ToArray();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -164,8 +157,8 @@ namespace AdrianKousz.GenieEngine
|
|||
*/
|
||||
private void ChangeTiles_AOE1_AOE2(IList<Scenario.ScnUnit>[] units, Scenario.ScnMap map)
|
||||
{
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
units.ForEach(list => {
|
||||
list.ForEach(unit => {
|
||||
var posx = (int)(unit.PosX - 0.5);
|
||||
var posy = (int)(unit.PosY - 0.5);
|
||||
var linearpos = posy * map.SizeX + posx;
|
||||
|
@ -203,12 +196,11 @@ namespace AdrianKousz.GenieEngine
|
|||
var treeids = new int[] {
|
||||
411, 351, 414, 350, 348, 349,
|
||||
};
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
treeids.ForEach((k, treeid) => {
|
||||
units.ForEach(list => {
|
||||
list.ForEach(unit => {
|
||||
treeids.ForEach(treeid => {
|
||||
if (unit.UnitId == treeid) {
|
||||
unit.InitialFrame = (short)Util.Math.Rand(0, 13); // Whats the maximum?
|
||||
unit.Rotation = unit.InitialFrame;
|
||||
unit.Rotation = (short)Util.Math.Rand(0, 13); // Whats the maximum?
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,9 +17,10 @@ namespace AdrianKousz.GenieEngine
|
|||
|
||||
Console.WriteLine("{0,-8} {1,-8} {2,-8} {3}", "ID", "UnitID", "TileID", "Position");
|
||||
Console.WriteLine();
|
||||
scn.Units.ForEach((i, list) => {
|
||||
Console.WriteLine("Units of player {0}:", i);
|
||||
list.ForEach((j, unit) => {
|
||||
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 tile = scn.Map.LinearTiles[tiley * scn.Map.SizeX + tilex];
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using AdrianKousz.Util;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
|
@ -6,9 +8,17 @@ namespace AdrianKousz.GenieEngine
|
|||
{
|
||||
override public void Run()
|
||||
{
|
||||
using (var file = File.OpenRead(args[0])) {
|
||||
var reader = new CpnReader(file);
|
||||
reader.ExtractFiles();
|
||||
using (var file = File.OpenRead(args[0]))
|
||||
{
|
||||
var cpn = GenieFile.Deserialize<Campaign>(file);
|
||||
Console.WriteLine("Extracting \"{0}\"...", cpn.Name);
|
||||
cpn.Files.ForEach(x => {
|
||||
using (var outfile = File.OpenWrite(x.Filename))
|
||||
{
|
||||
Console.WriteLine("Extracting \"{0}\" to \"{1}\"...", x.Name, x.Filename);
|
||||
outfile.Write(x.RawData);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +29,7 @@ namespace AdrianKousz.GenieEngine
|
|||
|
||||
override public string GetDescription()
|
||||
{
|
||||
return "Extract scenarios from campaign file";
|
||||
return "Extract files from campaign file";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
47
src/cmdapp/src/PackCommand.cs
Normal file
47
src/cmdapp/src/PackCommand.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using AdrianKousz.Util;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class PackCommand : BaseCommand
|
||||
{
|
||||
override public void Run()
|
||||
{
|
||||
var files = new List<Campaign.CpnFile>();
|
||||
for (var i = 2; i < args.Length; i++) {
|
||||
var file = new Campaign.CpnFile();
|
||||
file.Filename = args[i];
|
||||
file.Name = Path.GetFileNameWithoutExtension(file.Filename);
|
||||
using (var stream = File.OpenRead(file.Filename))
|
||||
using (var memorystream = new MemoryStream())
|
||||
{
|
||||
stream.CopyTo(memorystream);
|
||||
file.RawData = memorystream.ToArray();
|
||||
}
|
||||
files.Add(file);
|
||||
}
|
||||
|
||||
var cpn = new Campaign();
|
||||
cpn.Files = files;
|
||||
cpn.Name = args[1];
|
||||
cpn.Version = "1.00";
|
||||
|
||||
using (var file = File.OpenWrite(args[0]))
|
||||
{
|
||||
GenieFile.Serialize(cpn, file);
|
||||
}
|
||||
}
|
||||
|
||||
override public int GetArgumentCount()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
override public string GetDescription()
|
||||
{
|
||||
return "Pack files into a campaign file";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ namespace AdrianKousz.GenieEngine
|
|||
public static void Main(string[] args)
|
||||
{
|
||||
System.Threading.Thread.CurrentThread.Name = "main";
|
||||
Log.SetUncaughtExceptionHandler();
|
||||
|
||||
if (System.Diagnostics.Debugger.IsAttached) {
|
||||
debug();
|
||||
|
@ -26,6 +27,7 @@ namespace AdrianKousz.GenieEngine
|
|||
{
|
||||
var result = new Dictionary<string, ICommand<string[]>>();
|
||||
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());
|
||||
|
@ -34,6 +36,7 @@ namespace AdrianKousz.GenieEngine
|
|||
result.Add("fromjson", new FromJsonCommand());
|
||||
result.Add("dumpunits", new DumpunitsCommand());
|
||||
result.Add("extract", new ExtractCommand());
|
||||
result.Add("pack", new PackCommand());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue