Refactors to reuse some commonly used code. This changes a lot.

Refactor everything to use a base ILump interface, and a Lump class implementing it to use in place of regular List.
Refactor lump structures to use an ILumpObject interface. Eventually Lump<T> will enforce T is ILumpObject, there are some other things to do first.
Use Path class to simplify some code in BSP.
This commit is contained in:
wfowler
2019-07-16 02:55:07 -06:00
parent 43ebf69f01
commit 864a6dab6b
33 changed files with 2449 additions and 1627 deletions

View File

@@ -1,20 +1,51 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace LibBSP {
/// <summary>
/// Holds all the data for an edge in a BSP map.
/// </summary>
public struct Edge {
public struct Edge : ILumpObject {
public byte[] data;
public MapType type;
public int version;
/// <summary>
/// The <see cref="ILump"/> this <see cref="ILumpObject"/> came from.
/// </summary>
public ILump Parent { get; private set; }
/// <summary>
/// Array of <c>byte</c>s used as the data source for this <see cref="ILumpObject"/>.
/// </summary>
public byte[] Data { get; private set; }
/// <summary>
/// The <see cref="LibBSP.MapType"/> to use to interpret <see cref="Data"/>.
/// </summary>
public MapType MapType {
get {
if (Parent == null || Parent.Bsp == null) {
return MapType.Undefined;
}
return Parent.Bsp.version;
}
}
/// <summary>
/// The version number of the <see cref="ILump"/> this <see cref="ILumpObject"/> came from.
/// </summary>
public int LumpVersion {
get {
if (Parent == null) {
return 0;
}
return Parent.LumpInfo.version;
}
}
public int firstVertex {
get {
switch (type) {
switch (MapType) {
case MapType.Quake:
case MapType.SiN:
case MapType.Daikatana:
@@ -31,10 +62,10 @@ namespace LibBSP {
case MapType.DMoMaM:
case MapType.Quake2:
case MapType.SoF: {
return BitConverter.ToUInt16(data, 0);
return BitConverter.ToUInt16(Data, 0);
}
case MapType.Vindictus: {
return BitConverter.ToInt32(data, 0);
return BitConverter.ToInt32(Data, 0);
}
default: {
return -1;
@@ -43,7 +74,7 @@ namespace LibBSP {
}
set {
byte[] bytes = BitConverter.GetBytes(value);
switch (type) {
switch (MapType) {
case MapType.Quake:
case MapType.SiN:
case MapType.Daikatana:
@@ -60,12 +91,12 @@ namespace LibBSP {
case MapType.DMoMaM:
case MapType.Quake2:
case MapType.SoF: {
data[0] = bytes[0];
data[1] = bytes[1];
Data[0] = bytes[0];
Data[1] = bytes[1];
break;
}
case MapType.Vindictus: {
bytes.CopyTo(data, 0);
bytes.CopyTo(Data, 0);
break;
}
}
@@ -74,7 +105,7 @@ namespace LibBSP {
public int secondVertex {
get {
switch (type) {
switch (MapType) {
case MapType.Quake:
case MapType.SiN:
case MapType.Daikatana:
@@ -91,10 +122,10 @@ namespace LibBSP {
case MapType.DMoMaM:
case MapType.Quake2:
case MapType.SoF: {
return BitConverter.ToUInt16(data, 2);
return BitConverter.ToUInt16(Data, 2);
}
case MapType.Vindictus: {
return BitConverter.ToInt32(data, 4);
return BitConverter.ToInt32(Data, 4);
}
default: {
return -1;
@@ -103,7 +134,7 @@ namespace LibBSP {
}
set {
byte[] bytes = BitConverter.GetBytes(value);
switch (type) {
switch (MapType) {
case MapType.Quake:
case MapType.SiN:
case MapType.Daikatana:
@@ -120,12 +151,12 @@ namespace LibBSP {
case MapType.DMoMaM:
case MapType.Quake2:
case MapType.SoF: {
data[2] = bytes[0];
data[3] = bytes[1];
Data[2] = bytes[0];
Data[3] = bytes[1];
break;
}
case MapType.Vindictus: {
BitConverter.GetBytes(value).CopyTo(data, 4);
BitConverter.GetBytes(value).CopyTo(Data, 4);
break;
}
}
@@ -136,33 +167,42 @@ namespace LibBSP {
/// Creates a new <see cref="Edge"/> object from a <c>byte</c> array.
/// </summary>
/// <param name="data"><c>byte</c> array to parse.</param>
/// <param name="type">The map type.</param>
/// <param name="version">The version of this lump.</param>
/// <param name="parent">The <see cref="ILump"/> this <see cref="Edge"/> came from.</param>
/// <exception cref="ArgumentNullException"><paramref name="data"/> was <c>null</c>.</exception>
public Edge(byte[] data, MapType type, int version = 0) : this() {
public Edge(byte[] data, ILump parent = null) {
if (data == null) {
throw new ArgumentNullException();
}
this.data = data;
this.type = type;
this.version = version;
Data = data;
Parent = parent;
}
/// <summary>
/// Factory method to parse a <c>byte</c> array into a <c>List</c> of <see cref="Edge"/> objects.
/// Factory method to parse a <c>byte</c> array into a <see cref="Lump{Edge}"/>.
/// </summary>
/// <param name="data">The data to parse.</param>
/// <param name="type">The map type.</param>
/// <param name="version">The version of this lump.</param>
/// <returns>A <c>List</c> of <see cref="Edge"/> objects.</returns>
/// <exception cref="ArgumentNullException"><paramref name="data"/> was null.</exception>
/// <exception cref="ArgumentException">This structure is not implemented for the given maptype.</exception>
public static List<Edge> LumpFactory(byte[] data, MapType type, int version = 0) {
/// <param name="bsp">The <see cref="BSP"/> this lump came from.</param>
/// <param name="lumpInfo">The <see cref="LumpInfo"/> associated with this lump.</param>
/// <returns>A <see cref="Lump{Edge}"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="data"/> parameter was <c>null</c>.</exception>
public static Lump<Edge> LumpFactory(byte[] data, BSP bsp, LumpInfo lumpInfo) {
if (data == null) {
throw new ArgumentNullException();
}
int structLength = 0;
switch (type) {
return new Lump<Edge>(data, GetStructLength(bsp.version, lumpInfo.version), bsp, lumpInfo);
}
/// <summary>
/// Gets the length of this struct's data for the given <paramref name="mapType"/> and <paramref name="lumpVersion"/>.
/// </summary>
/// <param name="mapType">The <see cref="LibBSP.MapType"/> of the BSP.</param>
/// <param name="lumpVersion">The version number for the lump.</param>
/// <returns>The length, in <c>byte</c>s, of this struct.</returns>
/// <exception cref="ArgumentException">This struct is not valid or is not implemented for the given <paramref name="mapType"/> and <paramref name="lumpVersion"/>.</exception>
public static int GetStructLength(MapType mapType, int lumpVersion = 0) {
switch (mapType) {
case MapType.Quake:
case MapType.SiN:
case MapType.Daikatana:
@@ -179,25 +219,15 @@ namespace LibBSP {
case MapType.DMoMaM:
case MapType.Quake2:
case MapType.SoF: {
structLength = 4;
break;
return 4;
}
case MapType.Vindictus: {
structLength = 8;
break;
return 8;
}
default: {
throw new ArgumentException("Map type " + type + " isn't supported by the Edge lump factory.");
throw new ArgumentException("Lump object " + MethodBase.GetCurrentMethod().DeclaringType.Name + " does not exist in map type " + mapType + " or has not been implemented.");
}
}
int numObjects = data.Length / structLength;
List<Edge> lump = new List<Edge>(numObjects);
for (int i = 0; i < numObjects; ++i) {
byte[] bytes = new byte[structLength];
Array.Copy(data, (i * structLength), bytes, 0, structLength);
lump.Add(new Edge(bytes, type, version));
}
return lump;
}
/// <summary>