0

在过去的几天里,我一直在创建一个程序,该程序将从我的专用服务器托管游戏服务器。用户输入哪个 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,我不知道如何访问它们。

以下是文件结构的示例:

  1. 等级.pk3:
    • 音乐
    • 地图
      • d2dm01.wad
        • 地图01
      • d2dm02.wad
        • 地图02
      • d2dm03.wad
        • 地图03
    • 额外的

我不知道如何在不逐一提取它们并检查 for 循环中的级别的情况下访问 pk3 内的 wads 内的文件。诚然,我也不知道自己在做什么,所以我想知道的是如何读取 pk3 中的文件并获取地图(map01、map02、map03)。

此外,如果有人知道读取和解析文件中的字节以获取信息的好资源,那将非常有帮助。我现在觉得很无语。

4

0 回答 0