0

UnpackTool

This commit is contained in:
2019-03-21 13:49:44 +03:00
parent 62707869a1
commit acab8db4fc
2 changed files with 133 additions and 3 deletions

View File

@@ -0,0 +1,103 @@
package lwjake2;
import lombok.Value;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.*;
@Slf4j
@UtilityClass
public class UnpackTool {
private static final String READ_ONLY = "r";
private static Map<String, Entry> listPakFiles = new HashMap<>();
private static Map<String, RandomAccessFile> pakFiles = new HashMap<>();
private static RandomAccessFile getPak(String pakName) {
RandomAccessFile raf;
if (!pakFiles.containsKey(pakName)) {
try {
raf = new RandomAccessFile(pakName, READ_ONLY);
} catch (FileNotFoundException e) {
log.error("Read file error: {}", e.getMessage());
raf = null;
}
pakFiles.put(pakName, raf);
} else {
raf = pakFiles.get(pakName);
}
return raf;
}
public static void add(Entry entry) {
listPakFiles.put(entry.getName(), entry);
}
public static void printList() {
listPakFiles.values().stream()
.sorted((o1, o2) -> {
final int result = o1.getPakName().compareTo(o2.getPakName());
if (result == 0) {
return o1.getName().compareTo(o2.getName());
} else {
return result;
}
})
.forEach(entry -> log.info("{}: {}", entry.getPakName(), entry.getName()));
}
public static Collection<Entry> list() {
return listPakFiles.values();
}
public static Entry get(String name) {
return listPakFiles.get(name);
}
@Value
public static class Entry {
private String name;
private int pos;
private long size;
private String pakName;
public Entry(String name, int pos, long size, String pakName) {
int idx;
if ((idx = name.indexOf('\0')) != -1) {
this.name = name.substring(0, idx);
} else {
this.name = name;
}
this.pos = pos;
this.size = size;
this.pakName = pakName;
}
public byte[] getBytes() throws IOException {
RandomAccessFile pak = UnpackTool.getPak(pakName);
if (pak == null) {
return null;
}
pak.seek(pos);
byte[] result = new byte[(int) size];
if (result.length < size) {
log.error("Can't cast long to int: size too big for intValue");
return null;
}
pak.readFully(result);
return result;
}
}
}

View File

@@ -22,12 +22,14 @@ import lombok.extern.slf4j.Slf4j;
import lwjake2.Defines;
import lwjake2.ErrorCode;
import lwjake2.Globals;
import lwjake2.UnpackTool;
import lwjake2.game.Cmd;
import lwjake2.game.cvar_t;
import lwjake2.sys.Sys;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
@@ -487,7 +489,7 @@ public class BaseQ2FileSystem implements FileSystem {
* Takes an explicit (not game tree related) path to a pak file.
*
* Loads the header and directory, adding the files at the beginning of the
* list so they override previous pack files.
* printList so they override previous pack files.
*/
private pack_t loadPackFile(String packfile) {
dpackheader_t header;
@@ -538,6 +540,12 @@ public class BaseQ2FileSystem implements FileSystem {
entry.filelen = packhandle.getInt();
newfiles.put(entry.name.toLowerCase(), entry);
UnpackTool.add(new UnpackTool.Entry(
entry.name,
entry.filepos,
entry.filelen,
packfile
));
}
} catch (IOException e) {
@@ -564,7 +572,6 @@ public class BaseQ2FileSystem implements FileSystem {
*/
private void addGameDirectory(String dir) {
int i;
searchpath_t search;
pack_t pak;
String pakfile;
@@ -573,7 +580,7 @@ public class BaseQ2FileSystem implements FileSystem {
//
// add the directory to the search path
// ensure fs_userdir is first in searchpath
search = new searchpath_t();
searchpath_t search = new searchpath_t();
search.filename = dir;
if (fs_searchpaths != null) {
search.next = fs_searchpaths.next;
@@ -600,6 +607,26 @@ public class BaseQ2FileSystem implements FileSystem {
search.next = fs_searchpaths;
fs_searchpaths = search;
}
UnpackTool.printList();
final File baseq2UnpackDir = new File(dir, "_unpack");
baseq2UnpackDir.mkdirs();
UnpackTool.list().forEach(entry -> {
File file = new File(baseq2UnpackDir, entry.getName());
if (file.exists()) {
return;
}
file.getParentFile().mkdirs();
try (FileOutputStream fos = new FileOutputStream(file)) {
log.info("Write '{}'...", entry.getName());
fos.write(entry.getBytes());
} catch (IOException e) {
log.error("Can't write file '{}': {}", entry.getName(), e.getMessage());
}
});
}
/*