mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-12-27 04:26:29 -05:00
Started writing map data logic.
This commit is contained in:
parent
c4fac82bc3
commit
6c2847e4b3
15
OpenDiablo2.Common/Interfaces/IEngineDataManager.cs
Normal file
15
OpenDiablo2.Common/Interfaces/IEngineDataManager.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using OpenDiablo2.Common.Models;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Common.Interfaces
|
||||||
|
{
|
||||||
|
public interface IEngineDataManager
|
||||||
|
{
|
||||||
|
List<LevelPreset> LevelPresets { get; }
|
||||||
|
List<LevelType> LevelTypes { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,8 @@ namespace OpenDiablo2.Common.Interfaces
|
|||||||
{
|
{
|
||||||
ImageSet GetImageSet(string resourcePath);
|
ImageSet GetImageSet(string resourcePath);
|
||||||
MPQFont GetMPQFont(string resourcePath);
|
MPQFont GetMPQFont(string resourcePath);
|
||||||
|
MPQDS1 GetMPQDS1(string resourcePath, int definition, int act);
|
||||||
|
MPQDT1 GetMPQDT1(string resourcePath);
|
||||||
Palette GetPalette(string paletteName);
|
Palette GetPalette(string paletteName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
69
OpenDiablo2.Common/Models/LevelPreset.cs
Normal file
69
OpenDiablo2.Common/Models/LevelPreset.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Common.Models
|
||||||
|
{
|
||||||
|
//
|
||||||
|
public sealed class LevelPreset
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Def { get; set; }
|
||||||
|
public int LevelId { get; set; }
|
||||||
|
public bool Populate { get; set; }
|
||||||
|
public int Logicals { get; set; }
|
||||||
|
public int Outdoors { get; set; }
|
||||||
|
public int Animate { get; set; }
|
||||||
|
public int KillEdge { get; set; }
|
||||||
|
public int FillBlanks { get; set; }
|
||||||
|
public int SizeX { get; set; }
|
||||||
|
public int SizeY { get; set; }
|
||||||
|
public int AutoMap { get; set; }
|
||||||
|
public int Scan { get; set; }
|
||||||
|
public int Pops { get; set; }
|
||||||
|
public int PopPad { get; set; }
|
||||||
|
public int Files { get; set; }
|
||||||
|
public string File1 { get; set; }
|
||||||
|
public string File2 { get; set; }
|
||||||
|
public string File3 { get; set; }
|
||||||
|
public string File4 { get; set; }
|
||||||
|
public string File5 { get; set; }
|
||||||
|
public string File6 { get; set; }
|
||||||
|
public UInt32 Dt1Mask { get; set; }
|
||||||
|
public bool Beta { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LevelPresetHelper
|
||||||
|
{
|
||||||
|
public static LevelPreset ToLevelPreset(this string[] row)
|
||||||
|
=> new LevelPreset
|
||||||
|
{
|
||||||
|
Name = row[0],
|
||||||
|
Def = Convert.ToInt32(row[1]),
|
||||||
|
LevelId = row[2] == "#REF!" ? 0 : Convert.ToInt32(row[2]), // TODO: Why is this a thing?
|
||||||
|
Populate = Convert.ToInt32(row[3]) == 1,
|
||||||
|
Logicals = Convert.ToInt32(row[4]),
|
||||||
|
Outdoors = Convert.ToInt32(row[5]),
|
||||||
|
Animate = Convert.ToInt32(row[6]),
|
||||||
|
KillEdge = Convert.ToInt32(row[7]),
|
||||||
|
FillBlanks = Convert.ToInt32(row[8]),
|
||||||
|
SizeX = Convert.ToInt32(row[9]),
|
||||||
|
SizeY = Convert.ToInt32(row[10]),
|
||||||
|
AutoMap = Convert.ToInt32(row[11]),
|
||||||
|
Scan = Convert.ToInt32(row[12]),
|
||||||
|
Pops = Convert.ToInt32(row[13]),
|
||||||
|
PopPad = Convert.ToInt32(row[14]),
|
||||||
|
Files = Convert.ToInt32(row[15]),
|
||||||
|
File1 = row[16],
|
||||||
|
File2 = row[17],
|
||||||
|
File3 = row[18],
|
||||||
|
File4 = row[19],
|
||||||
|
File5 = row[20],
|
||||||
|
File6 = row[21],
|
||||||
|
Dt1Mask = Convert.ToUInt32(row[22]),
|
||||||
|
Beta = Convert.ToInt32(row[23]) == 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
39
OpenDiablo2.Common/Models/LevelType.cs
Normal file
39
OpenDiablo2.Common/Models/LevelType.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Common.Models
|
||||||
|
{
|
||||||
|
public sealed class LevelType
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string[] File { get; set; } = new string[32];
|
||||||
|
public bool Beta { get; set; }
|
||||||
|
public int Act { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LevelTypeHelper
|
||||||
|
{
|
||||||
|
public static LevelType ToLevelType(this string[] row)
|
||||||
|
{
|
||||||
|
var result = new LevelType
|
||||||
|
{
|
||||||
|
Name = row[0],
|
||||||
|
Id = Convert.ToInt32(row[1]),
|
||||||
|
Beta = Convert.ToInt32(row[34]) == 1,
|
||||||
|
Act = Convert.ToInt32(row[35])
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
result.File[i] = row[i + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
241
OpenDiablo2.Common/Models/MPQDS1.cs
Normal file
241
OpenDiablo2.Common/Models/MPQDS1.cs
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using OpenDiablo2.Common.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Common.Models
|
||||||
|
{
|
||||||
|
|
||||||
|
public sealed class MPQDS1TileProps
|
||||||
|
{
|
||||||
|
public byte Prop1 { get; internal set; }
|
||||||
|
public byte Prop2 { get; internal set; }
|
||||||
|
public byte Prop3 { get; internal set; }
|
||||||
|
public byte Prop4 { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDS1WallOrientationTileProps
|
||||||
|
{
|
||||||
|
public byte Orientation1 { get; internal set; }
|
||||||
|
public byte Orientation2 { get; internal set; }
|
||||||
|
public byte Orientation3 { get; internal set; }
|
||||||
|
public byte Orientation4 { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDS1WallLayer
|
||||||
|
{
|
||||||
|
public MPQDS1TileProps[] Props { get; internal set; }
|
||||||
|
public MPQDS1WallOrientationTileProps[] Orientations { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDS1FloorLayer
|
||||||
|
{
|
||||||
|
public MPQDS1TileProps[] Props { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDS1ShadowLayer
|
||||||
|
{
|
||||||
|
public MPQDS1TileProps[] Props { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDS1Object
|
||||||
|
{
|
||||||
|
public UInt32 Type { get; internal set; }
|
||||||
|
public UInt32 Id { get; internal set; }
|
||||||
|
public UInt32 X { get; internal set; }
|
||||||
|
public UInt32 Y { get; internal set; }
|
||||||
|
public UInt32 DS1Flags { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDS1
|
||||||
|
{
|
||||||
|
static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public UInt32 Version { get; internal set; }
|
||||||
|
public UInt32 Width { get; internal set; }
|
||||||
|
public UInt32 Height { get; internal set; }
|
||||||
|
public UInt32 Act { get; internal set; } // ???
|
||||||
|
public UInt32 TagType { get; internal set; } // ???
|
||||||
|
public UInt32 FileCount { get; internal set; }
|
||||||
|
public UInt32 NumberOfWalls { get; internal set; }
|
||||||
|
public UInt32 NumberOfFloors { get; internal set; }
|
||||||
|
public UInt32 NumberOfObjects { get; internal set; }
|
||||||
|
public UInt32 NumberOfNPCs { get; internal set; }
|
||||||
|
|
||||||
|
public MPQDT1[] DT1s = new MPQDT1[32];
|
||||||
|
|
||||||
|
public List<string> FileNames { get; internal set; } = new List<string>();
|
||||||
|
public List<MPQDS1WallLayer> WallLayers { get; internal set; } = new List<MPQDS1WallLayer>();
|
||||||
|
public List<MPQDS1FloorLayer> FloorLayers { get; internal set; } = new List<MPQDS1FloorLayer>();
|
||||||
|
public MPQDS1ShadowLayer ShadowLayer { get; internal set; } = new MPQDS1ShadowLayer();
|
||||||
|
public List<MPQDS1Object> Objects { get; internal set; } = new List<MPQDS1Object>();
|
||||||
|
|
||||||
|
// TODO: DI magic please
|
||||||
|
public MPQDS1(Stream stream, string fileName, int definition, int act, IEngineDataManager engineDataManager, IResourceManager resourceManager)
|
||||||
|
{
|
||||||
|
log.Debug($"Loading {fileName} (Act {act}) Def {definition}");
|
||||||
|
var br = new BinaryReader(stream);
|
||||||
|
Version = br.ReadUInt32();
|
||||||
|
Width = br.ReadUInt32() + 1;
|
||||||
|
Height = br.ReadUInt32() + 1;
|
||||||
|
Act = br.ReadUInt32();
|
||||||
|
TagType = br.ReadUInt32();
|
||||||
|
FileCount = br.ReadUInt32();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (TagType != 0)
|
||||||
|
throw new ApplicationException("We don't currently handle those tag things...");
|
||||||
|
|
||||||
|
for (int i = 0; i < FileCount; i++)
|
||||||
|
{
|
||||||
|
var fn = "";
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var b = br.ReadByte();
|
||||||
|
if (b == 0)
|
||||||
|
break;
|
||||||
|
fn += (char)b;
|
||||||
|
}
|
||||||
|
if (fn.StartsWith("\\d2\\"))
|
||||||
|
fn = fn.Substring(4);
|
||||||
|
FileNames.Add(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberOfWalls = br.ReadUInt32();
|
||||||
|
NumberOfFloors = br.ReadUInt32();
|
||||||
|
|
||||||
|
for (int i = 0; i < NumberOfWalls; i++)
|
||||||
|
{
|
||||||
|
var wallLayer = new MPQDS1WallLayer
|
||||||
|
{
|
||||||
|
Props = new MPQDS1TileProps[Width * Height],
|
||||||
|
Orientations = new MPQDS1WallOrientationTileProps[Width * Height]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int y = 0; y < Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < Width; x++)
|
||||||
|
{
|
||||||
|
wallLayer.Props[x + (y * Width)] = new MPQDS1TileProps
|
||||||
|
{
|
||||||
|
Prop1 = br.ReadByte(),
|
||||||
|
Prop2 = br.ReadByte(),
|
||||||
|
Prop3 = br.ReadByte(),
|
||||||
|
Prop4 = br.ReadByte()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < Width; x++)
|
||||||
|
{
|
||||||
|
wallLayer.Orientations[x + (y * Width)] = new MPQDS1WallOrientationTileProps
|
||||||
|
{
|
||||||
|
Orientation1 = br.ReadByte(),
|
||||||
|
Orientation2 = br.ReadByte(),
|
||||||
|
Orientation3 = br.ReadByte(),
|
||||||
|
Orientation4 = br.ReadByte()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WallLayers.Add(wallLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < NumberOfFloors; i++)
|
||||||
|
{
|
||||||
|
var floorLayer = new MPQDS1FloorLayer
|
||||||
|
{
|
||||||
|
Props = new MPQDS1TileProps[Width * Height]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int y = 0; y < Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < Width; x++)
|
||||||
|
{
|
||||||
|
floorLayer.Props[x + (y * Width)] = new MPQDS1TileProps
|
||||||
|
{
|
||||||
|
Prop1 = br.ReadByte(),
|
||||||
|
Prop2 = br.ReadByte(),
|
||||||
|
Prop3 = br.ReadByte(),
|
||||||
|
Prop4 = br.ReadByte()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FloorLayers.Add(floorLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShadowLayer.Props = new MPQDS1TileProps[Width * Height];
|
||||||
|
for (int y = 0; y < Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < Width; x++)
|
||||||
|
{
|
||||||
|
ShadowLayer.Props[x + (y * Width)] = new MPQDS1TileProps
|
||||||
|
{
|
||||||
|
Prop1 = br.ReadByte(),
|
||||||
|
Prop2 = br.ReadByte(),
|
||||||
|
Prop3 = br.ReadByte(),
|
||||||
|
Prop4 = br.ReadByte()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Tag layer goes here (tag = 1)
|
||||||
|
|
||||||
|
NumberOfObjects = br.ReadUInt32();
|
||||||
|
for (int i = 0; i < NumberOfObjects; i++)
|
||||||
|
{
|
||||||
|
Objects.Add(new MPQDS1Object
|
||||||
|
{
|
||||||
|
Type = br.ReadUInt32(),
|
||||||
|
Id = br.ReadUInt32(),
|
||||||
|
X = br.ReadUInt32(),
|
||||||
|
Y = br.ReadUInt32(),
|
||||||
|
DS1Flags = br.ReadUInt32()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Option groups go here (tag = 1)
|
||||||
|
|
||||||
|
NumberOfNPCs = br.ReadUInt32();
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: WalkPaths
|
||||||
|
|
||||||
|
LevelPreset levelPreset;
|
||||||
|
if (definition == -1)
|
||||||
|
{
|
||||||
|
levelPreset = engineDataManager.LevelPresets.First(x =>
|
||||||
|
x.File1.ToLower() == fileName.ToLower()
|
||||||
|
|| x.File2.ToLower() == fileName.ToLower()
|
||||||
|
|| x.File3.ToLower() == fileName.ToLower()
|
||||||
|
|| x.File4.ToLower() == fileName.ToLower()
|
||||||
|
|| x.File5.ToLower() == fileName.ToLower()
|
||||||
|
|| x.File6.ToLower() == fileName.ToLower());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
levelPreset = engineDataManager.LevelPresets.First(x => x.Def == definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dt1Mask = levelPreset.Dt1Mask;
|
||||||
|
var levelType = engineDataManager.LevelTypes.First(x => x.Id == levelPreset.LevelId && x.Act == act);
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
var tilePath = levelType.File[i];
|
||||||
|
var isMasked = ((dt1Mask >> i) & 1) == 1;
|
||||||
|
if (!isMasked)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
log.Debug($"Loading DT resource {levelType.File[i]}");
|
||||||
|
|
||||||
|
DT1s[i] = resourceManager.GetMPQDT1("data\\global\\tiles\\" + levelType.File[i].Replace("/", "\\"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
179
OpenDiablo2.Common/Models/MPQDT1.cs
Normal file
179
OpenDiablo2.Common/Models/MPQDT1.cs
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Common.Models
|
||||||
|
{
|
||||||
|
public sealed class MPQDT1Block
|
||||||
|
{
|
||||||
|
public UInt16 PositionX { get; internal set; }
|
||||||
|
public UInt16 PositionY { get; internal set; }
|
||||||
|
public byte GridX { get; internal set; }
|
||||||
|
public byte GridY { get; internal set; }
|
||||||
|
public UInt16 Format { get; internal set; }
|
||||||
|
public UInt32 Length { get; internal set; }
|
||||||
|
public Int32 FileOffset { get; internal set; }
|
||||||
|
public Int16[] PixelData { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDT1Tile
|
||||||
|
{
|
||||||
|
public UInt32 Direction { get; internal set; }
|
||||||
|
public UInt16 RoofHeight { get; internal set; }
|
||||||
|
public byte SoundIndex { get; internal set; }
|
||||||
|
public bool Animated { get; internal set; }
|
||||||
|
public int Height { get; internal set; }
|
||||||
|
public int Width { get; internal set; }
|
||||||
|
public UInt32 Orientation { get; internal set; }
|
||||||
|
public UInt32 MainIndex { get; internal set; }
|
||||||
|
public UInt32 SubIndex { get; internal set; }
|
||||||
|
public UInt32 RarityOrFrameIndex { get; internal set; }// Frame index if animated floor tile
|
||||||
|
public byte[] SubTileFlags { get; internal set; } = new byte[25];
|
||||||
|
public UInt32 BlockHeadersPointer { get; internal set; } // Pointer to block headers for this tile
|
||||||
|
public UInt32 BlockDataLength { get; internal set; } // Block headers + block data of this tile
|
||||||
|
public UInt32 NumberOfBlocks { get; internal set; }
|
||||||
|
public MPQDT1Block[] Blocks { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MPQDT1
|
||||||
|
{
|
||||||
|
public UInt32 NumberOfTiles { get; private set; }
|
||||||
|
public MPQDT1Tile[] Tiles { get; private set; }
|
||||||
|
|
||||||
|
public MPQDT1(Stream stream)
|
||||||
|
{
|
||||||
|
var br = new BinaryReader(stream);
|
||||||
|
|
||||||
|
stream.Seek(268, SeekOrigin.Begin); // Skip useless header info
|
||||||
|
NumberOfTiles = br.ReadUInt32();
|
||||||
|
var tileHeaderOffset = br.ReadUInt32();
|
||||||
|
stream.Seek(tileHeaderOffset, SeekOrigin.Begin);
|
||||||
|
Tiles = new MPQDT1Tile[NumberOfTiles];
|
||||||
|
|
||||||
|
for (int tileIndex = 0; tileIndex < NumberOfTiles; tileIndex++)
|
||||||
|
{
|
||||||
|
Tiles[tileIndex] = new MPQDT1Tile();
|
||||||
|
Tiles[tileIndex].Direction = br.ReadUInt32();
|
||||||
|
Tiles[tileIndex].RoofHeight = br.ReadUInt16();
|
||||||
|
Tiles[tileIndex].SoundIndex = br.ReadByte();
|
||||||
|
Tiles[tileIndex].Animated = br.ReadByte() == 1;
|
||||||
|
Tiles[tileIndex].Height = br.ReadInt32();
|
||||||
|
Tiles[tileIndex].Width = br.ReadInt32();
|
||||||
|
br.ReadBytes(4);
|
||||||
|
Tiles[tileIndex].Orientation = br.ReadUInt32();
|
||||||
|
Tiles[tileIndex].MainIndex = br.ReadUInt32();
|
||||||
|
Tiles[tileIndex].SubIndex = br.ReadUInt32();
|
||||||
|
Tiles[tileIndex].RarityOrFrameIndex = br.ReadUInt32();
|
||||||
|
br.ReadBytes(4);
|
||||||
|
for (int i = 0; i < 25; i++)
|
||||||
|
Tiles[tileIndex].SubTileFlags[i] = br.ReadByte();
|
||||||
|
br.ReadBytes(7);
|
||||||
|
Tiles[tileIndex].BlockHeadersPointer = br.ReadUInt32();
|
||||||
|
Tiles[tileIndex].BlockDataLength = br.ReadUInt32();
|
||||||
|
Tiles[tileIndex].NumberOfBlocks = br.ReadUInt32();
|
||||||
|
br.ReadBytes(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int tileIndex = 0; tileIndex < NumberOfTiles; tileIndex++)
|
||||||
|
{
|
||||||
|
var tile = Tiles[tileIndex];
|
||||||
|
if (tile.BlockHeadersPointer == 0)
|
||||||
|
{
|
||||||
|
tile.Blocks = new MPQDT1Block[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stream.Seek(tile.BlockHeadersPointer, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
tile.Blocks = new MPQDT1Block[tile.NumberOfBlocks];
|
||||||
|
for (int blockIndex = 0; blockIndex < tile.NumberOfBlocks; blockIndex++)
|
||||||
|
{
|
||||||
|
tile.Blocks[blockIndex] = new MPQDT1Block();
|
||||||
|
tile.Blocks[blockIndex].PositionX = br.ReadUInt16();
|
||||||
|
tile.Blocks[blockIndex].PositionY = br.ReadUInt16();
|
||||||
|
br.ReadBytes(2);
|
||||||
|
tile.Blocks[blockIndex].GridX = br.ReadByte();
|
||||||
|
tile.Blocks[blockIndex].GridX = br.ReadByte();
|
||||||
|
tile.Blocks[blockIndex].Format = br.ReadUInt16();
|
||||||
|
tile.Blocks[blockIndex].Length = br.ReadUInt32();
|
||||||
|
br.ReadBytes(2);
|
||||||
|
tile.Blocks[blockIndex].FileOffset = br.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int blockIndex = 0; blockIndex < tile.NumberOfBlocks; blockIndex++)
|
||||||
|
{
|
||||||
|
var block = tile.Blocks[blockIndex];
|
||||||
|
stream.Seek(tile.BlockHeadersPointer + block.FileOffset, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
if (block.Format == 1)
|
||||||
|
{
|
||||||
|
// 3D isometric block
|
||||||
|
if (block.Length != 256)
|
||||||
|
throw new ApplicationException($"Expected exactly 256 bytes of data, but got {block.Length} instead!");
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int n = 0;
|
||||||
|
int[] xjump = { 14, 12, 10, 8, 6, 4, 2, 0, 2, 4, 6, 8, 10, 12, 14 };
|
||||||
|
int[] nbpix = { 4, 8, 12, 16, 20, 24, 28, 32, 28, 24, 20, 16, 12, 8, 4 };
|
||||||
|
var length = 256;
|
||||||
|
block.PixelData = new Int16[32 * 16];
|
||||||
|
while (length > 0)
|
||||||
|
{
|
||||||
|
x = xjump[y];
|
||||||
|
n = nbpix[y];
|
||||||
|
length -= n;
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
block.PixelData[x + (y * 32)] = br.ReadByte();
|
||||||
|
x++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: This doesn't work.. memory pointer issues?
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// RLE block
|
||||||
|
var length = block.Length;
|
||||||
|
byte b1;
|
||||||
|
byte b2;
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
block.PixelData = new Int16[32 * 16];
|
||||||
|
while (length > 0)
|
||||||
|
{
|
||||||
|
b1 = br.ReadByte();
|
||||||
|
b2 = br.ReadByte();
|
||||||
|
length -= 2;
|
||||||
|
if (b1 != 0 || b2 != 0)
|
||||||
|
{
|
||||||
|
x += b1;
|
||||||
|
length -= b2;
|
||||||
|
while(b2 > 0)
|
||||||
|
{
|
||||||
|
block.PixelData[x + (y * 32)] = br.ReadByte();
|
||||||
|
br.ReadByte();
|
||||||
|
x++;
|
||||||
|
b2--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -73,6 +73,7 @@
|
|||||||
<Compile Include="Enums\eButtonType.cs" />
|
<Compile Include="Enums\eButtonType.cs" />
|
||||||
<Compile Include="Enums\eHero.cs" />
|
<Compile Include="Enums\eHero.cs" />
|
||||||
<Compile Include="Enums\eMPQFormatVersion.cs" />
|
<Compile Include="Enums\eMPQFormatVersion.cs" />
|
||||||
|
<Compile Include="Interfaces\IEngineDataManager.cs" />
|
||||||
<Compile Include="Interfaces\IFont.cs" />
|
<Compile Include="Interfaces\IFont.cs" />
|
||||||
<Compile Include="Interfaces\IGameEngine.cs" />
|
<Compile Include="Interfaces\IGameEngine.cs" />
|
||||||
<Compile Include="Interfaces\IKeyboardInfoProvider.cs" />
|
<Compile Include="Interfaces\IKeyboardInfoProvider.cs" />
|
||||||
@ -91,6 +92,10 @@
|
|||||||
<Compile Include="Interfaces\ITextLabel.cs" />
|
<Compile Include="Interfaces\ITextLabel.cs" />
|
||||||
<Compile Include="Models\BitStream.cs" />
|
<Compile Include="Models\BitStream.cs" />
|
||||||
<Compile Include="Models\ButtonLayout.cs" />
|
<Compile Include="Models\ButtonLayout.cs" />
|
||||||
|
<Compile Include="Models\LevelPreset.cs" />
|
||||||
|
<Compile Include="Models\LevelType.cs" />
|
||||||
|
<Compile Include="Models\MPQDS1.cs" />
|
||||||
|
<Compile Include="Models\MPQDT1.cs" />
|
||||||
<Compile Include="Models\MPQFont.cs" />
|
<Compile Include="Models\MPQFont.cs" />
|
||||||
<Compile Include="Models\GlobalConfiguration.cs" />
|
<Compile Include="Models\GlobalConfiguration.cs" />
|
||||||
<Compile Include="Models\ImageSet.cs" />
|
<Compile Include="Models\ImageSet.cs" />
|
||||||
|
@ -106,6 +106,11 @@ namespace OpenDiablo2.Common
|
|||||||
// TODO: Doesn't sound right :)
|
// TODO: Doesn't sound right :)
|
||||||
public static string EnglishTable = "data\\local\\lng\\eng\\English.txt";
|
public static string EnglishTable = "data\\local\\lng\\eng\\English.txt";
|
||||||
public static string ExpansionStringTable = "data\\local\\lng\\eng\\expansionstring.tbl";
|
public static string ExpansionStringTable = "data\\local\\lng\\eng\\expansionstring.tbl";
|
||||||
|
public static string LevelPreset = "data\\global\\excel\\LvlPrest.txt";
|
||||||
|
public static string LevelType = "data\\global\\excel\\LvlTypes.txt";
|
||||||
|
|
||||||
|
// --- Maps ---
|
||||||
|
public static string MapAct1TownE1 = "data\\global\\tiles\\ACT1\\Town\\townE1.ds1";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,10 @@ namespace OpenDiablo2.Core
|
|||||||
builder.RegisterType<MPQProvider>().As<IMPQProvider>().SingleInstance();
|
builder.RegisterType<MPQProvider>().As<IMPQProvider>().SingleInstance();
|
||||||
builder.RegisterType<ResourceManager>().As<IResourceManager>().SingleInstance();
|
builder.RegisterType<ResourceManager>().As<IResourceManager>().SingleInstance();
|
||||||
builder.RegisterType<TextDictionary>().As<ITextDictionary>().SingleInstance();
|
builder.RegisterType<TextDictionary>().As<ITextDictionary>().SingleInstance();
|
||||||
builder.RegisterType<Button>().AsSelf().InstancePerDependency();
|
builder.RegisterType<Button>().AsSelf().InstancePerDependency(); // TODO: Never register as Self() if we aren't in common...
|
||||||
builder.RegisterType<TextBox>().AsSelf().InstancePerDependency();
|
builder.RegisterType<TextBox>().AsSelf().InstancePerDependency(); // TODO: Never register as Self() if we aren't in common...
|
||||||
builder.RegisterType<GameState>().AsSelf().SingleInstance();
|
builder.RegisterType<GameState>().AsSelf().SingleInstance(); // TODO: Never register as Self() if we aren't in common...
|
||||||
|
builder.RegisterType<EngineDataManager>().As<IEngineDataManager>().SingleInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
OpenDiablo2.Core/EngineDataManager.cs
Normal file
55
OpenDiablo2.Core/EngineDataManager.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using OpenDiablo2.Common;
|
||||||
|
using OpenDiablo2.Common.Interfaces;
|
||||||
|
using OpenDiablo2.Common.Models;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Core
|
||||||
|
{
|
||||||
|
public sealed class EngineDataManager : IEngineDataManager
|
||||||
|
{
|
||||||
|
private readonly IMPQProvider mpqProvider;
|
||||||
|
|
||||||
|
public List<LevelPreset> LevelPresets { get; internal set; }
|
||||||
|
public List<LevelType> LevelTypes { get; internal set; }
|
||||||
|
|
||||||
|
public EngineDataManager(IMPQProvider mpqProvider)
|
||||||
|
{
|
||||||
|
this.mpqProvider = mpqProvider;
|
||||||
|
|
||||||
|
LoadLevelPresets();
|
||||||
|
LoadLevelTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadLevelTypes()
|
||||||
|
{
|
||||||
|
var data = mpqProvider
|
||||||
|
.GetTextFile(ResourcePaths.LevelType)
|
||||||
|
.First()
|
||||||
|
.Skip(1)
|
||||||
|
.Where(x => !String.IsNullOrWhiteSpace(x))
|
||||||
|
.Select(x => x.Split('\t'))
|
||||||
|
.ToArray()
|
||||||
|
.Select(x => x.ToLevelType());
|
||||||
|
|
||||||
|
LevelTypes = new List<LevelType>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadLevelPresets()
|
||||||
|
{
|
||||||
|
var data = mpqProvider
|
||||||
|
.GetTextFile(ResourcePaths.LevelPreset)
|
||||||
|
.First()
|
||||||
|
.Skip(1)
|
||||||
|
.Where(x => !String.IsNullOrWhiteSpace(x))
|
||||||
|
.Select(x => x.Split('\t'))
|
||||||
|
.ToArray()
|
||||||
|
.Select(x => x.ToLevelPreset());
|
||||||
|
|
||||||
|
LevelPresets = new List<LevelPreset>(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,24 +3,29 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using OpenDiablo2.Common;
|
||||||
using OpenDiablo2.Common.Enums;
|
using OpenDiablo2.Common.Enums;
|
||||||
using OpenDiablo2.Common.Interfaces;
|
using OpenDiablo2.Common.Interfaces;
|
||||||
|
using OpenDiablo2.Common.Models;
|
||||||
|
|
||||||
namespace OpenDiablo2.Core.GameState_
|
namespace OpenDiablo2.Core.GameState_
|
||||||
{
|
{
|
||||||
public sealed class GameState
|
public sealed class GameState
|
||||||
{
|
{
|
||||||
private readonly ISceneManager sceneManager;
|
private readonly ISceneManager sceneManager;
|
||||||
|
private readonly IResourceManager resourceManager;
|
||||||
|
MPQDS1 mapData;
|
||||||
|
|
||||||
public GameState(ISceneManager sceneManager)
|
public GameState(ISceneManager sceneManager, IResourceManager resourceManager)
|
||||||
{
|
{
|
||||||
this.sceneManager = sceneManager;
|
this.sceneManager = sceneManager;
|
||||||
|
this.resourceManager = resourceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(string characterName, eHero hero)
|
public void Initialize(string characterName, eHero hero)
|
||||||
{
|
{
|
||||||
|
|
||||||
sceneManager.ChangeScene("Game");
|
sceneManager.ChangeScene("Game");
|
||||||
|
mapData = resourceManager.GetMPQDS1(ResourcePaths.MapAct1TownE1, -1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AutofacModule.cs" />
|
<Compile Include="AutofacModule.cs" />
|
||||||
|
<Compile Include="EngineDataManager.cs" />
|
||||||
<Compile Include="GameEngine.cs" />
|
<Compile Include="GameEngine.cs" />
|
||||||
<Compile Include="GameState\GameState.cs" />
|
<Compile Include="GameState\GameState.cs" />
|
||||||
<Compile Include="MPQProvider.cs" />
|
<Compile Include="MPQProvider.cs" />
|
||||||
|
@ -11,13 +11,17 @@ namespace OpenDiablo2.Core
|
|||||||
public sealed class ResourceManager : IResourceManager
|
public sealed class ResourceManager : IResourceManager
|
||||||
{
|
{
|
||||||
private readonly IMPQProvider mpqProvider;
|
private readonly IMPQProvider mpqProvider;
|
||||||
|
private readonly IEngineDataManager engineDataManager;
|
||||||
|
|
||||||
private Dictionary<string, ImageSet> ImageSets = new Dictionary<string, ImageSet>();
|
private Dictionary<string, ImageSet> ImageSets = new Dictionary<string, ImageSet>();
|
||||||
private Dictionary<string, MPQFont> MPQFonts = new Dictionary<string, MPQFont>();
|
private Dictionary<string, MPQFont> MPQFonts = new Dictionary<string, MPQFont>();
|
||||||
private Dictionary<string, Palette> Palettes = new Dictionary<string, Palette>();
|
private Dictionary<string, Palette> Palettes = new Dictionary<string, Palette>();
|
||||||
|
private Dictionary<string, MPQDT1> DTs = new Dictionary<string, MPQDT1>();
|
||||||
|
|
||||||
public ResourceManager(IMPQProvider mpqProvider)
|
public ResourceManager(IMPQProvider mpqProvider, IEngineDataManager engineDataManager)
|
||||||
{
|
{
|
||||||
this.mpqProvider = mpqProvider;
|
this.mpqProvider = mpqProvider;
|
||||||
|
this.engineDataManager = engineDataManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageSet GetImageSet(string resourcePath)
|
public ImageSet GetImageSet(string resourcePath)
|
||||||
@ -36,6 +40,12 @@ namespace OpenDiablo2.Core
|
|||||||
return MPQFonts[resourcePath];
|
return MPQFonts[resourcePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MPQDS1 GetMPQDS1(string resourcePath, int definition, int act)
|
||||||
|
{
|
||||||
|
var mapName = resourcePath.Replace("data\\global\\tiles\\", "").Replace("\\", "/");
|
||||||
|
return new MPQDS1(mpqProvider.GetStream(resourcePath), mapName, definition, act, engineDataManager, this);
|
||||||
|
}
|
||||||
|
|
||||||
public Palette GetPalette(string paletteFile)
|
public Palette GetPalette(string paletteFile)
|
||||||
{
|
{
|
||||||
if (!Palettes.ContainsKey(paletteFile))
|
if (!Palettes.ContainsKey(paletteFile))
|
||||||
@ -49,5 +59,13 @@ namespace OpenDiablo2.Core
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MPQDT1 GetMPQDT1(string resourcePath)
|
||||||
|
{
|
||||||
|
if (!DTs.ContainsKey(resourcePath))
|
||||||
|
DTs[resourcePath] = new MPQDT1(mpqProvider.GetStream(resourcePath));
|
||||||
|
|
||||||
|
return DTs[resourcePath];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ namespace OpenDiablo2.Scenes
|
|||||||
IMouseInfoProvider mouseInfoProvider,
|
IMouseInfoProvider mouseInfoProvider,
|
||||||
IMusicProvider musicProvider,
|
IMusicProvider musicProvider,
|
||||||
ISceneManager sceneManager,
|
ISceneManager sceneManager,
|
||||||
|
IResourceManager resourceManager,
|
||||||
Func<eButtonType, Button> createButton,
|
Func<eButtonType, Button> createButton,
|
||||||
Func<string, IScene> getScene // Temporary until SDL load functions are sped up
|
Func<string, IScene> getScene // Temporary until SDL load functions are sped up
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user