在过去的几天里,我一直在创建一个程序,该程序将从我的专用服务器托管游戏服务器。用户输入哪个 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:
- 音乐
- 地图
- d2dm01.wad
- 地图01
- d2dm02.wad
- 地图02
- d2dm03.wad
- 地图03
- d2dm01.wad
- 额外的
我不知道如何在不逐一提取它们并检查 for 循环中的级别的情况下访问 pk3 内的 wads 内的文件。诚然,我也不知道自己在做什么,所以我想知道的是如何读取 pk3 中的文件并获取地图(map01、map02、map03)。
此外,如果有人知道读取和解析文件中的字节以获取信息的好资源,那将非常有帮助。我现在觉得很无语。