eaglercraft-1.5/epkcompiler/src/CompilePackage.java
2022-08-03 22:47:19 -07:00

170 lines
4.8 KiB
Java

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import com.jcraft.jzlib.CRC32;
import com.jcraft.jzlib.Deflater;
import com.jcraft.jzlib.DeflaterOutputStream;
import com.jcraft.jzlib.GZIPOutputStream;
public class CompilePackage {
private static ArrayList<File> files = new ArrayList();
public static void main(String[] args) throws IOException {
if(args.length < 2 || args.length > 4) {
System.out.println("Usage: java -jar CompilePackage.jar <input directory> <output file> [gzip|zlib|none] [file-type]");
return;
}
File root = new File(args[0]);
File output = new File(args[1]);
char compressionType;
if(args.length > 2) {
if(args[2].equalsIgnoreCase("gzip")) {
compressionType = 'G';
}else if(args[2].equalsIgnoreCase("zlib")) {
compressionType = 'Z';
}else if(args[2].equalsIgnoreCase("none")) {
compressionType = '0';
}else {
throw new IllegalArgumentException("Unknown compression method: " + args[2]);
}
}else {
compressionType = 'G';
}
listDirectory(root);
ByteArrayOutputStream osb = new ByteArrayOutputStream();
String start = root.getAbsolutePath();
osb.write("EAGPKG$$".getBytes(Charset.forName("UTF-8")));
String chars = "ver2.0";
osb.write(chars.length());
osb.write(chars.getBytes(StandardCharsets.US_ASCII));
Date d = new Date();
String comment = "\n\n # Eagler EPK v2.0 (c) " + (new SimpleDateFormat("yyyy")).format(d) + " Calder Young\n" +
" # update: on " + (new SimpleDateFormat("MM/dd/yyyy")).format(d) + " at " +
(new SimpleDateFormat("hh:mm:ss aa")).format(d) + "\n\n";
String nm = output.getName();
osb.write(nm.length());
osb.write(nm.getBytes(StandardCharsets.US_ASCII));
writeShort(comment.length(), osb);
osb.write(comment.getBytes(StandardCharsets.US_ASCII));
writeLong(d.getTime(), osb);
writeInt(files.size() + 1, osb);
osb.write(compressionType);
OutputStream os;
if(compressionType == 'G') {
os = new GZIPOutputStream(osb, new Deflater(9, 15+16), 16384, true);
}else if(compressionType == 'Z') {
os = new DeflaterOutputStream(osb, new Deflater(9), 16384, true);
}else {
os = osb;
}
os.write("HEAD".getBytes(StandardCharsets.US_ASCII));
String key = "file-type";
os.write(key.length());
os.write(key.getBytes(StandardCharsets.US_ASCII));
String value;
if(args.length > 3) {
value = args[3];
}else {
value = "epk/resources";
}
writeInt(value.length(), os);
os.write(value.getBytes(StandardCharsets.US_ASCII));
os.write('>');
CRC32 checkSum = new CRC32();
for(File f : files) {
InputStream stream = new FileInputStream(f);
byte[] targetArray = new byte[(int)f.length()];
stream.read(targetArray);
stream.close();
checkSum.reset();
checkSum.update(targetArray, 0, targetArray.length);
int ch = (int)checkSum.getValue();
os.write("FILE".getBytes(StandardCharsets.US_ASCII));
String p = f.getAbsolutePath().replace(start, "").replace('\\', '/');
if(p.startsWith("/")) {
p = p.substring(1);
}
os.write(p.length());
os.write(p.getBytes(StandardCharsets.US_ASCII));
writeInt(targetArray.length + 5, os);
writeInt(ch, os);
os.write(targetArray);
os.write(':');
os.write('>');
}
os.write("END$".getBytes(StandardCharsets.US_ASCII));
os.close();
osb.write(":::YEE:>".getBytes(StandardCharsets.US_ASCII));
FileOutputStream out = new FileOutputStream(output);
out.write(osb.toByteArray());
out.close();
}
public static void writeShort(int i, OutputStream os) throws IOException {
os.write((i >> 8) & 0xFF);
os.write(i & 0xFF);
}
public static void writeInt(int i, OutputStream os) throws IOException {
os.write((i >> 24) & 0xFF);
os.write((i >> 16) & 0xFF);
os.write((i >> 8) & 0xFF);
os.write(i & 0xFF);
}
public static void writeLong(long i, OutputStream os) throws IOException {
os.write((int)((i >> 56) & 0xFF));
os.write((int)((i >> 48) & 0xFF));
os.write((int)((i >> 40) & 0xFF));
os.write((int)((i >> 32) & 0xFF));
os.write((int)((i >> 24) & 0xFF));
os.write((int)((i >> 16) & 0xFF));
os.write((int)((i >> 8) & 0xFF));
os.write((int)(i & 0xFF));
}
public static void listDirectory(File dir) {
for(File f : dir.listFiles()) {
if(f.isDirectory()) {
listDirectory(f);
}else {
files.add(f);
}
}
}
}