UnpackTool
This commit is contained in:
103
src/main/java/lwjake2/UnpackTool.java
Normal file
103
src/main/java/lwjake2/UnpackTool.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,12 +22,14 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import lwjake2.Defines;
|
import lwjake2.Defines;
|
||||||
import lwjake2.ErrorCode;
|
import lwjake2.ErrorCode;
|
||||||
import lwjake2.Globals;
|
import lwjake2.Globals;
|
||||||
|
import lwjake2.UnpackTool;
|
||||||
import lwjake2.game.Cmd;
|
import lwjake2.game.Cmd;
|
||||||
import lwjake2.game.cvar_t;
|
import lwjake2.game.cvar_t;
|
||||||
import lwjake2.sys.Sys;
|
import lwjake2.sys.Sys;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.nio.ByteBuffer;
|
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.
|
* 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
|
* 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) {
|
private pack_t loadPackFile(String packfile) {
|
||||||
dpackheader_t header;
|
dpackheader_t header;
|
||||||
@@ -538,6 +540,12 @@ public class BaseQ2FileSystem implements FileSystem {
|
|||||||
entry.filelen = packhandle.getInt();
|
entry.filelen = packhandle.getInt();
|
||||||
|
|
||||||
newfiles.put(entry.name.toLowerCase(), entry);
|
newfiles.put(entry.name.toLowerCase(), entry);
|
||||||
|
UnpackTool.add(new UnpackTool.Entry(
|
||||||
|
entry.name,
|
||||||
|
entry.filepos,
|
||||||
|
entry.filelen,
|
||||||
|
packfile
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -564,7 +572,6 @@ public class BaseQ2FileSystem implements FileSystem {
|
|||||||
*/
|
*/
|
||||||
private void addGameDirectory(String dir) {
|
private void addGameDirectory(String dir) {
|
||||||
int i;
|
int i;
|
||||||
searchpath_t search;
|
|
||||||
pack_t pak;
|
pack_t pak;
|
||||||
String pakfile;
|
String pakfile;
|
||||||
|
|
||||||
@@ -573,7 +580,7 @@ public class BaseQ2FileSystem implements FileSystem {
|
|||||||
//
|
//
|
||||||
// add the directory to the search path
|
// add the directory to the search path
|
||||||
// ensure fs_userdir is first in searchpath
|
// ensure fs_userdir is first in searchpath
|
||||||
search = new searchpath_t();
|
searchpath_t search = new searchpath_t();
|
||||||
search.filename = dir;
|
search.filename = dir;
|
||||||
if (fs_searchpaths != null) {
|
if (fs_searchpaths != null) {
|
||||||
search.next = fs_searchpaths.next;
|
search.next = fs_searchpaths.next;
|
||||||
@@ -600,6 +607,26 @@ public class BaseQ2FileSystem implements FileSystem {
|
|||||||
search.next = fs_searchpaths;
|
search.next = fs_searchpaths;
|
||||||
fs_searchpaths = search;
|
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());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user