diff --git a/Maple2.File.IO/Nif/PhysXMesh.cs b/Maple2.File.IO/Nif/PhysXMesh.cs
index a5fd196..e0f2940 100644
--- a/Maple2.File.IO/Nif/PhysXMesh.cs
+++ b/Maple2.File.IO/Nif/PhysXMesh.cs
@@ -5,11 +5,11 @@
namespace Maple2.File.IO.Nif;
public struct PhysXMeshFace {
- public byte Vert0;
- public byte Vert1;
- public byte Vert2;
+ public uint Vert0;
+ public uint Vert1;
+ public uint Vert2;
- public PhysXMeshFace(byte vert0 = 0, byte vert1 = 0, byte vert2 = 0) {
+ public PhysXMeshFace(uint vert0 = 0, uint vert1 = 0, uint vert2 = 0) {
Vert0 = vert0;
Vert1 = vert1;
Vert2 = vert2;
@@ -67,7 +67,7 @@ private NxsMeshType ParseConvexMesh(EndianReader reader) {
byte[] unkSection1 = reader.ReadBytes(8);
- // Sanity check to check a known piece of data for potential changes
+ // Sanity check to check a known piece of data for potential changes
if (!unkSection1.SequenceEqual(unkDataSection1)) {
throw new InvalidDataException("Unknown PhysX convex mesh data layout");
}
@@ -76,7 +76,7 @@ private NxsMeshType ParseConvexMesh(EndianReader reader) {
byte[] unkSection2 = reader.ReadBytes(4);
- // Sanity check to check a known piece of data for potential changes
+ // Sanity check to check a known piece of data for potential changes
if (!unkSection2.SequenceEqual(unkDataSection2)) {
throw new InvalidDataException("Unknown PhysX convex mesh data layout");
}
@@ -102,11 +102,27 @@ private NxsMeshType ParseConvexMesh(EndianReader reader) {
uint unk10 = reader.ReadAdjustedUInt32();
for (int i = 0; i < faceCount; ++i) {
- PhysXMeshFace face = new PhysXMeshFace(
- reader.ReadByte(),
- reader.ReadByte(),
- reader.ReadByte()
- );
+ PhysXMeshFace face;
+
+ if (vertexCount < 0x100) {
+ face = new PhysXMeshFace(
+ reader.ReadByte(),
+ reader.ReadByte(),
+ reader.ReadByte()
+ );
+ } else if (vertexCount < 0x10000) {
+ face = new PhysXMeshFace(
+ reader.ReadUInt16(),
+ reader.ReadUInt16(),
+ reader.ReadUInt16()
+ );
+ } else {
+ face = new PhysXMeshFace(
+ reader.ReadUInt32(),
+ reader.ReadUInt32(),
+ reader.ReadUInt32()
+ );
+ }
Faces.Add(face);
@@ -141,11 +157,27 @@ private NxsMeshType ParseTriangleMesh(EndianReader reader) {
}
for (int i = 0; i < faceCount; ++i) {
- PhysXMeshFace face = new PhysXMeshFace(
- reader.ReadByte(),
- reader.ReadByte(),
- reader.ReadByte()
- );
+ PhysXMeshFace face;
+
+ if (vertexCount < 0x100) {
+ face = new PhysXMeshFace(
+ reader.ReadByte(),
+ reader.ReadByte(),
+ reader.ReadByte()
+ );
+ } else if (vertexCount < 0x10000) {
+ face = new PhysXMeshFace(
+ reader.ReadUInt16(),
+ reader.ReadUInt16(),
+ reader.ReadUInt16()
+ );
+ } else {
+ face = new PhysXMeshFace(
+ reader.ReadUInt32(),
+ reader.ReadUInt32(),
+ reader.ReadUInt32()
+ );
+ }
Faces.Add(face);
diff --git a/Maple2.File.IO/Nif/NifM2dArchive.cs b/Maple2.File.IO/Nif/PrefixedM2dReader.cs
similarity index 100%
rename from Maple2.File.IO/Nif/NifM2dArchive.cs
rename to Maple2.File.IO/Nif/PrefixedM2dReader.cs
diff --git a/Maple2.File.Parser/Enum/NxActorFlag.cs b/Maple2.File.Parser/Enum/NxActorFlag.cs
deleted file mode 100644
index 12228ec..0000000
--- a/Maple2.File.Parser/Enum/NxActorFlag.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Maple2.File.Parser.Enum;
-
-public enum NxActorFlag : uint {
- None,
- DisableCollision = 1 << 0,
- DisableResponse = 1 << 1,
- LockCenterOfMass = 1 << 2,
- FluidDisableCollision = 1 << 3,
- ContactModification = 1 << 4,
- ForceConeFriction = 1 << 5,
- UserActorPairFiltering = 1 << 6
-}
diff --git a/Maple2.File.Parser/Enum/NxMeshShapeFlags.cs b/Maple2.File.Parser/Enum/NxMeshShapeFlags.cs
deleted file mode 100644
index 51dfd53..0000000
--- a/Maple2.File.Parser/Enum/NxMeshShapeFlags.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Maple2.File.Parser.Enum;
-
-public enum NxMeshShapeFlags : uint {
- None = 0,
- SmoothSphereCollisions = 1 << 0,
- DoubleSided = 1 << 1
-}
diff --git a/Maple2.File.Parser/Enum/NxPagingMode.cs b/Maple2.File.Parser/Enum/NxPagingMode.cs
deleted file mode 100644
index 7a939e9..0000000
--- a/Maple2.File.Parser/Enum/NxPagingMode.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Maple2.File.Parser.Enum;
-
-public enum NxPagingMode : uint {
- Manual,
- Fallback,
- Auto
-}
diff --git a/Maple2.File.Parser/Enum/NxShapeFlag.cs b/Maple2.File.Parser/Enum/NxShapeFlag.cs
deleted file mode 100644
index 0e98221..0000000
--- a/Maple2.File.Parser/Enum/NxShapeFlag.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace Maple2.File.Parser.Enum;
-
-public enum NxShapeFlag : uint {
- None,
- Visualization = 1 << 3,
- DisableCollision = 1 << 4,
- FeatureIndices = 1 << 5,
- DisableRaycasting = 1 << 6,
- PointContactForce = 1 << 7,
- FluidDrain = 1 << 8,
- FluidDisableCollision = 1 << 10,
- FluidTwoWay = 1 << 11,
- DisableResponse = 1 << 12,
- DynamicDynamicCCD = 1 << 13,
- DisableSceneQueries = 1 << 14,
- ClothDrain = 1 << 15,
- ClothDisableCollision = 1 << 16,
- ClothTwoWay = 1 << 17,
- SoftBodyDrain = 1 << 18,
- SoftBodyDisableCollision = 1 << 19,
- SoftBodyTwoWay = 1 << 20
-}
-
diff --git a/Maple2.File.Parser/Enum/NxShapeType.cs b/Maple2.File.Parser/Enum/NxShapeType.cs
deleted file mode 100644
index 6c62e21..0000000
--- a/Maple2.File.Parser/Enum/NxShapeType.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Maple2.File.Parser.Enum;
-
-public enum NxShapeType : uint {
- Plane,
- Sphere,
- Box,
- Capsule,
- Wheel,
- Convex,
- Mesh,
- HeightField,
- RawMesh,
- Compound
-}
-
diff --git a/Maple2.File.Parser/Enum/NxsMeshType.cs b/Maple2.File.Parser/Enum/NxsMeshType.cs
deleted file mode 100644
index 94a7c02..0000000
--- a/Maple2.File.Parser/Enum/NxsMeshType.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Maple2.File.Parser.Enum;
-
-public enum NxsMeshType {
- None,
- Convex,
- Triangle,
- Cloth
-}
-
diff --git a/Maple2.File.Parser/Enum/PhysXMeshFlags.cs b/Maple2.File.Parser/Enum/PhysXMeshFlags.cs
deleted file mode 100644
index e087bbb..0000000
--- a/Maple2.File.Parser/Enum/PhysXMeshFlags.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Maple2.File.Parser.Enum;
-
-public enum PhysXMeshFlags : byte {
- None = 0,
- IsConvex = 0x1,
- IsCloth = 0x2,
- Hardware = 0x4,
- CookedForWin32 = 0x8,
- CookedForPS3 = 0x10,
- CookedForXenon = 0x20
-}
diff --git a/Maple2.File.Parser/Maple2.File.Parser.csproj b/Maple2.File.Parser/Maple2.File.Parser.csproj
index 0ca034b..6f7971f 100644
--- a/Maple2.File.Parser/Maple2.File.Parser.csproj
+++ b/Maple2.File.Parser/Maple2.File.Parser.csproj
@@ -13,7 +13,7 @@
MapleStory2, File, Parser, m2d, xml
true
- 2.1.19
+ 2.1.20
net8.0
README.md
enable
diff --git a/Maple2.File.Parser/Nif/Endian.cs b/Maple2.File.Parser/Nif/Endian.cs
deleted file mode 100644
index b5bbf76..0000000
--- a/Maple2.File.Parser/Nif/Endian.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-using System.Buffers.Binary;
-using System.Numerics;
-using System.Text;
-
-namespace Maple2.File.Parser.Nif;
-public class EndianReader {
- public bool Swap { get; init; }
- public byte[] Data { get; init; }
- public int Index { get; private set; }
-
- public EndianReader(byte[] data, bool swap, int index = 0) {
- Swap = swap;
- Data = data;
- Index = index;
- }
-
- public bool ReadBool() {
- bool value = BitConverter.ToBoolean(Data, Index);
-
- Index += 1;
-
- return value;
- }
-
- public byte ReadByte() {
- byte value = Data[Index];
-
- Index += 1;
-
- return value;
- }
-
- public ushort ReadUInt16() {
- ushort value = BitConverter.ToUInt16(Data, Index);
-
- Index += 2;
-
- if (Swap) {
- return BinaryPrimitives.ReverseEndianness(value);
- }
-
- return value;
- }
-
- public uint ReadUInt32() {
- uint value = BitConverter.ToUInt32(Data, Index);
-
- Index += 4;
-
- if (Swap) {
- return BinaryPrimitives.ReverseEndianness(value);
- }
-
- return value;
- }
-
- public int ReadInt32() {
- int value = BitConverter.ToInt32(Data, Index);
-
- Index += 4;
-
- if (Swap) {
- return BinaryPrimitives.ReverseEndianness(value);
- }
-
- return value;
- }
-
- public ulong ReadUInt64() {
- ulong value = BitConverter.ToUInt64(Data, Index);
-
- Index += 8;
-
- if (Swap) {
- return BinaryPrimitives.ReverseEndianness(value);
- }
-
- return value;
- }
-
- public float ReadFloat32() {
- Span bytes = stackalloc byte[4] { Data[Index + 3], Data[Index + 2], Data[Index + 1], Data[Index] };
-
- if (Swap) {
- bytes.Reverse();
- }
-
- Index += 4;
-
- return BitConverter.ToSingle(bytes);
- }
-
- public string ReadString(int length) {
- string value = Encoding.UTF8.GetString(Data, Index, length);
-
- Index += length;
-
- return value;
- }
-
- public string ReadStringLen32() {
- int length = ReadInt32();
-
- if (length == 0) {
- return string.Empty;
- }
-
- string value = Encoding.UTF8.GetString(Data, Index, length);
-
- Index += length;
-
- return value;
- }
-
- // explicitly using 4x4 for matrix multiplication compatibility
- public Matrix4x4 ReadMatrix4x3() {
- Matrix4x4 matrix = new Matrix4x4();
-
- for (int column = 0; column < 3; ++column) {
- for (int row = 0; row < 3; ++row) {
- matrix[row, column] = ReadFloat32();
- }
- }
-
- // Translation
- matrix.M41 = ReadFloat32();
- matrix.M42 = ReadFloat32();
- matrix.M43 = ReadFloat32();
- matrix.M44 = 1;
-
- return matrix;
- }
-
- public Vector3 ReadVector3() {
- float x = ReadFloat32();
- float y = ReadFloat32();
- float z = ReadFloat32();
-
- return new Vector3(x, y, z);
- }
-
- public void Advance(int distance) {
- Index += distance;
- }
-}
diff --git a/Maple2.File.Parser/Nif/NiPhysXActorDesc.cs b/Maple2.File.Parser/Nif/NiPhysXActorDesc.cs
deleted file mode 100644
index 2c6f4dd..0000000
--- a/Maple2.File.Parser/Nif/NiPhysXActorDesc.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Maple2.File.Parser.Enum;
-using System.Numerics;
-
-namespace Maple2.File.Parser.Nif;
-
-public class NiPhysXActorDesc : NifBlock {
- public string ActorName;
- public List Poses;
- public NifBlock? BodyDesc;
- public float Density = 1;
- public NxActorFlag ActorFlags = NxActorFlag.None;
- public ushort ActorGroup = 0;
- public ushort DominanceGroup = 0;
- public uint ContactReportFlags = 0;
- public ushort ForceFieldMaterial = 0;
- public List ShapeDescriptions;
- public NiPhysXActorDesc? ActorParent;
- public NifBlock? Source;
- public NifBlock? Destination;
-
- public NiPhysXActorDesc(int blockIndex) : base("NiPhysXActorDesc", false, blockIndex) { }
-
- public override void Parse(NifDocument document) {
- base.Parse(document);
-
- ActorName = document.ReadString();
-
- int numPoses = document.Reader.ReadInt32();
-
- Poses = new List();
- Poses.EnsureCapacity(numPoses);
-
- for (int i = 0; i < numPoses; ++i) {
- Poses.Add(document.Reader.ReadMatrix4x3());
- }
-
- BodyDesc = document.ReadBlockRef();
- Density = document.Reader.ReadFloat32();
- ActorFlags = (NxActorFlag) document.Reader.ReadUInt32();
- ActorGroup = document.Reader.ReadUInt16();
- DominanceGroup = document.Reader.ReadUInt16();
- ContactReportFlags = document.Reader.ReadUInt32();
- ForceFieldMaterial = document.Reader.ReadUInt16();
- ShapeDescriptions = document.ReadBlockRefList();
- ActorParent = document.ReadBlockRef();
- Source = document.ReadBlockRef();
- Destination = document.ReadBlockRef();
- }
-}
-
diff --git a/Maple2.File.Parser/Nif/NiPhysXMeshDesc.cs b/Maple2.File.Parser/Nif/NiPhysXMeshDesc.cs
deleted file mode 100644
index fe1def6..0000000
--- a/Maple2.File.Parser/Nif/NiPhysXMeshDesc.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using Maple2.File.Parser.Enum;
-
-namespace Maple2.File.Parser.Nif;
-
-public class NiPhysXMeshDesc : NifBlock {
- public string MeshName;
- public byte[] MeshData;
- public NxMeshShapeFlags MeshFlags = NxMeshShapeFlags.None;
- public NxPagingMode PagingMode = NxPagingMode.Manual;
- public PhysXMeshFlags Flags = PhysXMeshFlags.None;
-
- public NiPhysXMeshDesc(int blockIndex) : base("NiPhysXMeshDesc", false, blockIndex) { }
-
- public override void Parse(NifDocument document) {
- base.Parse(document);
-
- MeshName = document.ReadString();
-
- int meshSize = document.Reader.ReadInt32();
-
- MeshData = new byte[meshSize];
-
- Buffer.BlockCopy(document.Reader.Data, document.Reader.Index, MeshData, 0, meshSize);
-
- document.Reader.Advance(meshSize);
-
- MeshFlags = (NxMeshShapeFlags) document.Reader.ReadInt32();
- PagingMode = (NxPagingMode) document.Reader.ReadInt32();
- Flags = (PhysXMeshFlags) document.Reader.ReadByte();
- }
-}
diff --git a/Maple2.File.Parser/Nif/NiPhysXProp.cs b/Maple2.File.Parser/Nif/NiPhysXProp.cs
deleted file mode 100644
index 76f28d3..0000000
--- a/Maple2.File.Parser/Nif/NiPhysXProp.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-namespace Maple2.File.Parser.Nif;
-
-public class NiPhysXProp : NifBlock {
- public List ExtraData; // NiExtraData
- public NifBlock? Controller = null; // NiTimeController
- public float PhysXToWorldScale = 1;
- public List Sources; // NiPhysXSrc
- public List Dests; // NiPhysXDest
- public List ModifiedMeshes; // NiMesh
- public bool KeepMeshes = false;
- public NiPhysXPropDesc? Snapshot = null;
-
- public NiPhysXProp(int blockIndex) : base("NiPhysXProp", true, blockIndex) { }
-
- public override void Parse(NifDocument document) {
- base.Parse(document);
-
- ExtraData = document.ReadBlockRefList();
- Controller = document.ReadBlockRef();
- PhysXToWorldScale = document.Reader.ReadFloat32();
- Sources = document.ReadBlockRefList();
- Dests = document.ReadBlockRefList();
- ModifiedMeshes = document.ReadBlockRefList();
- KeepMeshes = document.Reader.ReadBool();
- Snapshot = document.ReadBlockRef();
-
- document.PhysXProps.Add(this);
- }
-}
-
diff --git a/Maple2.File.Parser/Nif/NiPhysXPropDesc.cs b/Maple2.File.Parser/Nif/NiPhysXPropDesc.cs
deleted file mode 100644
index 48365b6..0000000
--- a/Maple2.File.Parser/Nif/NiPhysXPropDesc.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-namespace Maple2.File.Parser.Nif;
-
-public class NiPhysXPropDesc : NifBlock {
- public class StateString {
- public string String;
- public uint Value;
-
- public StateString(string key, uint value) {
- String = key;
- Value = value;
- }
- }
-
- public class State {
- public List Strings;
-
- public State() {
- Strings = new List();
- }
- }
-
- public List Actors;
- public List Joints;
- public List Clothes;
- public Dictionary Materials;
- public List StateNames;
- public byte Flags;
-
- public NiPhysXPropDesc(int blockIndex) : base("NiPhysXPropDesc", false, blockIndex) { }
-
- public override void Parse(NifDocument document) {
- base.Parse(document);
-
- Actors = document.ReadBlockRefList();
- Joints = document.ReadBlockRefList();
- Clothes = document.ReadBlockRefList();
- Materials = new Dictionary();
- StateNames = new List();
-
- uint numMaterials = document.Reader.ReadUInt32();
-
- for (uint i = 0; i < numMaterials; i++) {
- ushort key = document.Reader.ReadUInt16();
- NifBlock material = document.ReadBlockRef();
-
- Materials.Add(key, material);
- }
-
- uint numStates = document.Reader.ReadUInt32();
-
- StateNames.EnsureCapacity((int) numStates);
-
- for (uint i = 0; i < numStates; i++) {
- State state = new State();
-
- int numStrings = document.Reader.ReadInt32();
-
- state.Strings.EnsureCapacity((int) numStrings);
-
- for (int j = 0; j < numStrings; j++) {
- string key = document.ReadString();
- uint value = document.Reader.ReadUInt32();
-
- state.Strings.Add(new StateString(key, value));
- }
-
- StateNames.Add(state);
- }
-
- Flags = document.Reader.ReadByte();
- }
-}
diff --git a/Maple2.File.Parser/Nif/NiPhysXShapeDesc.cs b/Maple2.File.Parser/Nif/NiPhysXShapeDesc.cs
deleted file mode 100644
index bb4bac7..0000000
--- a/Maple2.File.Parser/Nif/NiPhysXShapeDesc.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using Maple2.File.Parser.Enum;
-using System.Numerics;
-
-namespace Maple2.File.Parser.Nif;
-
-public class NiPhysXShapeDesc : NifBlock {
- public NxShapeType ShapeType = NxShapeType.Plane;
- public NxShapeFlag Flags = NxShapeFlag.Visualization | NxShapeFlag.ClothTwoWay | NxShapeFlag.SoftBodyTwoWay;
- public Matrix4x4 LocalPose;
- public ushort CollisionGroup;
- public ushort MaterialIndex;
- public float Density = 1;
- public float Mass = 1;
- public float SkinWidth = 0.01f;
- public string ShapeName;
- public uint NonInteractingCompartment;
- public uint[] CollisionBits;
- public NiPhysXMeshDesc? Mesh;
- public Vector3 BoxHalfExtents;
-
- public NiPhysXShapeDesc(int blockIndex) : base("NiPhysXShapeDesc", false, blockIndex) {
- CollisionBits = new uint[4];
- }
-
- public override void Parse(NifDocument document) {
- base.Parse(document);
-
- ShapeType = (NxShapeType) document.Reader.ReadUInt32();
- Flags = (NxShapeFlag) document.Reader.ReadUInt32();
- LocalPose = document.Reader.ReadMatrix4x3();
- CollisionGroup = document.Reader.ReadUInt16();
- MaterialIndex = document.Reader.ReadUInt16();
- Density = document.Reader.ReadFloat32();
- Mass = document.Reader.ReadFloat32();
- SkinWidth = document.Reader.ReadFloat32();
- ShapeName = document.ReadString();
- NonInteractingCompartment = document.Reader.ReadUInt32();
-
- for (int i = 0; i < 4; ++i) {
- CollisionBits[i] = document.Reader.ReadUInt32();
- }
-
- switch (ShapeType) {
- case NxShapeType.Box:
- BoxHalfExtents = document.Reader.ReadVector3();
- break;
- case NxShapeType.Mesh:
- case NxShapeType.Convex:
- Mesh = document.ReadBlockRef();
- break;
- default:
- throw new NotSupportedException($"Unsupported NiPhysXShapeDesc.ShapeType found: {ShapeType}");
- }
- }
-}
-
diff --git a/Maple2.File.Parser/Nif/NifBlock.cs b/Maple2.File.Parser/Nif/NifBlock.cs
deleted file mode 100644
index 24027ae..0000000
--- a/Maple2.File.Parser/Nif/NifBlock.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace Maple2.File.Parser.Nif;
-
-public class NifBlock {
- public string BlockType { get; init; }
- public bool HasName { get; init; }
- public int BlockIndex { get; init; }
- public string Name;
-
- public NifBlock(string blockType, bool hasName, int blockIndex) {
- BlockType = blockType;
- HasName = hasName;
- BlockIndex = blockIndex;
- Name = string.Empty;
- }
-
- public virtual void Parse(NifDocument document) {
- if (HasName) {
- Name = document.ReadString();
- }
-
- document.Reading(this);
- }
-}
diff --git a/Maple2.File.Parser/Nif/NifDocument.cs b/Maple2.File.Parser/Nif/NifDocument.cs
deleted file mode 100644
index efeffdb..0000000
--- a/Maple2.File.Parser/Nif/NifDocument.cs
+++ /dev/null
@@ -1,263 +0,0 @@
-using System.Text;
-
-namespace Maple2.File.Parser.Nif;
-
-public class NifDocument {
- private readonly byte[] fileData;
- private NifDocumentHeader header;
- public EndianReader Reader { get; private set; }
- public string RelPath { get; init; }
- private NifBlock?[] blocks;
- public NifBlock? ReadingBlock { get; private set; }
-
- public List PhysXProps { get; init; }
- public string VersionString { get => header.HeaderString; }
-
- public NifDocument(string relpath, byte[] fileData) {
- PhysXProps = new List();
- this.fileData = fileData;
- Reader = new EndianReader(Array.Empty(), false);
- blocks = Array.Empty();
- header = new NifDocumentHeader();
- RelPath = relpath;
- }
-
- private int ReadHeaderString() {
- int index = 0;
- int headerStringLength = 0;
-
- while (headerStringLength < fileData.Length && fileData[headerStringLength] != 0x0A) {
- headerStringLength++;
- }
-
- header.HeaderString = Encoding.UTF8.GetString(fileData, 0, headerStringLength);
-
- index += headerStringLength + 1;
-
- int versionStart = headerStringLength;
-
- while (versionStart - 1 > 0 && (fileData[versionStart - 1] == '.' || (fileData[versionStart - 1] >= '0' && fileData[versionStart - 1] <= '9')))
- --versionStart;
-
- for (int i = 0; i < 4; ++i) {
- int versionEnd = versionStart;
-
- while (versionEnd < headerStringLength && fileData[versionEnd] != '.')
- ++versionEnd;
-
- string versionText = Encoding.UTF8.GetString(fileData, versionStart, versionEnd - versionStart);
-
- header.Version[i] = ushort.Parse(versionText);
-
- versionStart = versionEnd + 1;
- }
-
- return index;
- }
-
- public NifBlock? GetBlock(int index) {
- if (index == -1) {
- return null;
- }
-
- if (blocks[index] is not null) {
- return blocks[index];
- }
-
- NifBlock block;
- string blockType = header.BlockTypes[header.BlockTypeIndices[index]];
-
- switch (blockType) {
- case "NiPhysXProp":
- block = new NiPhysXProp(index);
-
- break;
- case "NiPhysXPropDesc":
- block = new NiPhysXPropDesc(index);
-
- break;
- case "NiPhysXActorDesc":
- block = new NiPhysXActorDesc(index);
-
- break;
- case "NiPhysXShapeDesc":
- block = new NiPhysXShapeDesc(index);
-
- break;
- case "NiPhysXMeshDesc":
- block = new NiPhysXMeshDesc(index);
-
- break;
- default:
- block = new NifBlock(blockType, false, index);
-
- break;
- }
-
- blocks[index] = block;
-
- return block;
- }
-
- public T? GetBlock(int index) {
- if (index == -1) {
- return default;
- }
-
- NifBlock? block = GetBlock(index);
-
- if (block is T nifBlock) {
- return nifBlock;
- }
-
- throw new InvalidCastException($"Invalid block handle <{typeof(T).Name}> referenced block {index}");
- }
-
- public T? ReadBlockRef() {
- int index = Reader.ReadInt32();
-
- if (index != -1) {
- return GetBlock(index);
- }
-
- return default;
- }
-
- public List ReadBlockRefList() {
- List blocks = new List();
-
- int count = Reader.ReadInt32();
-
- blocks.EnsureCapacity(count);
-
- for (int i = 0; i < count; ++i) {
- T? block = ReadBlockRef();
-
- if (block is null) {
- throw new InvalidCastException($"Null/invalid block handle in block list <{typeof(T).Name}> of size {count}");
- }
-
- blocks.Add(block);
- }
-
- return blocks;
- }
-
- public string ReadString() {
- uint stringIndex = Reader.ReadUInt32();
-
- return header.Strings[stringIndex];
- }
-
- public void Reading(NifBlock block) {
- ReadingBlock = block;
- }
-
- public bool Parse() {
- int index = ReadHeaderString();
-
- if (header.Version[0] < 30) {
- Console.WriteLine(RelPath);
- Console.WriteLine($"NIF version number too low: {header.HeaderString}. Parser is built for v30+"); // is it possible to do warnings?
-
- return false;
- }
-
- index += 4;
-
- bool isLittleEndian = fileData[index] != 0;
-
- Reader = new EndianReader(fileData, isLittleEndian != BitConverter.IsLittleEndian, index + 1);
-
- uint userVersion = Reader.ReadUInt32();
- int numBlocks = Reader.ReadInt32();
- int metaBlockSize = Reader.ReadInt32();
-
- Reader.Advance(metaBlockSize);
-
- ushort numBlockTypes = Reader.ReadUInt16();
-
- if (numBlockTypes == 0) {
- return true;
- }
-
- header.BlockTypes = new string[numBlockTypes];
- header.BlockTypeIndices = new ushort[numBlocks];
- header.BlockSizes = new int[numBlocks];
- blocks = new NifBlock?[numBlocks];
-
- for (uint i = 0; i < numBlockTypes; i++) {
- header.BlockTypes[i] = Reader.ReadStringLen32();
- }
-
- for (uint i = 0; i < numBlocks; i++) {
- header.BlockTypeIndices[i] = (ushort) (0x7FFFU & Reader.ReadUInt16());
- }
-
- for (uint i = 0; i < numBlocks; i++) {
- header.BlockSizes[i] = Reader.ReadInt32();
- }
-
- uint numStrings = Reader.ReadUInt32();
- uint maxStringLength = Reader.ReadUInt32();
-
- header.Strings = new string[numStrings];
-
- for (uint i = 0; i < numStrings; i++) {
- header.Strings[i] = Reader.ReadStringLen32();
- }
-
- uint numGroups = Reader.ReadUInt32();
-
- if (numGroups > 0) {
- throw new NotSupportedException("NIF groups aren't currently supported");
- }
-
- for (int i = 0; i < numBlocks; ++i) {
- string blockType = header.BlockTypes[header.BlockTypeIndices[i]];
- int blockSize = header.BlockSizes[i];
-
- int blockStart = Reader.Index;
-
-
- NifBlock? block = GetBlock(i);
-
- block?.Parse(this);
-
- int readBytes = Reader.Index - blockStart;
-
- if (readBytes != 0 && readBytes != blockSize) {
- throw new TypeLoadException($"Failed to read in the proper block size for type {blockType} index {i}; read {readBytes}, block size: {blockSize}");
- }
-
- ReadingBlock = null;
-
- if (readBytes == 0) {
- Reader.Advance(blockSize);
- }
- }
-
- return true;
- }
-
- void ParseNiPhysXProp(uint blockIndex) {
-
- }
-
- void ParseNiPhysXPropDesc(uint blockIndex) {
-
- }
-
- void ParseNiPhysXActorDesc(uint blockIndex) {
-
- }
-
- void ParseNiPhysXShapeDesc(uint blockIndex) {
-
- }
-
- void ParseNiPhysXMeshDesc(uint blockIndex) {
-
- }
-}
-
diff --git a/Maple2.File.Parser/Nif/NifDocumentHeader.cs b/Maple2.File.Parser/Nif/NifDocumentHeader.cs
deleted file mode 100644
index 093510f..0000000
--- a/Maple2.File.Parser/Nif/NifDocumentHeader.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace Maple2.File.Parser.Nif;
-
-public struct NifDocumentHeader {
- public string HeaderString;
- public ushort[] Version;
- public string[] BlockTypes;
- public ushort[] BlockTypeIndices;
- public int[] BlockSizes;
- public string[] Strings;
-
- public NifDocumentHeader() {
- HeaderString = string.Empty;
- Version = new ushort[4];
- BlockTypes = Array.Empty();
- BlockTypeIndices = Array.Empty();
- BlockSizes = Array.Empty();
- Strings = Array.Empty();
- }
-}
diff --git a/Maple2.File.Parser/Nif/NifM2dArchive.cs b/Maple2.File.Parser/Nif/NifM2dArchive.cs
deleted file mode 100644
index 11d23b0..0000000
--- a/Maple2.File.Parser/Nif/NifM2dArchive.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Maple2.File.IO;
-
-namespace Maple2.File.Parser.Nif;
-
-public class NifM2dArchive {
- public string PathPrefix { get; init; }
- public M2dReader M2dReader { get; init; }
-
- public NifM2dArchive(string pathPrefix, M2dReader m2dReader) {
- PathPrefix = pathPrefix;
- M2dReader = m2dReader;
- }
-}
diff --git a/Maple2.File.Parser/Nif/PhysXMesh.cs b/Maple2.File.Parser/Nif/PhysXMesh.cs
deleted file mode 100644
index 94b7466..0000000
--- a/Maple2.File.Parser/Nif/PhysXMesh.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-using Maple2.File.Parser.Enum;
-using System.Numerics;
-using System.Text;
-
-namespace Maple2.File.Parser.Nif;
-
-public struct PhysXMeshFace {
- public uint Vert0;
- public uint Vert1;
- public uint Vert2;
-
- public PhysXMeshFace(uint vert0 = 0, uint vert1 = 0, uint vert2 = 0) {
- Vert0 = vert0;
- Vert1 = vert1;
- Vert2 = vert2;
- }
-}
-
-public class PhysXMesh {
- public NxsMeshType Type { get; init; }
- public List Vertices { get; init; }
- public List Faces { get; init; }
-
- public PhysXMesh(byte[] data) {
- Vertices = new List();
- Faces = new List();
-
- Type = ParseNxsMesh(data);
- }
-
- private NxsMeshType ParseNxsMesh(byte[] data) {
- if (data.Length < 8) {
- throw new InvalidDataException("PhysX mesh data too small to fit header");
- }
-
- string headerPiece1 = Encoding.UTF8.GetString(data, 0, 3);
- string headerPiece2 = Encoding.UTF8.GetString(data, 4, 4);
-
- if (headerPiece1 != "NXS") {
- throw new InvalidDataException($"Invalid header found in PhysX mesh data: {Encoding.UTF8.GetString(data, 0, 8)}");
- }
-
- switch (headerPiece2) {
- case "CVXM":
- return ParseConvexMesh(data);
- case "MESH":
- return ParseTriangleMesh(data);
- case "CLTH":
- throw new NotSupportedException($"Cloth mesh not supported! Found unsupported PhysX cloth mesh in mesh data");
- default:
- throw new InvalidDataException($"Unknown PhysX nxs mesh type {headerPiece2} found in mesh data");
- }
- }
-
- private NxsMeshType ParseConvexMesh(byte[] data) {
- EndianReader reader = new EndianReader(data, !BitConverter.IsLittleEndian, 8);
-
- uint unk1 = reader.ReadUInt32();
- uint unk2 = reader.ReadUInt32();
-
- bool unkDataSectionMatches = false;
-
- unkDataSectionMatches |= data[reader.Index + 0] == 'I';
- unkDataSectionMatches |= data[reader.Index + 0] == 'C';
- unkDataSectionMatches |= data[reader.Index + 0] == 'E';
- unkDataSectionMatches |= data[reader.Index + 0] == 1;
- unkDataSectionMatches |= data[reader.Index + 0] == 'C';
- unkDataSectionMatches |= data[reader.Index + 0] == 'L';
- unkDataSectionMatches |= data[reader.Index + 0] == 'H';
- unkDataSectionMatches |= data[reader.Index + 0] == 'L';
-
- if (!unkDataSectionMatches) {
- throw new InvalidDataException("Unknown PhysX convex mesh data layout");
- }
-
- reader.Advance(8);
-
- uint unk3 = reader.ReadUInt32();
-
- unkDataSectionMatches = false;
-
- unkDataSectionMatches |= data[reader.Index + 0] == 'I';
- unkDataSectionMatches |= data[reader.Index + 0] == 'C';
- unkDataSectionMatches |= data[reader.Index + 0] == 'E';
- unkDataSectionMatches |= data[reader.Index + 0] == 1;
-
- if (!unkDataSectionMatches) {
- throw new InvalidDataException("Unknown PhysX convex mesh data layout");
- }
-
- reader.Advance(4);
-
- uint unk4 = reader.ReadUInt32();
- uint unk5 = reader.ReadUInt32();
-
- int vertexCount = reader.ReadInt32();
- int faceCount = reader.ReadInt32();
-
- uint unk6 = reader.ReadUInt32();
- uint unk7 = reader.ReadUInt32();
- uint unk8 = reader.ReadUInt32();
- uint unk9 = reader.ReadUInt32();
-
- Vertices.EnsureCapacity(vertexCount);
- Faces.EnsureCapacity(faceCount);
-
- for (int i = 0; i < vertexCount; ++i) {
- Vertices.Add(reader.ReadVector3());
- }
-
- uint unk10 = reader.ReadUInt32();
-
- for (int i = 0; i < faceCount; ++i) {
- PhysXMeshFace face;
-
- if (vertexCount < 0x100) {
- face = new PhysXMeshFace(
- reader.ReadByte(),
- reader.ReadByte(),
- reader.ReadByte()
- );
- } else if (vertexCount < 0x10000) {
- face = new PhysXMeshFace(
- reader.ReadUInt16(),
- reader.ReadUInt16(),
- reader.ReadUInt16()
- );
- } else {
- face = new PhysXMeshFace(
- reader.ReadUInt32(),
- reader.ReadUInt32(),
- reader.ReadUInt32()
- );
- }
-
- Faces.Add(face);
-
- if (face.Vert0 > vertexCount || face.Vert1 > vertexCount || face.Vert2 > vertexCount) {
- throw new IndexOutOfRangeException($"PhysX mesh data may be out of alignment for convex mesh format. Face index found out of bounds [{face.Vert0}, {face.Vert1}, {face.Vert2} with {vertexCount} vertices");
- }
- }
-
- // There is more data, but none that is mesh relevant as far as I can tell
-
- return NxsMeshType.Convex;
- }
-
- private NxsMeshType ParseTriangleMesh(byte[] data) {
- EndianReader reader = new EndianReader(data, !BitConverter.IsLittleEndian, 8);
-
- uint unk1 = reader.ReadUInt32();
- uint unk2 = reader.ReadUInt32();
- float unk3 = reader.ReadFloat32();
- ulong unk4 = reader.ReadUInt64();
-
- if (unk4 != 0xFF || unk1 != 1) {
- throw new InvalidDataException("Unknown PhysX triangle mesh data format");
- }
-
- int vertexCount = reader.ReadInt32();
- int faceCount = reader.ReadInt32();
-
- Vertices.EnsureCapacity(vertexCount);
- Faces.EnsureCapacity(faceCount);
-
- for (int i = 0; i < vertexCount; ++i) {
- Vertices.Add(reader.ReadVector3());
- }
-
- for (int i = 0; i < faceCount; ++i) {
- PhysXMeshFace face;
-
- if (vertexCount < 0x100) {
- face = new PhysXMeshFace(
- reader.ReadByte(),
- reader.ReadByte(),
- reader.ReadByte()
- );
- } else if (vertexCount < 0x10000) {
- face = new PhysXMeshFace(
- reader.ReadUInt16(),
- reader.ReadUInt16(),
- reader.ReadUInt16()
- );
- } else {
- face = new PhysXMeshFace(
- reader.ReadUInt32(),
- reader.ReadUInt32(),
- reader.ReadUInt32()
- );
- }
-
- Faces.Add(face);
-
- if (face.Vert0 > vertexCount || face.Vert1 > vertexCount || face.Vert2 > vertexCount) {
- throw new IndexOutOfRangeException($"PhysX mesh data may be out of alignment for triangle mesh format. Face index found out of bounds [{face.Vert0}, {face.Vert1}, {face.Vert2} with {vertexCount} vertices");
- }
- }
-
- // There is more data, but none that is mesh relevant as far as I can tell
-
- return NxsMeshType.Triangle;
- }
-}