diff --git a/LibBSP/Source/Structs/BSP/BSP.cs b/LibBSP/Source/Structs/BSP/BSP.cs index 60e314e..01a46b1 100644 --- a/LibBSP/Source/Structs/BSP/BSP.cs +++ b/LibBSP/Source/Structs/BSP/BSP.cs @@ -53,6 +53,10 @@ public enum MapType : int /// Half-Life Blue Shift /// BlueShift = 0x01010001, + /// + /// Quake BSP2 + /// + BSP2 = 0x01000001, /// /// Quake 2 or Quake 2 Engine flags, including diff --git a/LibBSP/Source/Structs/BSP/BSPHeader.cs b/LibBSP/Source/Structs/BSP/BSPHeader.cs index 18fd4b3..e2fe884 100644 --- a/LibBSP/Source/Structs/BSP/BSPHeader.cs +++ b/LibBSP/Source/Structs/BSP/BSPHeader.cs @@ -9,7 +9,10 @@ namespace LibBSP /// public struct BSPHeader { - + /// + /// "BSP2" represented as int32. + /// + public const int BSP2Header = 844124994; /// /// "IBSP" represented as int32. /// @@ -421,7 +424,11 @@ public static byte[] GetMagic(MapType type) case MapType.Quake: { return BitConverter.GetBytes(29); - } + } + case MapType.BSP2: + { + return BitConverter.GetBytes(BSP2Header); + } case MapType.GoldSrc: case MapType.BlueShift: { diff --git a/LibBSP/Source/Structs/BSP/Edge.cs b/LibBSP/Source/Structs/BSP/Edge.cs index dd56f02..a7dae13 100644 --- a/LibBSP/Source/Structs/BSP/Edge.cs +++ b/LibBSP/Source/Structs/BSP/Edge.cs @@ -83,7 +83,11 @@ public int FirstVertexIndex { get { - if (MapType == MapType.Vindictus) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return (int)BitConverter.ToUInt32(Data, 0); + } + else if (MapType == MapType.Vindictus) { return BitConverter.ToInt32(Data, 0); } @@ -99,8 +103,11 @@ public int FirstVertexIndex set { byte[] bytes = BitConverter.GetBytes(value); - - if (MapType == MapType.Vindictus) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + BitConverter.GetBytes((uint)value).CopyTo(Data, 0); + } + else if (MapType == MapType.Vindictus) { bytes.CopyTo(Data, 0); } @@ -132,7 +139,11 @@ public int SecondVertexIndex { get { - if (MapType == MapType.Vindictus) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return (int)BitConverter.ToUInt32(Data, 4); + } + else if (MapType == MapType.Vindictus) { return BitConverter.ToInt32(Data, 4); } @@ -149,7 +160,11 @@ public int SecondVertexIndex { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.Vindictus) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + BitConverter.GetBytes((uint)value).CopyTo(Data, 4); + } + else if (MapType == MapType.Vindictus) { BitConverter.GetBytes(value).CopyTo(Data, 4); } @@ -252,7 +267,11 @@ public static Lump LumpFactory(byte[] data, BSP bsp, LumpInfo lumpInfo) /// This struct is not valid or is not implemented for the given and . public static int GetStructLength(MapType mapType, int lumpVersion = 0) { - if (mapType == MapType.Vindictus) + if (mapType.IsSubtypeOf(MapType.BSP2)) + { + return 8; + } + else if (mapType == MapType.Vindictus) { return 8; } diff --git a/LibBSP/Source/Structs/BSP/Face.cs b/LibBSP/Source/Structs/BSP/Face.cs index 9ed3b78..c95ec2c 100644 --- a/LibBSP/Source/Structs/BSP/Face.cs +++ b/LibBSP/Source/Structs/BSP/Face.cs @@ -109,7 +109,11 @@ public int PlaneIndex { get { - if (MapType == MapType.Nightfire + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return BitConverter.ToInt32(Data, 0); + } + else if (MapType == MapType.Nightfire || MapType == MapType.Vindictus) { return BitConverter.ToInt32(Data, 0); @@ -128,14 +132,17 @@ public int PlaneIndex { return BitConverter.ToUInt16(Data, 0); } - return -1; } set { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.Nightfire + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + bytes.CopyTo(Data, 0); + } + else if (MapType == MapType.Nightfire || MapType == MapType.Vindictus) { bytes.CopyTo(Data, 0); @@ -167,8 +174,12 @@ public bool PlaneSide { get { - if (MapType.IsSubtypeOf(MapType.Quake) - || MapType.IsSubtypeOf(MapType.Quake2)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return BitConverter.ToUInt32(Data, 4) > 0; + } + else if (MapType.IsSubtypeOf(MapType.Quake) + || MapType.IsSubtypeOf(MapType.Quake2)) { return BitConverter.ToUInt16(Data, 2) > 0; } @@ -193,7 +204,11 @@ public bool PlaneSide } set { - if (MapType == MapType.Vindictus) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + BitConverter.GetBytes(value ? 1 : 0).CopyTo(Data, 4); + } + else if (MapType == MapType.Vindictus) { Data[4] = (byte)(value ? 1 : 0); } @@ -287,7 +302,11 @@ public int FirstEdgeIndexIndex { get { - if (MapType == MapType.Source17) + if (MapType == MapType.BSP2) + { + return BitConverter.ToInt32(Data, 8); + } + else if(MapType == MapType.Source17) { return BitConverter.ToInt32(Data, 36); } @@ -312,7 +331,11 @@ public int FirstEdgeIndexIndex { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.Source17) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + bytes.CopyTo(Data, 8); + } + else if (MapType == MapType.Source17) { bytes.CopyTo(Data, 36); } @@ -342,7 +365,11 @@ public int NumEdgeIndices { get { - if (MapType == MapType.Source17) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return BitConverter.ToInt32(Data, 12); + } + else if (MapType == MapType.Source17) { return BitConverter.ToUInt16(Data, 40); } @@ -367,7 +394,11 @@ public int NumEdgeIndices { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.Source17) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + bytes.CopyTo(Data, 12); + } + else if (MapType == MapType.Source17) { Data[40] = bytes[0]; Data[41] = bytes[1]; @@ -602,7 +633,7 @@ public TextureInfo TextureInfo { get { - return Parent.Bsp.TextureInfo[TextureInfoIndex]; + return Parent.Bsp.TextureInfo[TextureInfoIndex]; } } @@ -613,7 +644,11 @@ public int TextureInfoIndex { get { - if (MapType == MapType.Nightfire) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return BitConverter.ToInt32(Data, 16); + } + else if (MapType == MapType.Nightfire) { return BitConverter.ToInt32(Data, 32); } @@ -634,14 +669,17 @@ public int TextureInfoIndex { return BitConverter.ToUInt16(Data, 10); } - return -1; } set { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.Nightfire) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + bytes.CopyTo(Data, 16); + } + else if (MapType == MapType.Nightfire) { bytes.CopyTo(Data, 32); } @@ -1087,7 +1125,13 @@ public byte[] LightmapStyles { get { - if (MapType == MapType.SiN) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + byte[] bytes = new byte[4]; + Array.Copy(Data, 20, bytes, 0, 4); + return bytes; + } + else if(MapType == MapType.SiN) { byte[] bytes = new byte[16]; Array.Copy(Data, 12, bytes, 0, bytes.Length); @@ -1148,7 +1192,12 @@ public byte[] LightmapStyles } set { - if (MapType == MapType.SiN) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + Array.Copy(value, 0, Data, 20, Math.Min(value.Length, 4)); + } + + else if (MapType == MapType.SiN) { Array.Copy(value, 0, Data, 12, Math.Min(value.Length, 16)); } @@ -1248,7 +1297,11 @@ public int Lightmap { get { - if (MapType == MapType.Raven) + if (MapType == MapType.BSP2) + { + return BitConverter.ToInt32(Data, 24); + } + else if(MapType == MapType.Raven) { return BitConverter.ToInt32(Data, 36); } @@ -1301,7 +1354,12 @@ public int Lightmap { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.Raven) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + bytes.CopyTo(Data, 24); + } + + else if (MapType == MapType.Raven) { bytes.CopyTo(Data, 36); } @@ -2188,7 +2246,11 @@ public static Lump LumpFactory(byte[] data, BSP bsp, LumpInfo lumpInfo) /// This struct is not valid or is not implemented for the given and . public static int GetStructLength(MapType mapType, int lumpVersion = 0) { - if (mapType == MapType.CoD4) + if (mapType.IsSubtypeOf(MapType.BSP2)) + { + return 28; + } + else if(mapType == MapType.CoD4) { return 24; } diff --git a/LibBSP/Source/Structs/BSP/Leaf.cs b/LibBSP/Source/Structs/BSP/Leaf.cs index f340cbf..33f71b3 100644 --- a/LibBSP/Source/Structs/BSP/Leaf.cs +++ b/LibBSP/Source/Structs/BSP/Leaf.cs @@ -223,7 +223,11 @@ public Vector3 Minimums { get { - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + return new Vector3(BitConverter.ToSingle(Data, 8), BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 16)); + } + else if (MapType == MapType.SoF) { return new Vector3(BitConverter.ToInt16(Data, 10), BitConverter.ToInt16(Data, 12), BitConverter.ToInt16(Data, 14)); } @@ -250,7 +254,13 @@ public Vector3 Minimums } set { - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + BitConverter.GetBytes((float)value.X()).CopyTo(Data, 8); + BitConverter.GetBytes((float)value.Y()).CopyTo(Data, 12); + BitConverter.GetBytes((float)value.Z()).CopyTo(Data, 16); + } + else if (MapType == MapType.SoF) { BitConverter.GetBytes((short)value.X()).CopyTo(Data, 10); BitConverter.GetBytes((short)value.Y()).CopyTo(Data, 12); @@ -290,7 +300,11 @@ public Vector3 Maximums { get { - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + return new Vector3(BitConverter.ToSingle(Data, 20), BitConverter.ToSingle(Data, 24), BitConverter.ToSingle(Data, 28)); + } + else if (MapType == MapType.SoF) { return new Vector3(BitConverter.ToInt16(Data, 16), BitConverter.ToInt16(Data, 18), BitConverter.ToInt16(Data, 20)); } @@ -317,7 +331,13 @@ public Vector3 Maximums } set { - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + BitConverter.GetBytes((float)value.X()).CopyTo(Data, 20); + BitConverter.GetBytes((float)value.Y()).CopyTo(Data, 24); + BitConverter.GetBytes((float)value.Z()).CopyTo(Data, 28); + } + else if (MapType == MapType.SoF) { BitConverter.GetBytes((short)value.X()).CopyTo(Data, 16); BitConverter.GetBytes((short)value.Y()).CopyTo(Data, 18); @@ -530,7 +550,11 @@ public int FirstMarkFaceIndex { get { - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + return (int)BitConverter.ToUInt32(Data, 32); + } + else if (MapType == MapType.SoF) { return BitConverter.ToUInt16(Data, 22); } @@ -556,7 +580,11 @@ public int FirstMarkFaceIndex { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + BitConverter.GetBytes((uint)value).CopyTo(Data, 32); + } + else if (MapType == MapType.SoF) { Data[22] = bytes[0]; Data[23] = bytes[1]; @@ -588,7 +616,11 @@ public int NumMarkFaceIndices { get { - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + return (int)BitConverter.ToUInt32(Data, 36); + } + else if (MapType == MapType.SoF) { return BitConverter.ToUInt16(Data, 24); } @@ -614,7 +646,11 @@ public int NumMarkFaceIndices { byte[] bytes = BitConverter.GetBytes(value); - if (MapType == MapType.SoF) + if (MapType == MapType.BSP2) + { + BitConverter.GetBytes((uint)value).CopyTo(Data, 36); + } + else if (MapType == MapType.SoF) { Data[24] = bytes[0]; Data[25] = bytes[1]; @@ -645,7 +681,11 @@ public byte WaterSoundLevel { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return Data[40]; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return Data[24]; } @@ -654,7 +694,11 @@ public byte WaterSoundLevel } set { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType == MapType.BSP2) + { + Data[40] = value; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[24] = value; } @@ -668,7 +712,11 @@ public byte SkySoundLevel { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return Data[41]; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return Data[25]; } @@ -677,7 +725,11 @@ public byte SkySoundLevel } set { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType == MapType.BSP2) + { + Data[41] = value; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[25] = value; } @@ -691,7 +743,11 @@ public byte SlimeSoundLevel { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return Data[42]; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return Data[26]; } @@ -700,7 +756,11 @@ public byte SlimeSoundLevel } set { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType == MapType.BSP2) + { + Data[42] = value; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[26] = value; } @@ -714,7 +774,11 @@ public byte LavaSoundLevel { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return Data[43]; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return Data[27]; } @@ -723,7 +787,11 @@ public byte LavaSoundLevel } set { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType == MapType.BSP2) + { + Data[43] = value; + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[27] = value; } @@ -975,7 +1043,11 @@ public static Lump LumpFactory(byte[] data, BSP bsp, LumpInfo lumpInfo) /// This struct is not valid or is not implemented for the given and . public static int GetStructLength(MapType mapType, int lumpVersion = 0) { - if (mapType == MapType.CoD4) + if (mapType == MapType.BSP2) + { + return 44; + } + else if (mapType == MapType.CoD4) { return 24; } diff --git a/LibBSP/Source/Structs/BSP/Node.cs b/LibBSP/Source/Structs/BSP/Node.cs index 854161a..3a4d4eb 100644 --- a/LibBSP/Source/Structs/BSP/Node.cs +++ b/LibBSP/Source/Structs/BSP/Node.cs @@ -117,7 +117,11 @@ public int Child1Index { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return BitConverter.ToInt32(Data, 4); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return BitConverter.ToInt16(Data, 4); } @@ -135,7 +139,11 @@ public int Child1Index { byte[] bytes = BitConverter.GetBytes(value); - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + bytes.CopyTo(Data, 4); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[4] = bytes[0]; Data[5] = bytes[1]; @@ -173,7 +181,11 @@ public int Child2Index { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return BitConverter.ToInt32(Data, 8); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return BitConverter.ToInt16(Data, 6); } @@ -191,7 +203,11 @@ public int Child2Index { byte[] bytes = BitConverter.GetBytes(value); - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + bytes.CopyTo(Data, 8); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[6] = bytes[0]; Data[7] = bytes[1]; @@ -213,7 +229,11 @@ public Vector3 Minimums { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return new Vector3(BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 16), BitConverter.ToSingle(Data, 20)); + } + else if(MapType.IsSubtypeOf(MapType.Quake)) { return new Vector3(BitConverter.ToInt16(Data, 8), BitConverter.ToInt16(Data, 10), BitConverter.ToInt16(Data, 12)); } @@ -231,12 +251,18 @@ public Vector3 Minimums { return Vector3Extensions.ToVector3(Data, 12); } - + return new Vector3(0, 0, 0); } set { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + BitConverter.GetBytes((float)value.X()).CopyTo(Data, 12); + BitConverter.GetBytes((float)value.Y()).CopyTo(Data, 16); + BitConverter.GetBytes((float)value.Z()).CopyTo(Data, 20); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { BitConverter.GetBytes((short)value.X()).CopyTo(Data, 8); BitConverter.GetBytes((short)value.Y()).CopyTo(Data, 10); @@ -270,7 +296,11 @@ public Vector3 Maximums { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return new Vector3(BitConverter.ToSingle(Data, 24), BitConverter.ToSingle(Data, 28), BitConverter.ToSingle(Data, 32)); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return new Vector3(BitConverter.ToInt16(Data, 14), BitConverter.ToInt16(Data, 16), BitConverter.ToInt16(Data, 18)); } @@ -293,7 +323,13 @@ public Vector3 Maximums } set { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + BitConverter.GetBytes((float)value.X()).CopyTo(Data, 24); + BitConverter.GetBytes((float)value.Y()).CopyTo(Data, 28); + BitConverter.GetBytes((float)value.Z()).CopyTo(Data, 32); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { BitConverter.GetBytes((short)value.X()).CopyTo(Data, 14); BitConverter.GetBytes((short)value.Y()).CopyTo(Data, 16); @@ -342,7 +378,11 @@ public int FirstFaceIndex { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return (int)BitConverter.ToUInt32(Data, 36); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return BitConverter.ToUInt16(Data, 20); } @@ -362,7 +402,11 @@ public int FirstFaceIndex { byte[] bytes = BitConverter.GetBytes(value); - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + BitConverter.GetBytes((uint)value).CopyTo(Data, 36); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[20] = bytes[0]; Data[21] = bytes[1]; @@ -388,7 +432,11 @@ public int NumFaceIndices { get { - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + return (int)BitConverter.ToUInt32(Data, 40); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { return BitConverter.ToUInt16(Data, 22); } @@ -408,7 +456,11 @@ public int NumFaceIndices { byte[] bytes = BitConverter.GetBytes(value); - if (MapType.IsSubtypeOf(MapType.Quake)) + if (MapType.IsSubtypeOf(MapType.BSP2)) + { + BitConverter.GetBytes((uint)value).CopyTo(Data, 40); + } + else if (MapType.IsSubtypeOf(MapType.Quake)) { Data[22] = bytes[0]; Data[23] = bytes[1]; @@ -547,7 +599,11 @@ public static Lump LumpFactory(byte[] data, BSP bsp, LumpInfo lumpInfo) /// This struct is not valid or is not implemented for the given and . public static int GetStructLength(MapType mapType, int lumpVersion = 0) { - if (mapType.IsSubtypeOf(MapType.Quake)) + if (mapType.IsSubtypeOf(MapType.BSP2)) + { + return 44; + } + else if (mapType.IsSubtypeOf(MapType.Quake)) { return 24; } diff --git a/LibBSP/Source/Structs/Common/Lumps/NumList.cs b/LibBSP/Source/Structs/Common/Lumps/NumList.cs index a1333d9..b8bbe72 100644 --- a/LibBSP/Source/Structs/Common/Lumps/NumList.cs +++ b/LibBSP/Source/Structs/Common/Lumps/NumList.cs @@ -178,7 +178,12 @@ public byte[] GetBytes(int lumpOffset = 0) /// Index for this lump, or -1 if the format doesn't have this lump or it's not implemented. public static int GetIndexForLeafFacesLump(MapType version, out DataType dataType) { - if (version == MapType.Nightfire) + if (version == MapType.BSP2) + { + dataType = DataType.UInt32; + return 11; + } + else if (version == MapType.Nightfire) { dataType = DataType.UInt32; return 12; diff --git a/LibBSP/Source/Util/BSPReader.cs b/LibBSP/Source/Util/BSPReader.cs index 190b3ba..d08d09c 100644 --- a/LibBSP/Source/Util/BSPReader.cs +++ b/LibBSP/Source/Util/BSPReader.cs @@ -315,6 +315,11 @@ private MapType GetVersion(bool bigEndian) } switch (num) { + case BSPHeader.BSP2Header: + { + current = MapType.BSP2; + break; + } case BSPHeader.IBSPHeader: { // Versions: CoD, CoD2, CoD4, Quake 2, Daikatana, Quake 3 (RtCW), Soldier of Fortune