我花了几天时间创建了一个程序,它将从我的专用服务器托管游戏服务器。用户输入哪个WAD / PK3(存储地图信息,音乐等的文件),以及其他几个东西,并且能够托管服务器。
我有一个朋友制作了一个方法,该方法将通过WAD文件并收集信息,然后调用getLevelNames()并返回数组中的级别名称,然后将其添加到服务器主机命令行,添加适当的地图。
以下是我认为重要的代码部分:
public static byte[] getByteArrayFromFile(String filePath) throws IOException {
return Files.readAllBytes(new File(filePath).toPath());
}
/**
* Given a path to the file, this will extract the information into a byte array,
* and then it will read it, index the file locations and pass the appropriate byte
* data to other objects which will index the data in a useful way that the engine
* can read/use.
* Ideally after the data has been passed and indexed, the Wad object should be nullified and
* set for garbage collection.
* @param path The full path on the disk to the wad to be read from
* @throws IOException If the path to the file has an error
*/
public Wad(String path) throws IOException {
// Load wad data
wadData = ByteData.getByteArrayFromFile(path);
// Setup pointers
headerType = ByteData.bytesToString(Arrays.copyOfRange(wadData, 0, 4));
headerTotalLumps = ByteData.bytesToInt(wadData[4], wadData[5], wadData[6], wadData[7]);
headerPointerToDirectory = ByteData.bytesToInt(wadData[8], wadData[9], wadData[10], wadData[11]);
System.out.println("Wad data: " + headerType + ", " + headerTotalLumps + " total lumps, " + headerPointerToDirectory + " directory offset");
// Setup offset data
parseDirectory();
getLevelNames();
}
public void getLevelNames() {
String[] temp = new String[lumpName.length]; // Maybe I can divide this by 2, or 5 or something to save space since they all shouldn't be a map...
Arrays.fill(temp, "");
int tempIndex = 0;
List<String> listMapNames = Arrays.asList(lumpMapNames);
for (int i = 0; i < lumpName.length; i++)
// Make sure: 1) were not at an end piece, 2) its actually a marker, 3) the next lump contains a map file (like SEGS), 4) The marker itself isn't something like an empty reject table, 5) doesn't contain GL_xyzab
if (i != lumpName.length - 1 && fileSize[i] == 0 && listMapNames.contains(lumpName[i+1]) && !listMapNames.contains(lumpName[i]) && !lumpName[i].startsWith("GL_")) {
temp[tempIndex] = lumpName[i];
tempIndex++;
}
// If there's no levels
if (tempIndex == 0) {
levelNames = new String[0];
return;
}
levelNames = new String[tempIndex]; // We should be at levels + 1, or at least a proper length
for (int j = 0; j < tempIndex; j++)
levelNames[j] = temp[j];
// Sort the array just to make the server execution cleaner
Arrays.sort(levelNames);
}
private void parseDirectory() {
fileOffset = new int[headerTotalLumps];
fileSize = new int[headerTotalLumps];
lumpName = new String[headerTotalLumps];
int c = 0; // Counter for starting at index 0 and going upwards
System.out.println("Pointer: " + headerPointerToDirectory + ", total length: " + wadData.length + ", difference = " + (wadData.length - headerPointerToDirectory));
for (int off = headerPointerToDirectory; off < wadData.length; off += 16) {
fileOffset[c] = ByteData.bytesToInt(wadData[off], wadData[off+1], wadData[off+2], wadData[off+3]);
fileSize[c] = ByteData.bytesToInt(wadData[off+4], wadData[off+5], wadData[off+6], wadData[off+7]);
lumpName[c] = new String(Arrays.copyOfRange(wadData, off+8, off+16)).trim();
c++;
}
}
但是,我陷入了两难境地。由于PK3文件完全不同,因为它们基本上是.zip文件,它们为maps /目录中的每个地图存储单独的.WAD文件,我不知道我将如何访问它们。
以下是文件结构的示例:
我不知道如何在pk3内部的wads中访问文件,而不是逐个提取它们并检查for循环中的级别。不可否认,我也不知道自己在做什么,所以我想知道的是如何读取pk3中的文件并获取地图(map01,map02,map03)。
此外,如果有人知道读取和解析文件中的字节以获取信息的良好资源,那将非常有用。我现在感觉很无能。