/// <inheritdoc/> public uint GetSize() { int size = MH2OHeader.GetSize() * 256; foreach (var header in MH2OHeaders) { if (header.Attributes != null && !header.Attributes.HasOnlyZeroes) { size += MH2OAttribute.GetSize(); } foreach (var instance in header.Instances) { size += MH2OInstance.GetSize(); if (instance.RenderBitmapBytes.Length == (instance.Width * instance.Height + 7) / 8) { size += instance.RenderBitmapBytes.Length; } if (instance.VertexData != null) { size += MH2OInstanceVertexData.GetSize(); } } } return((uint)size); }
/// <summary> /// Processes an individual MH2O Chunk /// </summary> /// <param name="Header">MH20 Header Chunk</param> /// <param name="ofsMH20">MH20 OFFset</param> /// <returns>MH2O Filled with information</returns> private MH2O processMH20(MH2OHeader Header, long ofsMH20) { if (Header.used == 0) { return(new MH2O { used = false }); } Reader.BaseStream.Position = ofsMH20 + Header.ofsData1 + 2; var currentMH2O = new MH2O(); currentMH2O.used = true; currentMH2O.type = ((MH2O.FluidType)Reader.ReadUInt16()); currentMH2O.heightLevel1 = Reader.ReadSingle(); currentMH2O.heightLevel2 = Reader.ReadSingle(); currentMH2O.xOffset = Reader.ReadByte(); currentMH2O.yOffset = Reader.ReadByte(); currentMH2O.width = Reader.ReadByte(); currentMH2O.height = Reader.ReadByte(); UInt32 ofsData2a = Reader.ReadUInt32(); UInt32 ofsData2b = Reader.ReadUInt32(); currentMH2O.RenderBitMap = ReadRenderBitMap(currentMH2O, ofsData2a, ofsMH20 + ofsData2a, ofsData2b - ofsData2a); currentMH2O.heights = ReadHeights(currentMH2O, ofsData2b, (currentMH2O.width + 1) * (currentMH2O.height + 1), ofsMH20 + ofsData2b); return(currentMH2O); }
public MH2O(byte[] chunkBytes) : base(chunkBytes) { for (int i = 0; i < 256; i++) { Headers[i] = new MH2OHeader(this); } Close(); }
/// <inheritdoc/> public byte[] Serialize() { using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { // Write MH2O headers later when we got the offsets bw.Seek(256 * MH2OHeader.GetSize(), SeekOrigin.Begin); // Write MH2O instances later when we got the offsets foreach (var header in MH2OHeaders) { header.LayerCount = (uint)header.Instances.Length; if (header.LayerCount > 0) { foreach (var instance in header.Instances) { // Write MH2O instance subdata if (instance.VertexData is null) { instance.OffsetVertexData = 0; } else { instance.OffsetVertexData = (uint)bw.BaseStream.Position; bw.Write(instance.VertexData.Serialize(instance)); } if (instance.RenderBitmapBytes.Length == 0) { instance.OffsetExistsBitmap = 0; } // Don't write RenderBitmapBytes when the length is incorrect else if (instance.RenderBitmapBytes.Length == (instance.Width * instance.Height + 7) / 8) { instance.OffsetExistsBitmap = (uint)bw.BaseStream.Position; bw.Write(instance.RenderBitmapBytes); } } // Write MH2O attributes if (header.Attributes is null || header.Attributes.HasOnlyZeroes) { header.OffsetAttributes = 0; } else { header.OffsetAttributes = (uint)bw.BaseStream.Position; bw.Write(header.Attributes.Serialize()); } // Write MH2O instances header.OffsetInstances = (uint)bw.BaseStream.Position; foreach (var instance in header.Instances) { bw.Write(instance.Serialize()); } }
public void Read(BinaryReader br) { Headers = new MH2OHeader[256]; for (int i = 0; i < Headers.Length; i++) { var entry = new MH2OHeader(); entry.Read(br); Headers[i] = entry; } }
public void Read(BinaryReader br) { Headers = new MH2OHeader[256]; for (int i = 0; i < Headers.Length; i++) { var entry = new MH2OHeader(); entry.Read(br); Headers[i] = entry; } }
/// <inheritdoc/> public byte[] Serialize(long offset = 0) { using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { // Write MH2O headers later when we got the offsets bw.Seek(256 * MH2OHeader.GetSize(), SeekOrigin.Begin); // Write MH2O instances later when we got the offsets foreach (var header in MH2OHeaders) { header.OffsetInstances = (uint)bw.BaseStream.Position; bw.Seek(MH2OInstance.GetSize() * header.Instances.Length, SeekOrigin.Current); } foreach (var header in MH2OHeaders) { header.LayerCount = (uint)header.Instances.Length; if (header.LayerCount > 0) { WriteAttributes(bw, header); foreach (var instance in header.Instances) { WriteRenderBitmapBytes(bw, instance); WriteVertexData(bw, instance); } } else { header.OffsetAttributes = 0; header.OffsetInstances = 0; } } // Write MH2O instance data foreach (var header in MH2OHeaders) { bw.BaseStream.Position = header.OffsetInstances; foreach (var instance in header.Instances) { bw.Write(instance.Serialize()); } } // Write MH2O header data bw.Seek(0, SeekOrigin.Begin); foreach (var header in MH2OHeaders) { bw.Write(header.Serialize()); } return(ms.ToArray()); } }
/// <summary> /// Writes the MH2O header attributes or sets the offset to 0 if they can be omitted. /// </summary> /// <param name="bw"></param> /// <param name="header"></param> private void WriteAttributes(BinaryWriter bw, MH2OHeader header) { if (header.Attributes is null) { header.OffsetAttributes = 0; } else { header.OffsetAttributes = (uint)bw.BaseStream.Position; bw.Write(header.Attributes.Serialize()); } }
/// <inheritdoc/> public void LoadBinaryData(byte[] inData) { using (var ms = new MemoryStream(inData)) using (var br = new BinaryReader(ms)) { for (int i = 0; i < 256; i++) { MH2OHeaders[i] = new MH2OHeader(br.ReadBytes(MH2OHeader.GetSize())); } foreach (var header in MH2OHeaders) { // load MH2O header subdata if (header.LayerCount > 0) { // load MH2O instances br.BaseStream.Position = header.OffsetInstances; for (int i = 0; i < header.LayerCount; i++) { header.Instances[i] = new MH2OInstance(br.ReadBytes(MH2OInstance.GetSize())); } // load MH2O attributes if (header.OffsetAttributes > 0) { br.BaseStream.Position = header.OffsetAttributes; header.Attributes = new MH2OAttribute(br.ReadBytes(MH2OAttribute.GetSize())); } // load MH2O instance subdata foreach (var instance in header.Instances) { if (instance.OffsetExistsBitmap > 0) { br.BaseStream.Position = instance.OffsetExistsBitmap; instance.RenderBitmapBytes = br.ReadBytes(((instance.Width * instance.Height) + 7) / 8); } if (instance.OffsetVertexData > 0) { br.BaseStream.Position = instance.OffsetVertexData; instance.VertexData = new MH2OInstanceVertexData(br.ReadBytes(MH2OInstanceVertexData.GetSize(instance)), instance); } } } } } }
/// <summary> /// Parse all MH2O element from file stream /// </summary> public override MH2O[,] Parse() { Reader.BaseStream.Position = AbsoluteStart; var result = new MH2O[16, 16]; var mh2oHeader = new MH2OHeader[256]; for (int i = 0; i < 256; i++) { mh2oHeader[i].ofsData1 = Reader.ReadUInt32(); mh2oHeader[i].used = Reader.ReadUInt32(); mh2oHeader[i].ofsData2 = Reader.ReadUInt32(); } for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { result[x, y] = processMH20(mh2oHeader[y * 16 + x], AbsoluteStart); } } return(result); }
private static MH2O ProcessMH2O(BinaryReader fileReader, MH2OHeader header, long waterSegmentBase) { var water = new MH2O(); if (header.LayerCount == 0) { water.Used = false; return water; } water.Used = true; fileReader.BaseStream.Position = waterSegmentBase + header.ofsData1; water.Flags = (MH2OFlags)fileReader.ReadUInt16(); water.Type = (FluidType)fileReader.ReadUInt16(); water.HeightLevel1 = fileReader.ReadSingle(); water.HeightLevel2 = fileReader.ReadSingle(); water.XOffset = fileReader.ReadByte(); water.YOffset = fileReader.ReadByte(); water.Width = fileReader.ReadByte(); water.Height = fileReader.ReadByte(); var ofsWaterFlags = fileReader.ReadUInt32(); var ofsWaterHeightMap = fileReader.ReadUInt32(); var heightMapLen = (water.Width + 1) * (water.Height + 1); var heights = new float[heightMapLen]; // If flags is 2, the chunk is for an ocean, and there is no heightmap if (ofsWaterHeightMap != 0 && (water.Flags & MH2OFlags.Ocean) == 0) { fileReader.BaseStream.Position = waterSegmentBase + ofsWaterHeightMap; for (var i = 0; i < heightMapLen; i++) { heights[i] = fileReader.ReadSingle(); if (heights[i] == 0) { heights[i] = water.HeightLevel1; } } } else { for (var i = 0; i < heightMapLen; i++) { heights[i] = water.HeightLevel1; } } water.Heights = new float[water.Height + 1, water.Width + 1]; for (var r = 0; r <= water.Height; r++) { for (var c = 0; c <= water.Width; c++) { water.Heights[r, c] = heights[c + r * c]; } } return water; }
static void ReadMH2O(BinaryReader fileReader, ADTFile adt) { var sig = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); var ofsMH2O = fileReader.BaseStream.Position; var mh2oHeader = new MH2OHeader[256]; for (var i = 0; i < 256; i++) { mh2oHeader[i] = new MH2OHeader { ofsData1 = fileReader.ReadUInt32(), LayerCount = fileReader.ReadUInt32(), ofsData2 = fileReader.ReadUInt32() }; } for (var y = 0; y < 16; y++) { for (var x = 0; x < 16; x++) { adt.LiquidMaps[x, y] = ProcessMH2O(fileReader, mh2oHeader[y * 16 + x], ofsMH2O); } } }