mirror of
https://github.com/celisej567/LibBSP.git
synced 2026-09-23 20:08:40 +03:00
Move source into /Source rather than /src. Some documentation cleanup.
This commit is contained in:
142
LibBSP/Source/Structs/BSP/Lumps/GameLump.cs
Normal file
142
LibBSP/Source/Structs/BSP/Lumps/GameLump.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace LibBSP {
|
||||
public enum GameLumpType : int {
|
||||
sprp = 1936749168,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class containing the identification and information for the various Game Lumps in Source
|
||||
/// engine BSPs. The only one we're really concerned with is the Static Props.
|
||||
/// </summary>
|
||||
public class GameLump : Dictionary<GameLumpType, GameLump.GameLumpInfo> {
|
||||
|
||||
public struct GameLumpInfo {
|
||||
public ushort flags;
|
||||
public ushort version;
|
||||
public int offset;
|
||||
public int length;
|
||||
}
|
||||
|
||||
private byte[] _rawData;
|
||||
private int _gameLumpOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Byte array representing the raw data read from the BSP for the game lump
|
||||
/// </summary>
|
||||
public byte[] rawData {
|
||||
get {
|
||||
return _rawData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The amount to subtract from all the <c>GameLumpInfo.offset</c> values to find the offset relative to the start of the Game Lump data. May be 0.
|
||||
/// </summary>
|
||||
public int gameLumpOffset {
|
||||
get {
|
||||
return _gameLumpOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c>GameLump</c> object by parsing a <c>byte</c> array into a <c>Dictionary</c> of <c>GameLumpInfo</c> objects.
|
||||
/// These objects contain offsets, lengths and versions of the GameLump lumps.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to parse</param>
|
||||
/// <param name="type">The map type</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="data" /> was null</exception>
|
||||
/// <exception cref="ArgumentException">This structure is not implemented for the given maptype</exception>
|
||||
public GameLump(byte[] data, MapType type) {
|
||||
if (data == null) {
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
_rawData = data;
|
||||
|
||||
int structLength = 0;
|
||||
switch (type) {
|
||||
case MapType.Vindictus:
|
||||
case MapType.TacticalInterventionEncrypted:
|
||||
case MapType.Source17:
|
||||
case MapType.Source18:
|
||||
case MapType.Source19:
|
||||
case MapType.Source20:
|
||||
case MapType.Source21:
|
||||
case MapType.Source22:
|
||||
case MapType.Source23:
|
||||
case MapType.Source27: {
|
||||
structLength = 16;
|
||||
break;
|
||||
}
|
||||
case MapType.DMoMaM: {
|
||||
structLength = 20;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new ArgumentException("Map type " + type + " isn't supported by the GameLump class.");
|
||||
}
|
||||
}
|
||||
|
||||
int numGameLumps = BitConverter.ToInt32(data, 0);
|
||||
if (numGameLumps > 0) {
|
||||
int headerLength = 4 + (numGameLumps * structLength);
|
||||
int lowestLumpOffset = Int32.MaxValue;
|
||||
|
||||
for (int i = 0; i < numGameLumps; ++i) {
|
||||
GameLumpInfo info = new GameLumpInfo {
|
||||
flags = BitConverter.ToUInt16(data, (i * structLength) + 8),
|
||||
version = BitConverter.ToUInt16(data, (i * structLength) + 10),
|
||||
offset = BitConverter.ToInt32(data, (i * structLength) + 14),
|
||||
length = BitConverter.ToInt32(data, (i * structLength) + 18),
|
||||
};
|
||||
this[(GameLumpType)BitConverter.ToInt32(data, (i * structLength) + 4)] = info;
|
||||
|
||||
if (info.offset < lowestLumpOffset) {
|
||||
lowestLumpOffset = info.offset;
|
||||
}
|
||||
}
|
||||
|
||||
// If the offset values are given relative to the beginning of the lump, this should give 0.
|
||||
_gameLumpOffset = lowestLumpOffset - headerLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passes a <c>byte</c> array into the constructor for <c>GameLump</c>.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to parse</param>
|
||||
/// <param name="type">The map type</param>
|
||||
/// <returns>A new <c>GameLump</c> object</returns>
|
||||
/// <remarks>This is only here for consistency with the other lump structures.</remarks>
|
||||
public static GameLump LumpFactory(byte[] data, MapType type) {
|
||||
return new GameLump(data, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index for this lump in the BSP file for a specific map format.
|
||||
/// </summary>
|
||||
/// <param name="type">The map type</param>
|
||||
/// <returns>Index for this lump, or -1 if the format doesn't have this lump</returns>
|
||||
public static int GetIndexForLump(MapType type) {
|
||||
switch (type) {
|
||||
case MapType.Vindictus:
|
||||
case MapType.TacticalInterventionEncrypted:
|
||||
case MapType.Source17:
|
||||
case MapType.Source18:
|
||||
case MapType.Source19:
|
||||
case MapType.Source20:
|
||||
case MapType.Source21:
|
||||
case MapType.Source22:
|
||||
case MapType.Source23:
|
||||
case MapType.Source27:
|
||||
case MapType.DMoMaM: {
|
||||
return 35;
|
||||
}
|
||||
default: {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
LibBSP/Source/Structs/BSP/Lumps/SourceDispVertices.cs
Normal file
58
LibBSP/Source/Structs/BSP/Lumps/SourceDispVertices.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace LibBSP {
|
||||
/// <summary>
|
||||
/// Class representing a group of <c>SourceDispVertex</c> objects. Contains helpful methods to handle Displacement Vertices in the <c>List</c>
|
||||
/// </summary>
|
||||
public class SourceDispVertices : List<SourceDispVertex> {
|
||||
|
||||
/// <summary>
|
||||
/// Parses the passed <c>byte</c> array into a <c>List</c> of <c>SourceDispVertices</c>
|
||||
/// </summary>
|
||||
/// <param name="data">Array of <c>byte</c>s to parse</param>
|
||||
/// <param name="type">Format identifier</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="data" /> was null</exception>
|
||||
public SourceDispVertices(byte[] data, MapType type) : base(data.Length / 20) {
|
||||
if (data == null) {
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
int structLength = 20;
|
||||
byte[] bytes = new byte[structLength];
|
||||
for (int i = 0; i < data.Length / structLength; ++i) {
|
||||
Array.Copy(data, (i * structLength), bytes, 0, structLength);
|
||||
Add(new SourceDispVertex(bytes, type));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets enough vertices from the list for a displacement of power <paramref name="power" />, starting at <paramref name="first" />.
|
||||
/// </summary>
|
||||
/// <param name="first">The first vertex to get</param>
|
||||
/// <param name="power">The power of the displacement</param>
|
||||
/// <returns>Array of <c>SourceDispVertex</c> objects containing all the vertices in this displacement</returns>
|
||||
public virtual SourceDispVertex[] GetVerticesInDisplacement(int first, int power) {
|
||||
int numVerts = 0;
|
||||
switch (power) {
|
||||
case 2: {
|
||||
numVerts = 25;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
numVerts = 81;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
numVerts = 289;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SourceDispVertex[] ret = new SourceDispVertex[numVerts];
|
||||
for (int i = 0; i < numVerts; ++i) {
|
||||
ret[i] = this[first + i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
47
LibBSP/Source/Structs/BSP/Lumps/SourceStaticProps.cs
Normal file
47
LibBSP/Source/Structs/BSP/Lumps/SourceStaticProps.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace LibBSP {
|
||||
/// <summary>
|
||||
/// List of <c>SourceStaticProp</c> objects containing data relevant to Static Props, like the dictionary of actual model paths.
|
||||
/// </summary>
|
||||
public class SourceStaticProps : List<SourceStaticProp> {
|
||||
|
||||
public string[] dictionary { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parses the passed <c>byte</c> array into a <c>List</c> of <c>SourceStaticProp</c> objects
|
||||
/// </summary>
|
||||
/// <param name="data">Array of <c>byte</c>s to parse</param>
|
||||
/// <param name="type">Format identifier</param>
|
||||
/// <param name="version">Version of static prop lump this is</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="data" /> was null</exception>
|
||||
public SourceStaticProps(byte[] data, MapType type, int version) {
|
||||
if (data == null) {
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
int structLength = 0;
|
||||
string[] dictionary = new string[0];
|
||||
if (data.Length > 0) {
|
||||
int offset = 0;
|
||||
dictionary = new string[BitConverter.ToInt32(data, 0)];
|
||||
for (int i = 0; i < dictionary.Length; ++i) {
|
||||
byte[] temp = new byte[128];
|
||||
Array.Copy(data, (i * 128) + 4, temp, 0, 128);
|
||||
dictionary[i] = temp.ToNullTerminatedString();
|
||||
}
|
||||
int numLeafDefinitions = BitConverter.ToInt32(data, (dictionary.Length * 128) + 4);
|
||||
int numProps = BitConverter.ToInt32(data, (dictionary.Length * 128) + (numLeafDefinitions * 2) + 8);
|
||||
if (numProps > 0) {
|
||||
structLength = (data.Length - ((dictionary.Length * 128) + (numLeafDefinitions * 2) + 12)) / numProps;
|
||||
byte[] bytes = new byte[structLength];
|
||||
for (int i = 0; i < numProps; ++i) {
|
||||
Array.Copy(data, (dictionary.Length * 128) + (numLeafDefinitions * 2) + 12 + (i * structLength), bytes, 0, structLength);
|
||||
Add(new SourceStaticProp(bytes, type, version));
|
||||
offset += structLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
138
LibBSP/Source/Structs/BSP/Lumps/Textures.cs
Normal file
138
LibBSP/Source/Structs/BSP/Lumps/Textures.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace LibBSP {
|
||||
/// <summary>
|
||||
/// <c>List</c><<c>Texture</c>> with some useful methods for manipulating <c>Texture</c> objects,
|
||||
/// especially when handling them as a group.
|
||||
/// </summary>
|
||||
public class Textures : List<Texture> {
|
||||
|
||||
/// <summary>
|
||||
/// Parses a <c>byte</c> array into this <c>List</c> of <c>Texture</c> objects
|
||||
/// </summary>
|
||||
/// <param name="data">The data to parse</param>
|
||||
/// <param name="type">The map type</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="data" /> was null</exception>
|
||||
/// <exception cref="ArgumentException">This structure is not implemented for the given maptype</exception>
|
||||
public Textures(byte[] data, MapType type) {
|
||||
if (data == null) {
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
int structLength = 0;
|
||||
switch (type) {
|
||||
case MapType.Nightfire: {
|
||||
structLength = 64;
|
||||
break;
|
||||
}
|
||||
case MapType.Quake3:
|
||||
case MapType.Raven:
|
||||
case MapType.CoD:
|
||||
case MapType.CoD2:
|
||||
case MapType.CoD4: {
|
||||
structLength = 72;
|
||||
break;
|
||||
}
|
||||
case MapType.Quake2:
|
||||
case MapType.Daikatana:
|
||||
case MapType.SoF:
|
||||
case MapType.STEF2:
|
||||
case MapType.STEF2Demo:
|
||||
case MapType.FAKK: {
|
||||
structLength = 76;
|
||||
break;
|
||||
}
|
||||
case MapType.MOHAA: {
|
||||
structLength = 140;
|
||||
break;
|
||||
}
|
||||
case MapType.SiN: {
|
||||
structLength = 180;
|
||||
break;
|
||||
}
|
||||
case MapType.Source17:
|
||||
case MapType.Source18:
|
||||
case MapType.Source19:
|
||||
case MapType.Source20:
|
||||
case MapType.Source21:
|
||||
case MapType.Source22:
|
||||
case MapType.Source23:
|
||||
case MapType.Source27:
|
||||
case MapType.TacticalInterventionEncrypted:
|
||||
case MapType.Vindictus:
|
||||
case MapType.DMoMaM: {
|
||||
int offset = 0;
|
||||
byte[] bytes;
|
||||
for (int i = 0; i < data.Length; ++i) {
|
||||
if (data[i] == (byte)0x00) {
|
||||
// They are null-terminated strings, of non-constant length (not padded)
|
||||
bytes = new byte[i - offset];
|
||||
Array.Copy(data, offset, bytes, 0, i - offset);
|
||||
Add(new Texture(bytes, type));
|
||||
offset = i + 1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case MapType.Quake: {
|
||||
int numElements = BitConverter.ToInt32(data, 0);
|
||||
structLength = 40;
|
||||
byte[] bytes = new byte[structLength];
|
||||
for (int i = 0; i < numElements; ++i) {
|
||||
Array.Copy(data, BitConverter.ToInt32(data, (i + 1) * 4), bytes, 0, structLength);
|
||||
Add(new Texture(bytes, type));
|
||||
}
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
throw new ArgumentException("Map type " + type + " isn't supported by the Node class.");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
byte[] bytes = new byte[structLength];
|
||||
for (int i = 0; i < data.Length / structLength; ++i) {
|
||||
Array.Copy(data, (i * structLength), bytes, 0, structLength);
|
||||
Add(new Texture(bytes, type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the texture at the specified offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">Lump offset of the texture name to find</param>
|
||||
/// <returns>The name of the texture at offset <paramref name="offset" />, or null if it doesn't exist</returns>
|
||||
public string GetTextureAtOffset(uint offset) {
|
||||
int current = 0;
|
||||
for (int i = 0; i < Count; ++i) {
|
||||
if (current < offset) {
|
||||
// Add 1 for the missing null byte.
|
||||
current += this[i].name.Length + 1;
|
||||
} else {
|
||||
return this[i].name;
|
||||
}
|
||||
}
|
||||
// If we get to this point, the strings ended before target offset was reached
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the offset of the specified texture name.
|
||||
/// </summary>
|
||||
/// <param name="inTexture">The texture name to find in the lump</param>
|
||||
/// <returns>The offset of the specified texture, or -1 if it wasn't found</returns>
|
||||
public int GetOffsetOf(string inTexture) {
|
||||
int offset = 0;
|
||||
for (int i = 0; i < Count; ++i) {
|
||||
if (this[i].name.Equals(inTexture, StringComparison.CurrentCultureIgnoreCase)) {
|
||||
return offset;
|
||||
} else {
|
||||
offset += this[i].name.Length + 1;
|
||||
}
|
||||
}
|
||||
// If we get here, the requested texture didn't exist.
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user