mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-27 02:28:13 -05:00
Update #0 - First Release
This commit is contained in:
@ -0,0 +1,167 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.MergePullRequest;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.PullRequestTask;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CreateUnpatched;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InitTask;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.SetupWorkspace;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.TaskClean;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglerBuildTools {
|
||||
|
||||
public static File repositoryRoot = new File(".");
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Eaglercraft 1.8 Build Tools");
|
||||
System.out.println("Copyright (c) 2022 LAX1DUDE");
|
||||
System.out.println();
|
||||
|
||||
if(!System.getProperty("eaglercraft.isJava11", "false").equalsIgnoreCase("true")) {
|
||||
try {
|
||||
if (!(boolean) Class
|
||||
.forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java11Check", true,
|
||||
new URLClassLoader(new URL[] { (new File("buildtools/Java11Check.jar")).toURI().toURL() }))
|
||||
.getMethod("classLoadCheck").invoke(null)) {
|
||||
throw new RuntimeException("wtf?");
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: A minimum of Java 11 is required to run this tool!");
|
||||
System.err.println();
|
||||
System.err.println("You are using Java " + System.getProperty("java.version"));
|
||||
System.err.println();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(args.length == 0 || (args.length == 1 && args[0].equalsIgnoreCase("help"))) {
|
||||
System.out.println("Options:");
|
||||
System.out.println(" help - displays this message");
|
||||
System.out.println(" init - decompiles 1.8.8 and applies the main repo's patch files");
|
||||
System.out.println(" workspace - creates a dev workspace with a gradle project to compile the source");
|
||||
System.out.println(" pullrequest - scans changes in the dev workspace and creates patch files for pull requests");
|
||||
System.out.println(" pullrequest_test - makes new workspace and re-applies the patches in 'pullrequest'");
|
||||
System.out.println(" unpatched - creates a zip file with the vanilla minecraft source without patches");
|
||||
System.out.println(" merge - merges the patch files in the pullrequest folder with the repo's main patch files");
|
||||
System.out.println(" merge_direct - merges changes in the dev workspace with the repo's main patch files");
|
||||
System.out.println(" clean - delete init and pullrequest directories, keeps dev workspace");
|
||||
System.out.println();
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("init")) {
|
||||
LicensePrompt.display();
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(InitTask.initTask()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("workspace")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(SetupWorkspace.setupWorkspace()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("pullrequest")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(PullRequestTask.pullRequest()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("pullrequest_test")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(SetupWorkspace.pullRequestTest()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("unpatched")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(CreateUnpatched.createUnpatched()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("merge")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(MergePullRequest.mergeTask()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("merge_direct")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(MergePullRequest.mergeDirect()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else if(args.length == 1 && args[0].equalsIgnoreCase("clean")) {
|
||||
System.out.println("Running task '" + args[0] + "':");
|
||||
System.out.println();
|
||||
if(TaskClean.taskClean()) {
|
||||
System.out.println();
|
||||
System.out.println("Task Complete.");
|
||||
System.out.println();
|
||||
}else {
|
||||
System.err.println();
|
||||
System.err.println("Task Failed!");
|
||||
System.err.println();
|
||||
}
|
||||
}else {
|
||||
System.err.println("Invalid arguments!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglerBuildToolsConfig {
|
||||
|
||||
public static File temporary_directory = new File(System.getProperty("user.home"), ".eaglercraft_1.8_buildtools");
|
||||
private static boolean temporary_directory_isInit = false;
|
||||
private static boolean temporary_directory_mentioned = false;
|
||||
|
||||
public static File workspace_directory = new File("../eaglercraft_1.8_workspace");
|
||||
private static boolean workspace_directory_isInit = false;
|
||||
private static boolean workspace_directory_mentioned = false;
|
||||
|
||||
private static boolean config_file_loaded = false;
|
||||
|
||||
public static final File configFile = new File("./buildtools_config.json");
|
||||
|
||||
public static void load() {
|
||||
if(configFile.exists()) {
|
||||
try(FileInputStream is = new FileInputStream(configFile)) {
|
||||
byte[] r = new byte[(int)configFile.length()];
|
||||
is.read(r);
|
||||
is.close();
|
||||
String jsonTxt = new String(r, StandardCharsets.UTF_8);
|
||||
JSONObject obj = new JSONObject(jsonTxt);
|
||||
String path = obj.optString("temporary_directory", null);
|
||||
if(path != null) {
|
||||
temporary_directory = new File(path);
|
||||
temporary_directory_isInit = true;
|
||||
}
|
||||
path = obj.optString("workspace_directory", null);
|
||||
if(path != null) {
|
||||
workspace_directory = new File(path);
|
||||
workspace_directory_isInit = true;
|
||||
}
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("Failed to read config!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
JSONObject obj = new JSONObject();
|
||||
if(temporary_directory_isInit) obj.put("temporary_directory", temporary_directory.getAbsolutePath());
|
||||
if(workspace_directory_isInit) obj.put("workspace_directory", workspace_directory.getAbsoluteFile());
|
||||
try(FileOutputStream os = new FileOutputStream(configFile)) {
|
||||
os.write(obj.toString(4).getBytes(StandardCharsets.UTF_8));
|
||||
os.close();
|
||||
}catch(IOException e) {
|
||||
System.err.println("Failed to write config!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void mentionConfigPath() {
|
||||
System.out.println("Edit '" + configFile.getName() + "' to change");
|
||||
}
|
||||
|
||||
public static File getTemporaryDirectory() {
|
||||
if(!config_file_loaded) {
|
||||
load();
|
||||
config_file_loaded = true;
|
||||
}
|
||||
if(!temporary_directory_isInit) {
|
||||
File f = temporary_directory;
|
||||
System.out.println();
|
||||
System.out.println("Using temporary directory: " + f.getAbsolutePath());
|
||||
temporary_directory_mentioned = true;
|
||||
f = askIfChangeIsWanted(f);
|
||||
temporary_directory = f;
|
||||
temporary_directory_isInit = true;
|
||||
while(!temporary_directory.isDirectory() && !temporary_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + f.getAbsolutePath());
|
||||
temporary_directory = askIfChangeIsWanted(f);
|
||||
}
|
||||
save();
|
||||
System.out.println();
|
||||
return temporary_directory;
|
||||
}else {
|
||||
if(!temporary_directory_mentioned) {
|
||||
System.out.println("Using temporary directory: " + temporary_directory.getAbsolutePath());
|
||||
temporary_directory_mentioned = true;
|
||||
while(!temporary_directory.isDirectory() && !temporary_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + temporary_directory.getAbsolutePath());
|
||||
temporary_directory = askIfChangeIsWanted(temporary_directory);
|
||||
}
|
||||
mentionConfigPath();
|
||||
}
|
||||
return temporary_directory;
|
||||
}
|
||||
}
|
||||
|
||||
public static File getWorkspaceDirectory() {
|
||||
if(!config_file_loaded) {
|
||||
load();
|
||||
config_file_loaded = true;
|
||||
}
|
||||
if(!workspace_directory_isInit) {
|
||||
File f = workspace_directory;
|
||||
System.out.println();
|
||||
System.out.println("Using workspace directory: " + f.getAbsolutePath());
|
||||
workspace_directory_mentioned = true;
|
||||
f = askIfChangeIsWanted(f);
|
||||
workspace_directory = f;
|
||||
workspace_directory_isInit = true;
|
||||
while(!workspace_directory.isDirectory() && !workspace_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + f.getAbsolutePath());
|
||||
workspace_directory = askIfChangeIsWanted(f);
|
||||
}
|
||||
save();
|
||||
System.out.println();
|
||||
return workspace_directory;
|
||||
}else {
|
||||
if(!workspace_directory_mentioned) {
|
||||
System.out.println("Using workspace directory: " + workspace_directory.getAbsolutePath());
|
||||
workspace_directory_mentioned = true;
|
||||
while(!workspace_directory.isDirectory() && !workspace_directory.mkdirs()) {
|
||||
System.err.println("Failed to create: " + workspace_directory.getAbsolutePath());
|
||||
workspace_directory = askIfChangeIsWanted(workspace_directory);
|
||||
}
|
||||
mentionConfigPath();
|
||||
}
|
||||
return workspace_directory;
|
||||
}
|
||||
}
|
||||
|
||||
public static File askIfChangeIsWanted(File in) {
|
||||
System.out.println("Would you like to change this directory?");
|
||||
System.out.println("Enter 'Y' for yes or 'N' for no: ");
|
||||
String l = "N";
|
||||
|
||||
try {
|
||||
l = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
if(l != null && ((l = l.trim()).equalsIgnoreCase("y") || l.equalsIgnoreCase("yes"))) {
|
||||
System.out.println();
|
||||
System.out.println("Type a new filename or hit 'Enter' to browse: ");
|
||||
try {
|
||||
l = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
if(l != null && (l = l.trim()).length() > 0) {
|
||||
in = new File(l);
|
||||
}else {
|
||||
File f = FileChooserTool.load(true);
|
||||
if(f == null) {
|
||||
System.out.println("You hit cancel on the file chooser, the directory '" + in.getAbsolutePath() + "' will be used.");
|
||||
in = askIfChangeIsWanted(in);
|
||||
}else {
|
||||
in = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FileChooserTool {
|
||||
|
||||
public static final JFileChooser fc = new JFileChooser();
|
||||
|
||||
public static File load(boolean directory) {
|
||||
fc.setFileSelectionMode(directory ? JFileChooser.DIRECTORIES_ONLY : JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
fc.setFileHidingEnabled(false);
|
||||
fc.setDialogTitle("Eaglercraft Buildtools");
|
||||
JFrame parent = new JFrame();
|
||||
parent.setBounds(0, 0, 50, 50);
|
||||
parent.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
parent.setAlwaysOnTop(true);
|
||||
parent.setTitle("File Chooser");
|
||||
parent.setLocationRelativeTo(null);
|
||||
parent.setVisible(true);
|
||||
if(fc.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
|
||||
parent.dispose();
|
||||
return fc.getSelectedFile();
|
||||
}else {
|
||||
parent.dispose();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class LicensePrompt {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println();
|
||||
display();
|
||||
}
|
||||
|
||||
public static void display() {
|
||||
System.out.println("WARNING: You must agree to the LICENSE before running this command");
|
||||
System.out.println();
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(LicensePrompt.class.getResourceAsStream("/lang/LICENSE_console_wrapped.txt"), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while((line = reader.readLine()) != null) {
|
||||
if(line.equals("<press enter>")) {
|
||||
pressEnter();
|
||||
}else {
|
||||
System.out.println(line);
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: could not display license text");
|
||||
System.err.println("Please read the \"LICENSE\" file before using this software");
|
||||
System.err.println();
|
||||
pressEnter();
|
||||
}
|
||||
}
|
||||
|
||||
private static void pressEnter() {
|
||||
System.out.println();
|
||||
System.out.println("(press ENTER to continue)");
|
||||
while(true) {
|
||||
try {
|
||||
if(System.in.read() == '\n') {
|
||||
break;
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("Unexpected IOException reading STDIN", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,447 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.decompiler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.signature.SignatureReader;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class LocalVariableGenerator extends SignatureVisitor {
|
||||
|
||||
public static final Map<Character,String> primitiveNames = new HashMap();
|
||||
public static final Set<String> illegalVariableNames = new HashSet();
|
||||
|
||||
static {
|
||||
|
||||
primitiveNames.put('Z', "Flag");
|
||||
primitiveNames.put('C', "Char");
|
||||
primitiveNames.put('B', "Byte");
|
||||
primitiveNames.put('S', "Short");
|
||||
primitiveNames.put('I', "Int");
|
||||
primitiveNames.put('F', "Float");
|
||||
primitiveNames.put('J', "Long");
|
||||
primitiveNames.put('D', "Double");
|
||||
primitiveNames.put('V', "Void");
|
||||
|
||||
illegalVariableNames.addAll(Arrays.asList(
|
||||
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class",
|
||||
"continue", "const", "default", "do", "double", "else", "enum", "exports", "extends",
|
||||
"final", "finally", "float", "for", "goto", "if", "implements", "import",
|
||||
"instanceof", "int", "interface", "long", "native", "new", "package", "private",
|
||||
"protected", "public", "return", "short", "static", "strictfp", "super", "switch",
|
||||
"synchronized", "this", "throw", "throws", "transient", "try", "var", "void",
|
||||
"volatile", "while", "string"
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
private String baseClass = null;
|
||||
private boolean isArray = false;
|
||||
private String typeParam1 = null;
|
||||
private boolean typeParam1IsArray = false;
|
||||
private String typeParam2 = null;
|
||||
private boolean typeParam2IsArray = false;
|
||||
|
||||
public static final SignatureVisitor nopVisitor = new SignatureVisitor(Opcodes.ASM5) {};
|
||||
|
||||
LocalVariableGenerator() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
public static String createName(String sig) {
|
||||
SignatureReader rd = new SignatureReader(sig);
|
||||
LocalVariableGenerator gen = new LocalVariableGenerator();
|
||||
rd.acceptType(gen);
|
||||
return gen.getResult();
|
||||
}
|
||||
|
||||
private String removePath(String in) {
|
||||
int idx = in.lastIndexOf('/');
|
||||
int idx2 = in.lastIndexOf('$');
|
||||
if(idx2 > idx && idx2 != in.length() - 1) {
|
||||
idx = idx2;
|
||||
}
|
||||
if(idx != -1) {
|
||||
in = in.substring(idx + 1);
|
||||
}
|
||||
if(in.length() == 0 || Character.isDigit(in.charAt(0))) {
|
||||
in = "obj" + in;
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
String getResult() {
|
||||
String rt;
|
||||
if(baseClass == null) {
|
||||
rt = "Object";
|
||||
}else {
|
||||
rt = removePath(baseClass);
|
||||
}
|
||||
if(typeParam1 == null && typeParam2 == null) {
|
||||
if(isArray) {
|
||||
rt = "ArrayOf" + rt;
|
||||
}
|
||||
}else {
|
||||
if(isArray) {
|
||||
rt = rt + "Array";
|
||||
}
|
||||
}
|
||||
if(typeParam1 != null && typeParam2 == null) {
|
||||
if(typeParam1IsArray) {
|
||||
typeParam1 = typeParam1 + "Array";
|
||||
}
|
||||
rt = rt + "Of" + removePath(typeParam1);
|
||||
}else if(typeParam1 != null && typeParam2 != null) {
|
||||
if(typeParam1IsArray) {
|
||||
typeParam1 = typeParam1 + "Array";
|
||||
}
|
||||
if(typeParam2IsArray) {
|
||||
typeParam2 = typeParam2 + "Array";
|
||||
}
|
||||
rt = rt + "Of" + removePath(typeParam1) + "And" + removePath(typeParam2);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(baseClass == null) {
|
||||
isArray = true;
|
||||
return new ArrayTypeVisitor();
|
||||
}else {
|
||||
return nopVisitor;
|
||||
}
|
||||
}
|
||||
|
||||
private class ArrayTypeVisitor extends SignatureVisitor {
|
||||
|
||||
protected ArrayTypeVisitor() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(baseClass == null) {
|
||||
baseClass = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
if(baseClass == null) {
|
||||
baseClass = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(baseClass == null) {
|
||||
baseClass = "array";
|
||||
}
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override public SignatureVisitor visitClassBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitExceptionType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterface() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterfaceBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitParameterType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitTypeArgument(char wildcard) { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitReturnType() { return nopVisitor; }
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(baseClass == null) {
|
||||
baseClass = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitClassBound() {
|
||||
//System.out.println("class: " + this);
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
//System.out.println("classType: " + name);
|
||||
if(baseClass == null) {
|
||||
baseClass = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
//System.out.println("formalTypeParam: " + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(String name) {
|
||||
//System.out.println("innerClassType: " + name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterface() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitParameterType() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
private class TypeParamVisitor extends SignatureVisitor {
|
||||
|
||||
private boolean hasVisited = false;
|
||||
private final int firstOrSecond;
|
||||
|
||||
protected TypeParamVisitor(int firstOrSecond) {
|
||||
super(Opcodes.ASM5);
|
||||
this.firstOrSecond = firstOrSecond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = name;
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = name;
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1IsArray = true;
|
||||
return new TypeParamArrayVisitor();
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2IsArray = true;
|
||||
return new TypeParamArrayVisitor();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
private class TypeParamArrayVisitor extends SignatureVisitor {
|
||||
|
||||
protected TypeParamArrayVisitor() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = primitiveNames.get(descriptor);
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = name;
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = name;
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
if(!hasVisited) {
|
||||
if(firstOrSecond == 1) {
|
||||
if(typeParam1 == null) {
|
||||
typeParam1 = "array";
|
||||
}
|
||||
}else if(firstOrSecond == 2) {
|
||||
if(typeParam2 == null) {
|
||||
typeParam2 = "array";
|
||||
}
|
||||
}
|
||||
hasVisited = true;
|
||||
}
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override public SignatureVisitor visitClassBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitExceptionType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterface() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterfaceBound() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitParameterType() { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitTypeArgument(char wildcard) { return nopVisitor; }
|
||||
@Override public SignatureVisitor visitReturnType() { return nopVisitor; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitReturnType() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitSuperclass() {
|
||||
return nopVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||
if(typeParam1 == null) {
|
||||
return new TypeParamVisitor(1);
|
||||
}else if(typeParam2 == null) {
|
||||
return new TypeParamVisitor(2);
|
||||
}else {
|
||||
return nopVisitor;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name) {
|
||||
|
||||
}
|
||||
|
||||
public static String nextLocalVariableNameFromString(Map<String,Integer> tmpLocalsMap, String signature, String pfx) {
|
||||
String str = signature.length() == 1 ? primitiveNames.get(signature.charAt(0)) : null;
|
||||
if(str == null) {
|
||||
str = LocalVariableGenerator.createName(signature);
|
||||
}
|
||||
String ls = str.toLowerCase();
|
||||
Integer i = tmpLocalsMap.get(ls);
|
||||
if(i == null) {
|
||||
tmpLocalsMap.put(ls, 1);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1))) {
|
||||
str = str + "_1";
|
||||
}else {
|
||||
str = illegalVariableNames.contains(str.toLowerCase()) ? str + "1" : str;
|
||||
}
|
||||
}else {
|
||||
int ii = i.intValue() + 1;
|
||||
tmpLocalsMap.put(ls, ii);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1)) || str.contains("And") || str.length() > 16) {
|
||||
str = str + "_" + ii;
|
||||
}else {
|
||||
str = str + ii;
|
||||
}
|
||||
}
|
||||
return pfx == null ? camelCase(str) : pfx + str;
|
||||
}
|
||||
|
||||
public static String nextLocalVariableName(Map<String,Integer> tmpLocalsMap, LocalVariableGenerator signature, String pfx) {
|
||||
String str = signature.getResult();
|
||||
String ls = str.toLowerCase();
|
||||
Integer i = tmpLocalsMap.get(ls);
|
||||
if(i == null) {
|
||||
tmpLocalsMap.put(ls, 1);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1))) {
|
||||
str = str + "_1";
|
||||
}else {
|
||||
str = illegalVariableNames.contains(str.toLowerCase()) ? str + "1" : str;
|
||||
}
|
||||
}else {
|
||||
int ii = i.intValue() + 1;
|
||||
tmpLocalsMap.put(ls, ii);
|
||||
if(Character.isDigit(str.charAt(str.length() - 1)) || str.contains("And") || str.length() > 16) {
|
||||
str = str + "_" + ii;
|
||||
}else {
|
||||
str = str + ii;
|
||||
}
|
||||
}
|
||||
return pfx == null ? camelCase(str) : pfx + str;
|
||||
}
|
||||
|
||||
public static String camelCase(String in) {
|
||||
if(in == null || in.length() <= 0) {
|
||||
return "name";
|
||||
}else {
|
||||
if(in.length() > 1 && Character.isUpperCase(in.charAt(0)) && Character.isUpperCase(in.charAt(1))) {
|
||||
return "var" + in;
|
||||
}else {
|
||||
return in.substring(0, 1).toLowerCase() + in.substring(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.decompiler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.signature.SignatureReader;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ParameterSplitter extends SignatureVisitor {
|
||||
|
||||
protected ParameterSplitter() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
protected static final ArrayList<LocalVariableGenerator> ret = new ArrayList();
|
||||
protected static final HashMap<String,Integer> usedLocals = new HashMap();
|
||||
|
||||
public static int getParameterArray(String sig, String[] input) {
|
||||
SignatureReader rd = new SignatureReader(sig);
|
||||
ParameterSplitter pms = new ParameterSplitter();
|
||||
ret.clear();
|
||||
usedLocals.clear();
|
||||
rd.accept(pms);
|
||||
int l = ret.size();
|
||||
if(l > input.length) {
|
||||
l = input.length;
|
||||
}
|
||||
int c = 0;
|
||||
for(int i = 0; i < l; ++i) {
|
||||
if(input[i] == null) {
|
||||
input[i] = LocalVariableGenerator.nextLocalVariableName(usedLocals, ret.get(i), "par");
|
||||
++c;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public static String[] getParameterSigArray(String sig, String pfx) {
|
||||
SignatureReader rd = new SignatureReader(sig);
|
||||
ParameterSplitter pms = new ParameterSplitter();
|
||||
ret.clear();
|
||||
usedLocals.clear();
|
||||
rd.accept(pms);
|
||||
String[] r = new String[ret.size()];
|
||||
for(int i = 0; i < r.length; ++i) {
|
||||
r[i] = LocalVariableGenerator.nextLocalVariableName(usedLocals, ret.get(i), pfx);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitParameterType() {
|
||||
LocalVariableGenerator lv = new LocalVariableGenerator();
|
||||
ret.add(lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@Override public SignatureVisitor visitClassBound() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitExceptionType() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterface() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitInterfaceBound() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitTypeArgument(char wildcard) { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitReturnType() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public SignatureVisitor visitArrayType() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public void visitBaseType(char descriptor) { }
|
||||
@Override public void visitClassType(String name) { }
|
||||
@Override public void visitEnd() { }
|
||||
@Override public void visitFormalTypeParameter(String name) { }
|
||||
@Override public void visitInnerClassType(String name) { }
|
||||
@Override public SignatureVisitor visitSuperclass() { return LocalVariableGenerator.nopVisitor; }
|
||||
@Override public void visitTypeArgument() { }
|
||||
@Override public void visitTypeVariable(String name) { }
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,416 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.EventQueue;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries.MissingJARsException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.DecompileMinecraft;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.FFMPEG;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InitMCP;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMClassLoadException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMRuntimeException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CompileLatestClientGUI {
|
||||
|
||||
public static CompileLatestClientFrame frame = null;
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println();
|
||||
System.out.println("Launching client compiler wizard...");
|
||||
System.out.println("Copyright (c) 2022 lax1dude");
|
||||
System.out.println();
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
System.err.println("Could not set system look and feel: " + e.toString());
|
||||
}
|
||||
if(!System.getProperty("eaglercraft.isJava11", "false").equalsIgnoreCase("true")) {
|
||||
try {
|
||||
if (!(boolean) Class
|
||||
.forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java11Check", true,
|
||||
new URLClassLoader(new URL[] { (new File("buildtools/Java11Check.jar")).toURI().toURL() }))
|
||||
.getMethod("classLoadCheck").invoke(null)) {
|
||||
throw new RuntimeException("wtf?");
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
JOptionPane.showMessageDialog(null, "Error: Java 11 is required to run this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
frame = new CompileLatestClientFrame();
|
||||
frame.frmCompileLatestClient.setLocationRelativeTo(null);
|
||||
frame.frmCompileLatestClient.setVisible(true);
|
||||
System.out.println("you eagler");
|
||||
System.out.println();
|
||||
frame.launchLogUpdateThread();
|
||||
System.setOut(new PrintStream(new ConsoleRedirector(false)));
|
||||
System.setErr(new PrintStream(new ConsoleRedirector(true)));
|
||||
if(JavaC.jdkHome == null) {
|
||||
if(JOptionPane.showConfirmDialog(frame.frmCompileLatestClient, "Error: A JDK is required to run this program!\nYou are currently running on a JRE\nDo you have a JDK installed that you would like to use instead?", "Unsupported JRE", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "You need at least JDK 8 to compile EaglercraftX 1.8!\nSelect the path to the installation you want to use", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE);
|
||||
JFileChooser fileChooser = new JFileChooser((new File(System.getProperty("java.home"))).getParentFile());
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
fileChooser.setFileHidingEnabled(false);
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
while(true) {
|
||||
if(fileChooser.showOpenDialog(frame.frmCompileLatestClient) == JFileChooser.APPROVE_OPTION) {
|
||||
File f = fileChooser.getSelectedFile();
|
||||
if(JavaC.windows ? (new File(f, "bin/javac.exe")).exists() : (new File(f, "bin/javac")).canExecute()) {
|
||||
break;
|
||||
}else {
|
||||
if(JOptionPane.showConfirmDialog(frame.frmCompileLatestClient, "Could not find a java compiler in this directory!\nWould you like to try again?", "Unsupported JRE", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install JDK 8 or newer to continue", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
JavaC.jdkHome = fileChooser.getSelectedFile();
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "The JDK \"" + JavaC.jdkHome.getAbsolutePath() + "\" will be used to compile EaglercraftX", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE);
|
||||
}else {
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install a JDK and re-launch this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
frame.scrollPane_LicenseText.getVerticalScrollBar().setValue(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class CompileFailureException extends RuntimeException {
|
||||
public CompileFailureException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
public CompileFailureException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runCompiler() {
|
||||
try {
|
||||
runCompiler0();
|
||||
}catch(CompileFailureException t) {
|
||||
System.out.println();
|
||||
System.err.println("Error: " + t.getMessage());
|
||||
t.printStackTrace();
|
||||
frame.finishCompiling(true, t.getMessage());
|
||||
return;
|
||||
}catch(Throwable t) {
|
||||
System.out.println();
|
||||
System.err.println("Error: unhandled exception caught while compiling!");
|
||||
t.printStackTrace();
|
||||
frame.finishCompiling(true, t.toString());
|
||||
return;
|
||||
}
|
||||
if(!frame.finished) {
|
||||
System.out.println();
|
||||
System.err.println("Error: compilation finished with unknown status!");
|
||||
frame.finishCompiling(true, "Compilation finished with unknown status");
|
||||
}
|
||||
}
|
||||
|
||||
private static void runCompiler0() throws Throwable {
|
||||
File repositoryFolder = new File(frame.textField_RepositoryPath.getText().trim());
|
||||
EaglerBuildTools.repositoryRoot = repositoryFolder;
|
||||
File modCoderPack = new File(frame.textField_ModCoderPack.getText().trim());
|
||||
File minecraftJar = new File(frame.textField_JarFilePath.getText().trim());
|
||||
File assetsIndex = new File(frame.textField_AssetsIndexJSON.getText().trim());
|
||||
File outputDirectory = new File(frame.textField_OutputDirectory.getText().trim());
|
||||
File temporaryDirectory = new File(outputDirectory, "build");
|
||||
|
||||
File[] existingOutput = outputDirectory.listFiles();
|
||||
if(existingOutput.length > 0) {
|
||||
System.out.println("Deleting existing files from the output directory...");
|
||||
try {
|
||||
for(int i = 0; i < existingOutput.length; ++i) {
|
||||
File f = existingOutput[i];
|
||||
if(f.isDirectory()) {
|
||||
FileUtils.deleteDirectory(f);
|
||||
}else {
|
||||
if(!f.delete()) {
|
||||
throw new IOException("Could not delete: " + f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException t) {
|
||||
throw new CompileFailureException("Could not delete old output directory: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
File mcpDataTMP = new File(temporaryDirectory, "ModCoderPack");
|
||||
File minecraftSrcTmp = new File(temporaryDirectory, "MinecraftSrc");
|
||||
|
||||
String ffmpeg = frame.chckbxUsePathFFmpeg.isSelected() ? "" : frame.textField_pathToFFmpeg.getText().trim();
|
||||
if(ffmpeg.length() == 0) {
|
||||
FFMPEG.foundFFMPEG = "ffmpeg";
|
||||
}else {
|
||||
FFMPEG.foundFFMPEG = ffmpeg;
|
||||
}
|
||||
|
||||
String mavenRepositoryURL = frame.getRepositoryURL();
|
||||
File mavenRepositoryFolder = null;
|
||||
if(mavenRepositoryURL == null) {
|
||||
mavenRepositoryFolder = new File(frame.textField_MavenRepoLocal.getText().trim());
|
||||
}
|
||||
|
||||
boolean generateOfflineDownload = frame.chckbxOutputOfflineDownload.isSelected();
|
||||
boolean keepTemporaryFiles = frame.chckbxKeepTemporaryFiles.isSelected();
|
||||
|
||||
if(!mcpDataTMP.isDirectory() && !mcpDataTMP.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!InitMCP.initTask(modCoderPack, mcpDataTMP)) {
|
||||
throw new CompileFailureException("Error: could not initialize MCP from \"" + modCoderPack.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!minecraftSrcTmp.isDirectory() && !minecraftSrcTmp.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + minecraftSrcTmp.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!DecompileMinecraft.decompileMinecraft(mcpDataTMP, minecraftJar, minecraftSrcTmp, assetsIndex, false)) {
|
||||
throw new CompileFailureException("Error: could not decompile and patch 1.8.8.jar from \"" + minecraftJar.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.copyFile(new File(repositoryFolder, "patches/minecraft/output_license.txt"), new File(temporaryDirectory, "MinecraftSrc/LICENSE"));
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Error: failed to write LICENSE in temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(frame.rdbtnMavenRepoLocal.isSelected()) {
|
||||
System.out.println("TeaVM JARs will be loaded from: " + frame.textField_MavenRepoLocal.getText());
|
||||
}else {
|
||||
String url = frame.getRepositoryURL();
|
||||
System.out.println("TeaVM JARs will be downloaded from repository: " + url);
|
||||
System.out.println();
|
||||
try {
|
||||
TeaVMBinaries.downloadFromMaven(url, new File("##TEAVM.TMP##"));
|
||||
}catch(MissingJARsException ex) {
|
||||
throw new CompileFailureException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
int compileResultCode;
|
||||
File compiledResultClasses = new File(temporaryDirectory, "classes");
|
||||
|
||||
try {
|
||||
try {
|
||||
compileResultCode = JavaC.runJavaC(new File(minecraftSrcTmp, "minecraft_src_javadoc.jar"),
|
||||
compiledResultClasses, temporaryDirectory, TeaVMBinaries.getTeaVMRuntimeClasspath(),
|
||||
new File(repositoryFolder, "sources/main/java"), new File(repositoryFolder, "sources/teavm/java"));
|
||||
}catch(IOException ex) {
|
||||
throw new CompileFailureException("failed to run javac compiler! " + ex.toString(), ex);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(compileResultCode == 0) {
|
||||
System.out.println("Java compiler completed successfully");
|
||||
}else {
|
||||
throw new CompileFailureException("failed to run javac compiler! exit code " + compileResultCode + ", check log");
|
||||
}
|
||||
}finally {
|
||||
File extractedSrcTmp = new File(temporaryDirectory, "MinecraftSrc/src_javadoc_tmp");
|
||||
if(extractedSrcTmp.exists()) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting temporary directory: " + extractedSrcTmp.getAbsolutePath());
|
||||
try {
|
||||
FileUtils.deleteDirectory(extractedSrcTmp);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Preparing arguments for TeaVM...");
|
||||
|
||||
if(!TeaVMBinaries.tryLoadTeaVMBridge()) {
|
||||
System.err.println("Failed to locate TeaVMBridge.jar, you can specify it's path manually by adding the JVM argument \"-Deaglercraft.TeaVMBridge=<path>\"");
|
||||
throw new CompileFailureException("Failed to locate TeaVMBridge.jar!");
|
||||
}
|
||||
|
||||
Map<String, Object> teavmArgs = new HashMap();
|
||||
|
||||
List<String> teavmClassPath = new ArrayList();
|
||||
teavmClassPath.add(compiledResultClasses.getAbsolutePath());
|
||||
teavmClassPath.addAll(Arrays.asList(TeaVMBinaries.getTeaVMRuntimeClasspath()));
|
||||
teavmArgs.put("classPathEntries", teavmClassPath);
|
||||
|
||||
teavmArgs.put("entryPointName", "main");
|
||||
teavmArgs.put("mainClass", "net.lax1dude.eaglercraft.v1_8.internal.teavm.MainClass");
|
||||
teavmArgs.put("minifying", true);
|
||||
teavmArgs.put("optimizationLevel", "ADVANCED");
|
||||
teavmArgs.put("targetDirectory", outputDirectory.getAbsolutePath());
|
||||
teavmArgs.put("generateSourceMaps", true);
|
||||
teavmArgs.put("targetFileName", "classes.js");
|
||||
|
||||
System.out.println();
|
||||
|
||||
boolean teavmStatus;
|
||||
try {
|
||||
teavmStatus = TeaVMBridge.compileTeaVM(teavmArgs);
|
||||
}catch(TeaVMClassLoadException ex) {
|
||||
throw new CompileFailureException("Failed to link TeaVM jar files! Did you select the wrong jar?", ex);
|
||||
}catch(TeaVMRuntimeException ex) {
|
||||
throw new CompileFailureException("Failed to run TeaVM! Check log", ex);
|
||||
}
|
||||
|
||||
if(!teavmStatus) {
|
||||
frame.finishCompiling(true, "TeaVM reported problems, check the log");
|
||||
return;
|
||||
}
|
||||
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/CompileEPK.jar");
|
||||
|
||||
if(!epkCompiler.exists()) {
|
||||
throw new CompileFailureException("EPKCompiler JAR file is missing: " + epkCompiler.getAbsolutePath());
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Writing default index.html...");
|
||||
|
||||
FileUtils.copyFile(new File(repositoryFolder, "buildtools/production-index.html"), new File(outputDirectory, "index.html"));
|
||||
FileUtils.copyFile(new File(repositoryFolder, "buildtools/production-favicon.png"), new File(outputDirectory, "favicon.png"));
|
||||
FileUtils.copyFile(new File(repositoryFolder, "sources/setup/workspace_template/javascript/fix-webm-duration.js"), new File(outputDirectory, "fix-webm-duration.js"));
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on assets...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
((new File(minecraftSrcTmp, "minecraft_res_patch.jar")).getAbsolutePath() + System.getProperty("path.separator") +
|
||||
(new File(repositoryFolder, "sources/resources")).getAbsolutePath()), (new File(outputDirectory, "assets.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on languages.zip...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
(new File(minecraftSrcTmp, "minecraft_languages.zip")).getAbsolutePath(),
|
||||
(new File(temporaryDirectory, "languages.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Creating languages directory...");
|
||||
File langDirectory = new File(outputDirectory, "lang");
|
||||
|
||||
byte[] copyBuffer = new byte[16384];
|
||||
int i;
|
||||
try(ZipInputStream zis = new ZipInputStream(new FileInputStream(new File(minecraftSrcTmp, "minecraft_languages.zip")))) {
|
||||
ZipEntry etr;
|
||||
while((etr = zis.getNextEntry()) != null) {
|
||||
if(!etr.isDirectory()) {
|
||||
File phile = new File(langDirectory, etr.getName());
|
||||
File parent = phile.getParentFile();
|
||||
if(!parent.exists() && !parent.mkdirs()) {
|
||||
throw new IOException("Could not create directory: " + parent.getAbsolutePath());
|
||||
}
|
||||
try(FileOutputStream os = new FileOutputStream(phile)) {
|
||||
while((i = zis.read(copyBuffer)) != -1) {
|
||||
os.write(copyBuffer, 0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(generateOfflineDownload) {
|
||||
System.out.println("Running offline download generator...");
|
||||
System.out.println();
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/MakeOfflineDownload.jar");
|
||||
MakeOfflineDownload.compilerMain(offlineDownloadGenerator, new String[] {
|
||||
(new File(repositoryFolder, "sources/setup/workspace_template/javascript/OfflineDownloadTemplate.txt")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "classes.js")).getAbsolutePath() + System.getProperty("path.separator")
|
||||
+ (new File(outputDirectory, "fix-webm-duration.js")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "assets.epk")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_en_US.html")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_International.html")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "build/languages.epk")).getAbsolutePath()
|
||||
});
|
||||
}
|
||||
|
||||
System.out.println("Releasing external ClassLoader(s)...");
|
||||
System.out.println();
|
||||
|
||||
TeaVMBridge.free();
|
||||
EPKCompiler.free();
|
||||
|
||||
if(generateOfflineDownload) {
|
||||
MakeOfflineDownload.free();
|
||||
}
|
||||
|
||||
if(!keepTemporaryFiles) {
|
||||
System.out.println("Cleaning up temporary files...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(temporaryDirectory);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory: " + temporaryDirectory.getAbsolutePath());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Client build successful! Check the output directory for your files");
|
||||
|
||||
try {
|
||||
Desktop.getDesktop().open(outputDirectory);
|
||||
}catch(Throwable t) {
|
||||
}
|
||||
|
||||
frame.finishCompiling(false, "");
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ConsoleRedirector extends OutputStream {
|
||||
|
||||
private final OutputStream stdout;
|
||||
private final boolean err;
|
||||
|
||||
public ConsoleRedirector(boolean err) {
|
||||
stdout = err ? System.err : System.out;
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int o, int l) throws IOException {
|
||||
stdout.write(b, o, l);
|
||||
String append = new String(b, o, l, StandardCharsets.US_ASCII);
|
||||
if(err) {
|
||||
CompileLatestClientGUI.frame.logError(append);
|
||||
}else {
|
||||
CompileLatestClientGUI.frame.logInfo(append);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
stdout.write(b);
|
||||
write0(b);
|
||||
}
|
||||
|
||||
private void write0(int b) throws IOException {
|
||||
char c = (char)b;
|
||||
if(c != '\r') {
|
||||
if(err && c != '\n') {
|
||||
CompileLatestClientGUI.frame.logError(new String(new char[] { c }));
|
||||
}else {
|
||||
CompileLatestClientGUI.frame.logInfo(new String(new char[] { c }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EPKCompiler {
|
||||
|
||||
private static File currentJarFile = null;
|
||||
private static URLClassLoader classLoader = null;
|
||||
private static Method mainMethod = null;
|
||||
|
||||
public static void compilerMain(File jarFile, String[] args) throws InvocationTargetException {
|
||||
if(currentJarFile != null && !currentJarFile.equals(jarFile)) {
|
||||
throw new IllegalArgumentException("Cannot load two different EPKCompiler versions into the same runtime");
|
||||
}
|
||||
if(mainMethod == null) {
|
||||
currentJarFile = jarFile;
|
||||
try {
|
||||
if(classLoader == null) {
|
||||
classLoader = new URLClassLoader(new URL[] { jarFile.toURI().toURL() }, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
Class epkCompilerMain = classLoader.loadClass("CompilePackage");
|
||||
mainMethod = epkCompilerMain.getDeclaredMethod("main", String[].class);
|
||||
} catch (MalformedURLException | SecurityException e) {
|
||||
throw new IllegalArgumentException("Illegal EPKCompiler JAR path!", e);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
throw new IllegalArgumentException("EPKCompiler JAR does not contain main class: 'CompilePackage'", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { args });
|
||||
} catch (IllegalAccessException | IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("EPKCompiler JAR does not contain valid 'main' method", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void free() {
|
||||
if(classLoader != null) {
|
||||
try {
|
||||
classLoader.close();
|
||||
classLoader = null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Memory leak, failed to release EPKCompiler ClassLoader!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class JavaC {
|
||||
|
||||
public static final boolean windows;
|
||||
|
||||
public static File jdkHome;
|
||||
|
||||
public static final List<String> compilerFlags = Arrays.asList(
|
||||
"-Xlint:-unchecked", "-Xlint:-options", "-Xlint:-deprecation",
|
||||
"-source", "1.8", "-target", "1.8"
|
||||
);
|
||||
|
||||
private static int debugSourceFileCount = 0;
|
||||
|
||||
public static int runJavaC(File mcSourceJar, File outputDirectory, File tmpDirectory, String[] teavmClasspath,
|
||||
File... eaglerSourceDirs) throws IOException {
|
||||
|
||||
if(!outputDirectory.exists() && !outputDirectory.mkdirs()) {
|
||||
throw new IOException("Could not create output directory: " + outputDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
if(!tmpDirectory.exists() && !tmpDirectory.mkdirs()) {
|
||||
throw new IOException("Could not create temporary directory: " + outputDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
File minecraftSrcTmp = new File(tmpDirectory, "MinecraftSrc/src_javadoc_tmp");
|
||||
|
||||
if(!minecraftSrcTmp.exists() && !minecraftSrcTmp.mkdirs()) {
|
||||
throw new IOException("Could not create temporary directory: " + minecraftSrcTmp.getAbsolutePath());
|
||||
}
|
||||
|
||||
debugSourceFileCount = 0;
|
||||
|
||||
File argFile = new File(tmpDirectory, "sourceFiles.txt");
|
||||
try(PrintWriter writer = new PrintWriter(new FileWriter(argFile))) {
|
||||
|
||||
System.out.println("Extracting decompiled source...");
|
||||
|
||||
byte[] copyBuffer = new byte[16384];
|
||||
int copyBufferLen;
|
||||
try(ZipInputStream zis = new ZipInputStream(new FileInputStream(mcSourceJar))) {
|
||||
ZipEntry etr;
|
||||
while((etr = zis.getNextEntry()) != null && !etr.isDirectory()) {
|
||||
String n = etr.getName();
|
||||
if(n.endsWith(".java")) {
|
||||
File writeTo = new File(minecraftSrcTmp, n);
|
||||
File parent = writeTo.getParentFile();
|
||||
if(!parent.exists() && !parent.mkdirs()) {
|
||||
throw new IOException("Could not create temporary directory: " + parent.getAbsolutePath());
|
||||
}
|
||||
try(OutputStream os = new FileOutputStream(writeTo)) {
|
||||
while((copyBufferLen = zis.read(copyBuffer)) != -1) {
|
||||
os.write(copyBuffer, 0, copyBufferLen);
|
||||
}
|
||||
}
|
||||
writer.println("\"" + writeTo.getAbsolutePath().replace('\\', '/') + "\"");
|
||||
++debugSourceFileCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Scanning source folder paths...");
|
||||
|
||||
for(int i = 0; i < eaglerSourceDirs.length; ++i) {
|
||||
discoverSourceFiles(eaglerSourceDirs[i], writer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<String> commandBuilder = new ArrayList();
|
||||
|
||||
if(windows) {
|
||||
commandBuilder.add((new File(jdkHome, "bin/javac.exe")).getAbsolutePath());
|
||||
}else {
|
||||
commandBuilder.add((new File(jdkHome, "bin/javac")).getAbsolutePath());
|
||||
}
|
||||
|
||||
commandBuilder.addAll(compilerFlags);
|
||||
|
||||
String pathSeparator = System.getProperty("path.separator");
|
||||
|
||||
commandBuilder.add("-classpath");
|
||||
commandBuilder.add(String.join(pathSeparator, teavmClasspath));
|
||||
|
||||
commandBuilder.add("-sourcepath");
|
||||
|
||||
StringBuilder sourcePathBuilder = new StringBuilder();
|
||||
sourcePathBuilder.append(mcSourceJar.getAbsolutePath());
|
||||
|
||||
for(int i = 0; i < eaglerSourceDirs.length; ++i) {
|
||||
sourcePathBuilder.append(pathSeparator).append(eaglerSourceDirs[i].getAbsolutePath());
|
||||
}
|
||||
|
||||
commandBuilder.add(sourcePathBuilder.toString());
|
||||
|
||||
commandBuilder.add("-d");
|
||||
commandBuilder.add(outputDirectory.getAbsolutePath());
|
||||
|
||||
commandBuilder.add("@" + argFile.getAbsolutePath());
|
||||
|
||||
System.out.println();
|
||||
for(int i = 0, l = commandBuilder.size(); i < l; ++i) {
|
||||
String e = commandBuilder.get(i);
|
||||
if(e.indexOf(' ') != -1) {
|
||||
System.out.print("\"" + e + "\"");
|
||||
}else {
|
||||
System.out.print(e);
|
||||
}
|
||||
System.out.print(' ');
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println("Compiling " + debugSourceFileCount + " source files...");
|
||||
|
||||
ProcessBuilder procBuilder = new ProcessBuilder(commandBuilder);
|
||||
procBuilder.directory(tmpDirectory);
|
||||
Process javacProcess = procBuilder.start();
|
||||
|
||||
InputStream stdout = javacProcess.getInputStream();
|
||||
InputStream stderr = javacProcess.getErrorStream();
|
||||
byte[] readBuffer = new byte[128];
|
||||
int j;
|
||||
boolean tick;
|
||||
|
||||
do {
|
||||
tick = false;
|
||||
|
||||
j = stdout.available();
|
||||
if(j > 0) {
|
||||
if(j > 128) {
|
||||
j = 128;
|
||||
}
|
||||
stdout.read(readBuffer, 0, j);
|
||||
System.out.write(readBuffer, 0, j);
|
||||
tick = true;
|
||||
}
|
||||
|
||||
j = stderr.available();
|
||||
if(j > 0) {
|
||||
if(j > 128) {
|
||||
j = 128;
|
||||
}
|
||||
stderr.read(readBuffer, 0, j);
|
||||
System.err.write(readBuffer, 0, j);
|
||||
tick = true;
|
||||
}
|
||||
|
||||
if(!tick) {
|
||||
try {
|
||||
Thread.sleep(10l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
}while(javacProcess.isAlive());
|
||||
|
||||
while(true) {
|
||||
try {
|
||||
return javacProcess.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void discoverSourceFiles(File folder, PrintWriter printWriter) throws IOException {
|
||||
File[] files = folder.listFiles();
|
||||
for(int i = 0; i < files.length; ++i) {
|
||||
File f = files[i];
|
||||
String name = f.getAbsolutePath();
|
||||
if(f.isDirectory()) {
|
||||
discoverSourceFiles(f, printWriter);
|
||||
}else {
|
||||
if(name.endsWith(".java")) {
|
||||
printWriter.println("\"" + name.replace('\\', '/') + "\"");
|
||||
++debugSourceFileCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
windows = System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
String javac = windows ? "javac.exe" : "javac";
|
||||
File jdkHomeProp = new File(System.getProperty("java.home"));
|
||||
if((new File(jdkHomeProp, "bin/" + javac)).isFile()) {
|
||||
jdkHome = jdkHomeProp;
|
||||
}else if((new File(jdkHomeProp, "../bin/" + javac)).isFile()) {
|
||||
jdkHome = jdkHomeProp.getParentFile();
|
||||
}else {
|
||||
jdkHome = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class MakeOfflineDownload {
|
||||
|
||||
private static File currentJarFile = null;
|
||||
private static URLClassLoader classLoader = null;
|
||||
private static Method mainMethod = null;
|
||||
|
||||
public static void compilerMain(File jarFile, String[] args) throws InvocationTargetException {
|
||||
if(currentJarFile != null && !currentJarFile.equals(jarFile)) {
|
||||
throw new IllegalArgumentException("Cannot load two different MakeOfflineDownload versions into the same runtime");
|
||||
}
|
||||
if(mainMethod == null) {
|
||||
currentJarFile = jarFile;
|
||||
try {
|
||||
if(classLoader == null) {
|
||||
classLoader = new URLClassLoader(new URL[] { jarFile.toURI().toURL() }, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
Class epkCompilerMain = classLoader.loadClass("net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeOfflineDownload");
|
||||
mainMethod = epkCompilerMain.getDeclaredMethod("main", String[].class);
|
||||
} catch (MalformedURLException | SecurityException e) {
|
||||
throw new IllegalArgumentException("Illegal MakeOfflineDownload JAR path!", e);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
throw new IllegalArgumentException("MakeOfflineDownload JAR does not contain main class: 'net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeOfflineDownload'", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { args });
|
||||
} catch (IllegalAccessException | IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("MakeOfflineDownload JAR does not contain valid 'main' method", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void free() {
|
||||
if(classLoader != null) {
|
||||
try {
|
||||
classLoader.close();
|
||||
classLoader = null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Memory leak, failed to release MakeOfflineDownload ClassLoader!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,422 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class TeaVMBinaries {
|
||||
|
||||
public static final String teavmCoreJar = "teavm-core-0.6.1.jar";
|
||||
public static final String teavmCoreMaven = "org/teavm/teavm-core/0.6.1/teavm-core-0.6.1.jar";
|
||||
public static File teavmCore = null;
|
||||
|
||||
public static final String teavmCliJar = "teavm-cli-0.6.1.jar";
|
||||
public static final String teavmCliMaven = "org/teavm/teavm-cli/0.6.1/teavm-cli-0.6.1.jar";
|
||||
public static File teavmCli = null;
|
||||
|
||||
public static final String teavmToolingJar = "teavm-tooling-0.6.1.jar";
|
||||
public static final String teavmToolingMaven = "org/teavm/teavm-tooling/0.6.1/teavm-tooling-0.6.1.jar";
|
||||
public static File teavmTooling = null;
|
||||
|
||||
public static final String teavmPlatformJar = "teavm-platform-0.6.1.jar";
|
||||
public static final String teavmPlatformMaven = "org/teavm/teavm-platform/0.6.1/teavm-platform-0.6.1.jar";
|
||||
public static File teavmPlatform = null;
|
||||
|
||||
public static final String teavmClasslibJar = "teavm-classlib-0.6.1.jar";
|
||||
public static final String teavmClasslibMaven = "org/teavm/teavm-classlib/0.6.1/teavm-classlib-0.6.1.jar";
|
||||
public static File teavmClasslib = null;
|
||||
|
||||
public static final String teavmInteropJar = "teavm-interop-0.6.1.jar";
|
||||
public static final String teavmInteropMaven = "org/teavm/teavm-interop/0.6.1/teavm-interop-0.6.1.jar";
|
||||
public static File teavmInterop = null;
|
||||
|
||||
public static final String teavmJSOJar = "teavm-jso-0.6.1.jar";
|
||||
public static final String teavmJSOMaven = "org/teavm/teavm-jso/0.6.1/teavm-jso-0.6.1.jar";
|
||||
public static File teavmJSO = null;
|
||||
|
||||
public static final String teavmJSOApisJar = "teavm-jso-apis-0.6.1.jar";
|
||||
public static final String teavmJSOApisMaven = "org/teavm/teavm-jso-apis/0.6.1/teavm-jso-apis-0.6.1.jar";
|
||||
public static File teavmJSOApis = null;
|
||||
|
||||
public static final String teavmJSOImplJar = "teavm-jso-impl-0.6.1.jar";
|
||||
public static final String teavmJSOImplMaven = "org/teavm/teavm-jso-impl/0.6.1/teavm-jso-impl-0.6.1.jar";
|
||||
public static File teavmJSOImpl = null;
|
||||
|
||||
public static final String teavmMetaprogrammingAPIJar = "teavm-metaprogramming-api-0.6.1.jar";
|
||||
public static final String teavmMetaprogrammingAPIMaven = "org/teavm/teavm-metaprogramming-api/0.6.1/teavm-metaprogramming-api-0.6.1.jar";
|
||||
public static File teavmMetaprogrammingAPI = null;
|
||||
|
||||
public static final String teavmMetaprogrammingImplJar = "teavm-metaprogramming-impl-0.6.1.jar";
|
||||
public static final String teavmMetaprogrammingImplMaven = "org/teavm/teavm-metaprogramming-impl/0.6.1/teavm-metaprogramming-impl-0.6.1.jar";
|
||||
public static File teavmMetaprogrammingImpl = null;
|
||||
|
||||
public static final String teavmJodaTimeJar = "joda-time-2.7.jar";
|
||||
public static final String teavmJodaTimeMaven = "joda-time/joda-time/2.7/joda-time-2.7.jar";
|
||||
public static File teavmJodaTime = null;
|
||||
|
||||
public static final String teavmJZLIBJar = "jzlib-1.1.3.jar";
|
||||
public static final String teavmJZLIBMaven = "com/jcraft/jzlib/1.1.3/jzlib-1.1.3.jar";
|
||||
public static File teavmJZLIB = null;
|
||||
|
||||
public static File teavmBridge = null;
|
||||
|
||||
public static class MissingJARsException extends RuntimeException {
|
||||
|
||||
public final List<String> jars;
|
||||
|
||||
public MissingJARsException(String msg, List<String> jars) {
|
||||
super(msg);
|
||||
this.jars = jars;
|
||||
}
|
||||
|
||||
public MissingJARsException(List<String> jars) {
|
||||
this("The following JAR files were not found: " + String.join(", ", jars), jars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void downloadFromMaven(String url, File outputDir) throws MissingJARsException {
|
||||
teavmCore = teavmPlatform = teavmClasslib = teavmInterop = teavmJSO =
|
||||
teavmJSOApis = teavmJSOImpl = teavmMetaprogrammingAPI = teavmMetaprogrammingImpl =
|
||||
teavmJodaTime = teavmJZLIB = teavmTooling = teavmCli = null;
|
||||
|
||||
if(url.lastIndexOf('/') != url.length() - 1) {
|
||||
url += "/";
|
||||
}
|
||||
|
||||
String urlConc = url + teavmCoreMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmCoreJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmCore = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmCliMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmCliJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmCli = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmToolingMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmToolingJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmTooling = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmPlatformMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmPlatformJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmPlatform = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmClasslibMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmClasslibJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmClasslib = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmInteropMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmInteropJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmInterop = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJSOMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJSOJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJSO = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJSOApisMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJSOApisJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJSOApis = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJSOImplMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJSOImplJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJSOImpl = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmMetaprogrammingAPIMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmMetaprogrammingAPIJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmMetaprogrammingAPI = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmMetaprogrammingImplMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmMetaprogrammingImplJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmMetaprogrammingImpl = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJodaTimeMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJodaTimeJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJodaTime = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
urlConc = url + teavmJZLIBMaven;
|
||||
try {
|
||||
File f = new File(outputDir, teavmJZLIBJar);
|
||||
copyURLToFileCheck404(urlConc, f);
|
||||
teavmJZLIB = f;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not download JAR: " + urlConc);
|
||||
ex.printStackTrace();
|
||||
throw new MissingJARsException("The following JAR file could not be downloaded: " + urlConc, Arrays.asList(urlConc));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void loadFromDirectory(File directory) throws MissingJARsException {
|
||||
teavmCore = teavmPlatform = teavmClasslib = teavmInterop = teavmJSO =
|
||||
teavmJSOApis = teavmJSOImpl = teavmMetaprogrammingAPI = teavmMetaprogrammingImpl =
|
||||
teavmJodaTime = teavmJZLIB = teavmTooling = teavmCli = null;
|
||||
discoverJars(directory);
|
||||
List<String> missingJars = new ArrayList();
|
||||
if(teavmCore == null) {
|
||||
missingJars.add(teavmCoreJar);
|
||||
}
|
||||
if(teavmCli == null) {
|
||||
missingJars.add(teavmCliJar);
|
||||
}
|
||||
if(teavmTooling == null) {
|
||||
missingJars.add(teavmToolingJar);
|
||||
}
|
||||
if(teavmPlatform == null) {
|
||||
missingJars.add(teavmPlatformJar);
|
||||
}
|
||||
if(teavmClasslib == null) {
|
||||
missingJars.add(teavmClasslibJar);
|
||||
}
|
||||
if(teavmInterop == null) {
|
||||
missingJars.add(teavmInteropJar);
|
||||
}
|
||||
if(teavmJSO == null) {
|
||||
missingJars.add(teavmJSOJar);
|
||||
}
|
||||
if(teavmJSOApis == null) {
|
||||
missingJars.add(teavmJSOApisJar);
|
||||
}
|
||||
if(teavmJSOImpl == null) {
|
||||
missingJars.add(teavmJSOImplJar);
|
||||
}
|
||||
if(teavmMetaprogrammingAPI == null) {
|
||||
missingJars.add(teavmMetaprogrammingAPIJar);
|
||||
}
|
||||
if(teavmMetaprogrammingImpl == null) {
|
||||
missingJars.add(teavmMetaprogrammingImplJar);
|
||||
}
|
||||
if(teavmJodaTime == null) {
|
||||
missingJars.add(teavmJodaTimeJar);
|
||||
}
|
||||
if(teavmJZLIB == null) {
|
||||
missingJars.add(teavmJZLIBJar);
|
||||
}
|
||||
if(missingJars.size() > 0) {
|
||||
throw new MissingJARsException(missingJars);
|
||||
}
|
||||
}
|
||||
|
||||
private static void discoverJars(File dir) {
|
||||
File[] files = dir.listFiles();
|
||||
for(int i = 0; i < files.length; ++i) {
|
||||
File f = files[i];
|
||||
if(f.isDirectory()) {
|
||||
discoverJars(f);
|
||||
}else {
|
||||
String n = f.getName();
|
||||
switch(n) {
|
||||
case teavmCoreJar:
|
||||
teavmCore = f;
|
||||
break;
|
||||
case teavmCliJar:
|
||||
teavmCli = f;
|
||||
break;
|
||||
case teavmToolingJar:
|
||||
teavmTooling = f;
|
||||
break;
|
||||
case teavmPlatformJar:
|
||||
teavmPlatform = f;
|
||||
break;
|
||||
case teavmClasslibJar:
|
||||
teavmClasslib = f;
|
||||
break;
|
||||
case teavmInteropJar:
|
||||
teavmInterop = f;
|
||||
break;
|
||||
case teavmJSOJar:
|
||||
teavmJSO = f;
|
||||
break;
|
||||
case teavmJSOApisJar:
|
||||
teavmJSOApis = f;
|
||||
break;
|
||||
case teavmJSOImplJar:
|
||||
teavmJSOImpl = f;
|
||||
break;
|
||||
case teavmMetaprogrammingAPIJar:
|
||||
teavmMetaprogrammingAPI = f;
|
||||
break;
|
||||
case teavmMetaprogrammingImplJar:
|
||||
teavmMetaprogrammingImpl = f;
|
||||
break;
|
||||
case teavmJodaTimeJar:
|
||||
teavmJodaTime = f;
|
||||
break;
|
||||
case teavmJZLIBJar:
|
||||
teavmJZLIB = f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyURLToFileCheck404(String urlIn, File fileOut) throws IOException {
|
||||
System.out.println("downloading: " + urlIn);
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(urlIn);
|
||||
}catch(MalformedURLException ex) {
|
||||
throw new IOException("Invalid URL: " + urlIn, ex);
|
||||
}
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
int respCode = connection.getResponseCode();
|
||||
if(respCode != 200) {
|
||||
connection.disconnect();
|
||||
throw new IOException("Recieved response code: " + respCode);
|
||||
}
|
||||
try (InputStream stream = connection.getInputStream()) {
|
||||
FileUtils.copyInputStreamToFile(stream, fileOut);
|
||||
}finally {
|
||||
connection.disconnect(); // is this required?
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean tryLoadTeaVMBridge() {
|
||||
String override = System.getProperty("eaglercraft.TeaVMBridge");
|
||||
File teavmBridgeCheck;
|
||||
if(override != null) {
|
||||
teavmBridgeCheck = new File(override);
|
||||
}else {
|
||||
try {
|
||||
teavmBridgeCheck = new File(new File(URLDecoder.decode(
|
||||
TeaVMBinaries.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(),
|
||||
"UTF-8")).getParent(), "TeaVMBridge.jar");
|
||||
} catch (URISyntaxException | UnsupportedEncodingException e) {
|
||||
System.err.println("Failed to locate TeaVMBridge.jar relative to BuildTools jar!");
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(teavmBridgeCheck.exists()) {
|
||||
teavmBridge = teavmBridgeCheck;
|
||||
return true;
|
||||
}else {
|
||||
System.err.println("File does not exist: " + teavmBridgeCheck.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static File[] getTeaVMCompilerClasspath() {
|
||||
return new File[] { teavmCore, teavmCli, teavmTooling, teavmInterop, teavmMetaprogrammingAPI, teavmBridge };
|
||||
}
|
||||
|
||||
public static String[] getTeaVMRuntimeClasspath() {
|
||||
return new String[] {
|
||||
teavmJodaTime.getAbsolutePath(), teavmJZLIB.getAbsolutePath(), teavmClasslib.getAbsolutePath(),
|
||||
teavmInterop.getAbsolutePath(), teavmJSO.getAbsolutePath(), teavmJSOApis.getAbsolutePath(),
|
||||
teavmJSOImpl.getAbsolutePath(), teavmMetaprogrammingAPI.getAbsolutePath(),
|
||||
teavmMetaprogrammingImpl.getAbsolutePath(), teavmPlatform.getAbsolutePath()
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,612 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.gui.headless;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.LicensePrompt;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.EPKCompiler;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.JavaC;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.MakeOfflineDownload;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.CompileLatestClientGUI.CompileFailureException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries.MissingJARsException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.DecompileMinecraft;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.FFMPEG;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InitMCP;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMClassLoadException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridge.TeaVMRuntimeException;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CompileLatestClientHeadless {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Launching client compiler...");
|
||||
System.out.println("Copyright (c) 2022 lax1dude");
|
||||
System.out.println();
|
||||
|
||||
boolean yes = false;
|
||||
String configPath = null;
|
||||
|
||||
if(args.length == 1) {
|
||||
configPath = args[0];
|
||||
}else if(args.length == 2 && (yes = args[0].equalsIgnoreCase("-y"))) {
|
||||
configPath = args[1];
|
||||
}else {
|
||||
System.err.println("Usage: java -jar BuildTools.jar [-y] <config file>");
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Loading config file: " + configPath);
|
||||
System.out.println();
|
||||
|
||||
File configFile = new File(configPath);
|
||||
String configSrc;
|
||||
try {
|
||||
configSrc = FileUtils.readFileToString(configFile, StandardCharsets.UTF_8);
|
||||
}catch(FileNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
System.err.println();
|
||||
System.err.println("ERROR: File '" + configFile.getAbsolutePath() + "' does not exist!");
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject configJSON;
|
||||
try {
|
||||
configJSON = new JSONObject(configSrc);
|
||||
}catch(JSONException ex) {
|
||||
System.err.println("ERROR: Could not parse '" + configFile.getName() + "' as JSON!");
|
||||
System.err.println();
|
||||
System.err.println(ex.toString());
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
File repositoryFolder;
|
||||
File modCoderPack;
|
||||
File minecraftJar;
|
||||
File assetsIndex;
|
||||
File outputDirectory;
|
||||
File temporaryDirectory;
|
||||
String ffmpeg = "ffmpeg";
|
||||
String mavenURL = null;
|
||||
File mavenLocal = null;
|
||||
File productionIndex = null;
|
||||
File productionFavicon = null;
|
||||
List<String> addScripts = null;
|
||||
List<String> removeScripts = null;
|
||||
List<String> injectInOfflineScripts = null;
|
||||
boolean generateOffline;
|
||||
File offlineTemplate = null;
|
||||
boolean keepTemporaryFiles;
|
||||
boolean writeSourceMap = false;
|
||||
boolean minifying = true;
|
||||
try {
|
||||
repositoryFolder = new File(configJSON.optString("repositoryFolder", "."));
|
||||
modCoderPack = new File(configJSON.getString("modCoderPack"));
|
||||
minecraftJar = new File(configJSON.getString("minecraftJar"));
|
||||
assetsIndex = new File(configJSON.getString("assetsIndex"));
|
||||
outputDirectory = new File(configJSON.getString("outputDirectory"));
|
||||
String tmpDir = configJSON.optString("temporaryDirectory");
|
||||
temporaryDirectory = tmpDir == null ? new File(outputDirectory, "build") : new File(tmpDir);
|
||||
ffmpeg = configJSON.optString("ffmpeg", ffmpeg);
|
||||
if(ffmpeg.length() == 0) {
|
||||
ffmpeg = "ffmpeg";
|
||||
}
|
||||
String prodIndex = configJSON.optString("productionIndex");
|
||||
if(prodIndex != null) {
|
||||
productionIndex = new File(prodIndex);
|
||||
String prodFavicon = configJSON.optString("productionFavicon");
|
||||
if(prodFavicon != null) {
|
||||
productionFavicon = new File(prodFavicon);
|
||||
}
|
||||
JSONArray scripts = configJSON.optJSONArray("addScripts");
|
||||
if(scripts != null) {
|
||||
int l = scripts.length();
|
||||
if(l > 0) {
|
||||
addScripts = new ArrayList(l);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
addScripts.add(scripts.getString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
scripts = configJSON.optJSONArray("removeScripts");
|
||||
if(scripts != null) {
|
||||
int l = scripts.length();
|
||||
if(l > 0) {
|
||||
removeScripts = new ArrayList(l);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
removeScripts.add(scripts.getString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
scripts = configJSON.optJSONArray("injectInOffline");
|
||||
if(scripts != null) {
|
||||
int l = scripts.length();
|
||||
if(l > 0) {
|
||||
injectInOfflineScripts = new ArrayList(l);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
injectInOfflineScripts.add(scripts.getString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mavenURL = configJSON.optString("mavenURL");
|
||||
mavenLocal = new File(configJSON.getString("mavenLocal"));
|
||||
generateOffline = configJSON.optBoolean("generateOfflineDownload", false);
|
||||
if(generateOffline) {
|
||||
offlineTemplate = new File(configJSON.getString("offlineDownloadTemplate"));
|
||||
}
|
||||
keepTemporaryFiles = configJSON.optBoolean("keepTemporaryFiles", false);
|
||||
writeSourceMap = configJSON.optBoolean("writeSourceMap", false);
|
||||
minifying = configJSON.optBoolean("minifying", true);
|
||||
}catch(JSONException ex) {
|
||||
System.err.println("CONFIG ERROR: " + ex.toString());
|
||||
System.err.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Loaded config successfully:");
|
||||
System.out.println();
|
||||
System.out.println(" - Repository Folder: " + repositoryFolder.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Mod Coder Pack: " + modCoderPack.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Minecraft 1.8.8: " + minecraftJar.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Assets Index 1.8: " + assetsIndex.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Temporary Directory: " + temporaryDirectory.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Output Directory: " + outputDirectory.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - FFmpeg Executable: " + ffmpeg.replace('\\', '/'));
|
||||
System.out.println(" - Maven Repo URL: " + mavenURL);
|
||||
System.out.println(" - Maven Local Dir: " + mavenLocal.getAbsolutePath().replace('\\', '/'));
|
||||
System.out.println(" - Production Index: " + (productionIndex == null ? "null" : productionIndex.getAbsolutePath().replace('\\', '/')));
|
||||
System.out.println(" - Production Favicon: " + (productionFavicon == null ? "null" : productionFavicon.getAbsolutePath().replace('\\', '/')));
|
||||
System.out.println(" - Generate Offline: " + generateOffline);
|
||||
System.out.println(" - Offline Template: " + (offlineTemplate == null ? "null" : offlineTemplate.getAbsolutePath().replace('\\', '/')));
|
||||
System.out.println(" - Inject in Offline: " + (injectInOfflineScripts == null ? "[ ]" : "[ " + String.join(", ", injectInOfflineScripts).replace('\\', '/') + " ]"));
|
||||
System.out.println(" - Minifying: " + minifying);
|
||||
System.out.println(" - Write Source Map: " + writeSourceMap);
|
||||
System.out.println(" - Keep Temp Files: " + keepTemporaryFiles);
|
||||
System.out.println(" - Add Scripts: " + (addScripts == null ? "[ ]" : "[ " + String.join(", ", addScripts).replace('\\', '/') + " ]"));
|
||||
System.out.println(" - Remove Scripts: " + (removeScripts == null ? "[ ]" : "[ " + String.join(", ", removeScripts).replace('\\', '/') + " ]"));
|
||||
System.out.println();
|
||||
|
||||
if(!yes) {
|
||||
System.out.println();
|
||||
LicensePrompt.display();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
EaglerBuildTools.repositoryRoot = repositoryFolder;
|
||||
|
||||
try {
|
||||
if(!outputDirectory.isDirectory() && !outputDirectory.mkdirs()) {
|
||||
throw new CompileFailureException("Could not create output directory!");
|
||||
}
|
||||
|
||||
File[] existingOutput = outputDirectory.listFiles();
|
||||
if(existingOutput.length > 0) {
|
||||
|
||||
if(!yes) {
|
||||
System.out.print("Output directory has existing files, would you like to delete them? [y/n] ");
|
||||
String str = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
System.out.println();
|
||||
if(!str.equalsIgnoreCase("y") && !str.equalsIgnoreCase("yes")) {
|
||||
System.out.println("Build cancelled.");
|
||||
System.out.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Deleting existing files from the output directory...");
|
||||
|
||||
try {
|
||||
for(int i = 0; i < existingOutput.length; ++i) {
|
||||
File f = existingOutput[i];
|
||||
if(f.isDirectory()) {
|
||||
FileUtils.deleteDirectory(f);
|
||||
}else {
|
||||
if(!f.delete()) {
|
||||
throw new IOException("Could not delete: " + f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException t) {
|
||||
throw new CompileFailureException("Could not delete old output directory: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
File mcpDataTMP = new File(temporaryDirectory, "ModCoderPack");
|
||||
File minecraftSrcTmp = new File(temporaryDirectory, "MinecraftSrc");
|
||||
|
||||
if(ffmpeg.length() == 0) {
|
||||
FFMPEG.foundFFMPEG = "ffmpeg";
|
||||
}else {
|
||||
FFMPEG.foundFFMPEG = ffmpeg;
|
||||
}
|
||||
|
||||
if(!mcpDataTMP.isDirectory() && !mcpDataTMP.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!InitMCP.initTask(modCoderPack, mcpDataTMP)) {
|
||||
throw new CompileFailureException("Error: could not initialize MCP from \"" + modCoderPack.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!minecraftSrcTmp.isDirectory() && !minecraftSrcTmp.mkdirs()) {
|
||||
throw new CompileFailureException("Error: failed to create \"" + minecraftSrcTmp.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!DecompileMinecraft.decompileMinecraft(mcpDataTMP, minecraftJar, minecraftSrcTmp, assetsIndex, false)) {
|
||||
throw new CompileFailureException("Error: could not decompile and patch 1.8.8.jar from \"" + minecraftJar.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.copyFile(new File(repositoryFolder, "patches/minecraft/output_license.txt"), new File(temporaryDirectory, "MinecraftSrc/LICENSE"));
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Error: failed to write LICENSE in temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(mavenURL == null) {
|
||||
System.out.println("TeaVM JARs will be loaded from: " + mavenLocal.getAbsolutePath());
|
||||
System.out.println();
|
||||
try {
|
||||
TeaVMBinaries.loadFromDirectory(mavenLocal);
|
||||
}catch(MissingJARsException ex) {
|
||||
throw new CompileFailureException(ex.getMessage());
|
||||
}
|
||||
}else {
|
||||
System.out.println("TeaVM JARs will be downloaded from repository: " + mavenURL);
|
||||
System.out.println();
|
||||
try {
|
||||
TeaVMBinaries.downloadFromMaven(mavenURL, mavenLocal);
|
||||
}catch(MissingJARsException ex) {
|
||||
throw new CompileFailureException(ex.getMessage());
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println("Notice: make sure to delete \"" + mavenLocal.getAbsolutePath() + "\" when the compiler is finished, it will not be deleted automatically");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
int compileResultCode;
|
||||
File compiledResultClasses = new File(temporaryDirectory, "classes");
|
||||
|
||||
try {
|
||||
try {
|
||||
compileResultCode = JavaC.runJavaC(new File(minecraftSrcTmp, "minecraft_src_javadoc.jar"),
|
||||
compiledResultClasses, temporaryDirectory, TeaVMBinaries.getTeaVMRuntimeClasspath(),
|
||||
new File(repositoryFolder, "sources/main/java"), new File(repositoryFolder, "sources/teavm/java"));
|
||||
}catch(IOException ex) {
|
||||
throw new CompileFailureException("failed to run javac compiler! " + ex.toString(), ex);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(compileResultCode == 0) {
|
||||
System.out.println("Java compiler completed successfully");
|
||||
}else {
|
||||
throw new CompileFailureException("failed to run javac compiler! exit code " + compileResultCode + ", check log");
|
||||
}
|
||||
}finally {
|
||||
File extractedSrcTmp = new File(temporaryDirectory, "MinecraftSrc/src_javadoc_tmp");
|
||||
if(extractedSrcTmp.exists()) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting temporary directory: " + extractedSrcTmp.getAbsolutePath());
|
||||
try {
|
||||
FileUtils.deleteDirectory(extractedSrcTmp);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Preparing arguments for TeaVM...");
|
||||
|
||||
if(!TeaVMBinaries.tryLoadTeaVMBridge()) {
|
||||
System.err.println("Failed to locate TeaVMBridge.jar, you can specify it's path manually by adding the JVM argument \"-Deaglercraft.TeaVMBridge=<path>\"");
|
||||
throw new CompileFailureException("Failed to locate TeaVMBridge.jar!");
|
||||
}
|
||||
|
||||
Map<String, Object> teavmArgs = new HashMap();
|
||||
|
||||
List<String> teavmClassPath = new ArrayList();
|
||||
teavmClassPath.add(compiledResultClasses.getAbsolutePath());
|
||||
teavmClassPath.addAll(Arrays.asList(TeaVMBinaries.getTeaVMRuntimeClasspath()));
|
||||
teavmArgs.put("classPathEntries", teavmClassPath);
|
||||
|
||||
teavmArgs.put("entryPointName", "main");
|
||||
teavmArgs.put("mainClass", "net.lax1dude.eaglercraft.v1_8.internal.teavm.MainClass");
|
||||
teavmArgs.put("minifying", minifying);
|
||||
teavmArgs.put("optimizationLevel", "ADVANCED");
|
||||
teavmArgs.put("targetDirectory", outputDirectory.getAbsolutePath());
|
||||
teavmArgs.put("generateSourceMaps", writeSourceMap);
|
||||
teavmArgs.put("targetFileName", "classes.js");
|
||||
|
||||
System.out.println();
|
||||
|
||||
boolean teavmStatus;
|
||||
try {
|
||||
teavmStatus = TeaVMBridge.compileTeaVM(teavmArgs);
|
||||
}catch(TeaVMClassLoadException ex) {
|
||||
throw new CompileFailureException("Failed to link TeaVM jar files! Did you select the wrong jar?", ex);
|
||||
}catch(TeaVMRuntimeException ex) {
|
||||
throw new CompileFailureException("Failed to run TeaVM! Check log", ex);
|
||||
}
|
||||
|
||||
if(!teavmStatus) {
|
||||
System.out.println("TeaVM reported problems, check the log");
|
||||
System.out.println();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/CompileEPK.jar");
|
||||
|
||||
if(!epkCompiler.exists()) {
|
||||
throw new CompileFailureException("EPKCompiler JAR file is missing: " + epkCompiler.getAbsolutePath());
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Writing index.html...");
|
||||
System.out.println();
|
||||
|
||||
String faviconExt = null;
|
||||
if(productionFavicon != null) {
|
||||
faviconExt = productionFavicon.getName();
|
||||
int i = faviconExt.lastIndexOf('.');
|
||||
if(i != -1) {
|
||||
faviconExt = faviconExt.substring(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
try(BufferedReader indexReader = new BufferedReader(new FileReaderUTF(productionIndex));
|
||||
PrintWriter indexWriter = new PrintWriter(new FileWriterUTF(new File(outputDirectory, "index.html")))) {
|
||||
String line;
|
||||
while((line = indexReader.readLine()) != null) {
|
||||
String trim = line.trim();
|
||||
if(trim.startsWith("<link")) {
|
||||
if(trim.contains("rel=\"shortcut icon\"")) {
|
||||
if(faviconExt != null) {
|
||||
String contentType = "image/png";
|
||||
switch(faviconExt) {
|
||||
case "png":
|
||||
break;
|
||||
case "jpg":
|
||||
case "jpeg":
|
||||
contentType = "image/jpeg";
|
||||
break;
|
||||
case "ico":
|
||||
contentType = "image/x-icon";
|
||||
break;
|
||||
case "gif":
|
||||
contentType = "image/gif";
|
||||
break;
|
||||
case "bmp":
|
||||
contentType = "image/bmp";
|
||||
break;
|
||||
case "webp":
|
||||
contentType = "image/webp";
|
||||
break;
|
||||
default:
|
||||
System.err.println();
|
||||
System.err.println("WARNING: favicon extension '" + faviconExt + "' is unknown, defaulting to image/png MIME type");
|
||||
System.err.println();
|
||||
break;
|
||||
}
|
||||
indexWriter.println(line.replace("favicon.png", "favicon." + faviconExt).replace("image/png", contentType));
|
||||
System.out.println("Setting favicon <link> href to \"favicon." + faviconExt + "\", MIME type \"" + contentType + "\" in index.html");
|
||||
}else {
|
||||
System.out.println("Removed favicon <link> from index.html, no favicon configured");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(trim.startsWith("<meta")) {
|
||||
if(trim.contains("property=\"og:image\"")) {
|
||||
if(faviconExt != null) {
|
||||
indexWriter.println(line.replace("favicon.png", "favicon." + faviconExt));
|
||||
System.out.println("Setting og:image <link> href to \"favicon." + faviconExt + "\"");
|
||||
}else {
|
||||
System.out.println("Removed og:image <meta> tag in index.html, no favicon configured");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(trim.startsWith("<script")) {
|
||||
int idx = line.indexOf("src=\"");
|
||||
int idx2 = line.indexOf('"', idx + 5);
|
||||
String srcSubStr = line.substring(idx + 5, idx2);
|
||||
if(addScripts != null && srcSubStr.equals("classes.js")) {
|
||||
for(int i = 0, l = addScripts.size(); i < l; ++i) {
|
||||
String addSrc = addScripts.get(i);
|
||||
indexWriter.println(line.replace("classes.js", addSrc));
|
||||
System.out.println("Added <script> tag with src \"" + addSrc + "\" to index.html");
|
||||
}
|
||||
}
|
||||
if(removeScripts != null && removeScripts.contains(srcSubStr)) {
|
||||
System.out.println("Removed <script> tag with src \"" + srcSubStr + "\" from index.html");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
indexWriter.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(productionFavicon != null) {
|
||||
FileUtils.copyFile(productionFavicon, new File(outputDirectory, "favicon." + faviconExt));
|
||||
}
|
||||
|
||||
FileUtils.copyFile(new File(repositoryFolder, "sources/setup/workspace_template/javascript/fix-webm-duration.js"), new File(outputDirectory, "fix-webm-duration.js"));
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on assets...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
((new File(minecraftSrcTmp, "minecraft_res_patch.jar")).getAbsolutePath() + System.getProperty("path.separator") +
|
||||
(new File(repositoryFolder, "sources/resources")).getAbsolutePath()), (new File(outputDirectory, "assets.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running EPKCompiler on languages.zip...");
|
||||
|
||||
EPKCompiler.compilerMain(epkCompiler, new String[] {
|
||||
(new File(minecraftSrcTmp, "minecraft_languages.zip")).getAbsolutePath(),
|
||||
(new File(temporaryDirectory, "languages.epk")).getAbsolutePath() });
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Creating languages directory...");
|
||||
File langDirectory = new File(outputDirectory, "lang");
|
||||
|
||||
byte[] copyBuffer = new byte[16384];
|
||||
int i;
|
||||
try(ZipInputStream zis = new ZipInputStream(new FileInputStream(new File(minecraftSrcTmp, "minecraft_languages.zip")))) {
|
||||
ZipEntry etr;
|
||||
while((etr = zis.getNextEntry()) != null) {
|
||||
if(!etr.isDirectory()) {
|
||||
File phile = new File(langDirectory, etr.getName());
|
||||
File parent = phile.getParentFile();
|
||||
if(!parent.exists() && !parent.mkdirs()) {
|
||||
throw new IOException("Could not create directory: " + parent.getAbsolutePath());
|
||||
}
|
||||
try(FileOutputStream os = new FileOutputStream(phile)) {
|
||||
while((i = zis.read(copyBuffer)) != -1) {
|
||||
os.write(copyBuffer, 0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
if(generateOffline) {
|
||||
System.out.println("Running offline download generator...");
|
||||
System.out.println();
|
||||
File offlineTemplateArg = offlineTemplate;
|
||||
if(injectInOfflineScripts != null) {
|
||||
offlineTemplateArg = new File(temporaryDirectory, "offline_download_template.txt");
|
||||
try(BufferedReader indexReader = new BufferedReader(new FileReaderUTF(offlineTemplate));
|
||||
PrintWriter indexWriter = new PrintWriter(new FileWriterUTF(offlineTemplateArg))) {
|
||||
String line;
|
||||
while((line = indexReader.readLine()) != null) {
|
||||
if(line.contains("${classes_js}")) {
|
||||
for(int j = 0, l = injectInOfflineScripts.size(); j < l; ++j) {
|
||||
File injectFile = new File(injectInOfflineScripts.get(j));
|
||||
String injectName = injectFile.getAbsolutePath();
|
||||
String injectNameName = injectFile.getName();
|
||||
System.out.println("Adding file to offline download template: " + injectName);
|
||||
indexWriter.println("// %%%%%%%%% " + injectNameName + " %%%%%%%%%");
|
||||
indexWriter.println();
|
||||
try(BufferedReader insertReader = new BufferedReader(new FileReaderUTF(injectFile))) {
|
||||
String line2;
|
||||
while((line2 = insertReader.readLine()) != null) {
|
||||
indexWriter.println(line2);
|
||||
}
|
||||
}
|
||||
indexWriter.println();
|
||||
char[] percents = new char[20 + injectNameName.length()];
|
||||
for(int k = 0; k < percents.length; ++k) {
|
||||
percents[k] = '%';
|
||||
}
|
||||
indexWriter.print("// ");
|
||||
indexWriter.println(percents);
|
||||
indexWriter.println();
|
||||
indexWriter.println();
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
indexWriter.println(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/MakeOfflineDownload.jar");
|
||||
MakeOfflineDownload.compilerMain(offlineDownloadGenerator, new String[] {
|
||||
offlineTemplateArg.getAbsolutePath(),
|
||||
(new File(outputDirectory, "classes.js")).getAbsolutePath() + System.getProperty("path.separator")
|
||||
+ (new File(outputDirectory, "fix-webm-duration.js")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "assets.epk")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_en_US.html")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_International.html")).getAbsolutePath(),
|
||||
(new File(temporaryDirectory, "languages.epk")).getAbsolutePath()
|
||||
});
|
||||
}
|
||||
|
||||
System.out.println("Releasing external ClassLoader(s)...");
|
||||
System.out.println();
|
||||
|
||||
TeaVMBridge.free();
|
||||
EPKCompiler.free();
|
||||
|
||||
if(generateOffline) {
|
||||
MakeOfflineDownload.free();
|
||||
}
|
||||
|
||||
if(!keepTemporaryFiles) {
|
||||
System.out.println("Cleaning up temporary files...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(temporaryDirectory);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to delete temporary directory: " + temporaryDirectory.getAbsolutePath());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Client build successful! Check the output directory for your files");
|
||||
|
||||
}catch(CompileFailureException ex) {
|
||||
System.out.println();
|
||||
System.err.println("COMPILATION FAILED: " + ex.getMessage());
|
||||
System.out.println();
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ApplyPatchesToZip {
|
||||
|
||||
public static final int patchContextLength = 3;
|
||||
|
||||
public static void applyPatches(File zipIn, File unpatchedZipIn, File patchesIn, File zipOut, boolean compress, boolean useECR) throws Throwable {
|
||||
if(!patchesIn.isDirectory()) {
|
||||
FileUtils.copyFile(zipIn, zipOut);
|
||||
return;
|
||||
}
|
||||
Map<String,byte[]> jarEntriesUnpatched;
|
||||
if(unpatchedZipIn != null) {
|
||||
System.out.println("Loading files from '" + unpatchedZipIn.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(unpatchedZipIn)) {
|
||||
jarEntriesUnpatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesUnpatched = new WeakHashMap();
|
||||
}
|
||||
Map<String,byte[]> jarEntriesPatched;
|
||||
if(zipIn != null) {
|
||||
System.out.println("Loading files from '" + zipIn.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(zipIn)) {
|
||||
jarEntriesPatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesPatched = new WeakHashMap();
|
||||
}
|
||||
System.out.println("Patching files in '" + zipIn.getName() + "'...");
|
||||
final Map<String,byte[]> jarEntries = new HashMap();
|
||||
jarEntries.putAll(jarEntriesUnpatched);
|
||||
jarEntries.putAll(jarEntriesPatched);
|
||||
DiffSet diffs = new DiffSet();
|
||||
int totalLoad = diffs.loadFolder(patchesIn, useECR, useECR ? new DiffSet.SourceProvider() {
|
||||
@Override
|
||||
public List<String> getSource(String filename) throws IOException {
|
||||
byte[] etr = jarEntries.get(filename);
|
||||
if(etr == null) {
|
||||
throw new FileNotFoundException("Could not find source for: " + filename);
|
||||
}
|
||||
return Lines.linesList(new String(etr, StandardCharsets.UTF_8));
|
||||
}
|
||||
} : null);
|
||||
System.out.println(" loaded " + totalLoad + " patch files from the repo");
|
||||
System.out.println(" patching files...");
|
||||
System.out.print(" ");
|
||||
|
||||
int cnt = 0;
|
||||
int crtCnt = 0;
|
||||
int delCnt = 0;
|
||||
int repCnt = 0;
|
||||
int pthCnt = 0;
|
||||
try(ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(zipOut))) {
|
||||
jarOut.setLevel(compress ? 5 : 0);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
String nm;
|
||||
for(Entry<String,byte[]> et : jarEntries.entrySet()) {
|
||||
nm = et.getKey();
|
||||
if(!nm.startsWith("META-INF")) {
|
||||
Object op = diffs.diffs.get(nm);
|
||||
if(op != null) {
|
||||
if(op instanceof DiffSet.DeleteFunction) {
|
||||
++delCnt;
|
||||
continue;
|
||||
}else if(op instanceof DiffSet.ReplaceFunction) {
|
||||
jarOut.putNextEntry(new ZipEntry(nm));
|
||||
IOUtils.write(((DiffSet.ReplaceFunction)op).file, jarOut);
|
||||
++repCnt;
|
||||
}else if(op instanceof Patch<?>) {
|
||||
jarOut.putNextEntry(new ZipEntry(nm));
|
||||
List<String> lines = Lines.linesList(new String(et.getValue(), "UTF-8"));
|
||||
try {
|
||||
lines = ((Patch<String>)op).applyTo(lines);
|
||||
}catch(PatchFailedException ptch) {
|
||||
throw new IOException("Could not patch file \"" + nm + "\"!", ptch);
|
||||
}
|
||||
IOUtils.writeLines(lines, null, jarOut, "UTF-8");
|
||||
++pthCnt;
|
||||
}else {
|
||||
// ?
|
||||
}
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}else {
|
||||
if(jarEntriesPatched.containsKey(nm)) {
|
||||
jarOut.putNextEntry(new ZipEntry(nm));
|
||||
IOUtils.write(et.getValue(), jarOut);
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Entry<String,byte[]> etr : diffs.recreate.entrySet()) {
|
||||
jarOut.putNextEntry(new ZipEntry(etr.getKey()));
|
||||
IOUtils.write(etr.getValue(), jarOut);
|
||||
++crtCnt;
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Patched " + pthCnt + " files");
|
||||
System.out.println("Restored " + crtCnt + " files");
|
||||
System.out.println("Replaced " + repCnt + " files");
|
||||
System.out.println("Deleted " + delCnt + " files");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class DiffSet {
|
||||
|
||||
public static class DeleteFunction {
|
||||
private DeleteFunction() {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReplaceFunction {
|
||||
public final byte[] file;
|
||||
private ReplaceFunction(byte[] file) {
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
||||
public static final DeleteFunction deleteFunction = new DeleteFunction();
|
||||
|
||||
public final Map<String,Object> diffs;
|
||||
public final Map<String,byte[]> recreate;
|
||||
|
||||
public DiffSet() {
|
||||
diffs = new HashMap();
|
||||
recreate = new HashMap();
|
||||
}
|
||||
|
||||
private static final Pattern editPattern = Pattern.compile(".*\\.edit(\\.[^\\.\\/\\\\]+)?$");
|
||||
private static final Pattern replacePattern = Pattern.compile(".*\\.replace(\\.[^\\.\\/\\\\]+)?$");
|
||||
private static final Pattern deletePattern = Pattern.compile(".*\\.delete(\\.[^\\.\\/\\\\]+)?$");
|
||||
private static final Pattern recreatePattern = Pattern.compile(".*\\.recreate(\\.[^\\.\\/\\\\]+)?$");
|
||||
|
||||
public int loadFolder(File pathIn, boolean useECR, SourceProvider ecrContextProvider) throws IOException {
|
||||
String baseAbsolutePath = pathIn.getAbsolutePath();
|
||||
int total = 0;
|
||||
|
||||
File del = new File(pathIn, "delete.txt");
|
||||
if(del.isFile()) {
|
||||
Collection<String> cl = FileUtils.readLines(del, "UTF-8");
|
||||
for(String s : cl) {
|
||||
s = s.trim();
|
||||
s = s.replace('\\', '/');
|
||||
if(!s.startsWith("#")) {
|
||||
if(s.startsWith("/")) {
|
||||
s = s.substring(1);
|
||||
}
|
||||
diffs.put(s, deleteFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection<File> fl = FileUtils.listFiles(pathIn, null, true);
|
||||
Iterator<File> fi = fl.iterator();
|
||||
while(fi.hasNext()) {
|
||||
File f = fi.next();
|
||||
String fName = f.getAbsolutePath().replace(baseAbsolutePath, "").replace('\\', '/');
|
||||
if(fName.startsWith("/")) {
|
||||
fName = fName.substring(1);
|
||||
}
|
||||
if(editPattern.matcher(fName).matches()) {
|
||||
try {
|
||||
String nm = removeExt(fName, "edit");
|
||||
Patch<String> pth;
|
||||
if(useECR) {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8))) {
|
||||
pth = EaglerContextRedacted.readContextRestricted(ecrContextProvider.getSource(nm), reader);
|
||||
}
|
||||
}else {
|
||||
List<String> phile = FileUtils.readLines(f, "UTF-8");
|
||||
pth = UnifiedDiffUtils.parseUnifiedDiff(phile);
|
||||
}
|
||||
if(pth == null) {
|
||||
throw new IOException("Invalid DIFF file!");
|
||||
}
|
||||
diffs.put(nm, pth);
|
||||
++total;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not read '" + fName + "'!");
|
||||
}
|
||||
}else if(replacePattern.matcher(fName).matches()) {
|
||||
try {
|
||||
diffs.put(removeExt(fName, "replace"), new ReplaceFunction(FileUtils.readFileToByteArray(f)));
|
||||
++total;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not read '" + fName + "'!");
|
||||
}
|
||||
}else if(deletePattern.matcher(fName).matches()) {
|
||||
diffs.put(removeExt(fName, "delete"), deleteFunction);
|
||||
++total;
|
||||
}else if(recreatePattern.matcher(fName).matches()) {
|
||||
try {
|
||||
String str = removeExt(fName, "recreate");
|
||||
recreate.put(str, FileUtils.readFileToByteArray(f));
|
||||
diffs.remove(str);
|
||||
++total;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not read '" + fName + "'!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
private static String removeExt(String fn, String ext) {
|
||||
int end = fn.lastIndexOf("." + ext);
|
||||
if(end != -1) {
|
||||
return fn.substring(0, end) + fn.substring(end + ext.length() + 1, fn.length());
|
||||
}else {
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface SourceProvider {
|
||||
List<String> getSource(String filename) throws IOException;
|
||||
}
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.ChangeDelta;
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import com.github.difflib.patch.DeleteDelta;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
import com.github.difflib.patch.InsertDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EaglerContextRedacted {
|
||||
|
||||
public static void writeContextRedacted(Patch<String> patch, PrintWriter output) {
|
||||
Date theDate = new Date();
|
||||
|
||||
output.println();
|
||||
output.println("# Eagler Context Redacted Diff");
|
||||
output.println("# Copyright (c) " + (new SimpleDateFormat("yyyy")).format(theDate) + " lax1dude. All rights reserved.");
|
||||
output.println();
|
||||
output.println("# Version: 1.0");
|
||||
output.println("# Author: lax1dude");
|
||||
output.println();
|
||||
|
||||
List<AbstractDelta<String>> deltas = patch.getDeltas();
|
||||
delta_itr: for(int i = 0, l = deltas.size(); i < l; ++i) {
|
||||
AbstractDelta<String> delta = deltas.get(i);
|
||||
|
||||
DeltaType type = delta.getType();
|
||||
String blockType;
|
||||
String blockPrefix;
|
||||
switch(type) {
|
||||
case CHANGE:
|
||||
blockType = "> CHANGE";
|
||||
blockPrefix = "~ ";
|
||||
break;
|
||||
case DELETE:
|
||||
blockType = "> DELETE";
|
||||
blockPrefix = "- ";
|
||||
break;
|
||||
case EQUAL:
|
||||
continue delta_itr;
|
||||
case INSERT:
|
||||
blockType = "> INSERT";
|
||||
blockPrefix = "+ ";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid type " + type + " for delta " + i);
|
||||
}
|
||||
|
||||
Chunk<String> source = delta.getSource();
|
||||
int sourcePos = source.getPosition();
|
||||
int sourceLen = source.getLines().size();
|
||||
|
||||
Chunk<String> target = delta.getTarget();
|
||||
int targetPos = target.getPosition();
|
||||
List<String> linesToWrite = target.getLines();
|
||||
int targetLen = linesToWrite.size();
|
||||
|
||||
output.println(blockType + " " + targetPos + (targetLen > 0 ? " : " + (targetPos + targetLen) : "") + " @ "
|
||||
+ sourcePos + (sourceLen > 0 ? " : " + (sourcePos + sourceLen) : ""));
|
||||
|
||||
output.println();
|
||||
|
||||
if(targetLen > 0) {
|
||||
for(int j = 0, ll = linesToWrite.size(); j < ll; ++j) {
|
||||
output.println(blockPrefix + linesToWrite.get(j));
|
||||
}
|
||||
|
||||
output.println();
|
||||
}
|
||||
}
|
||||
|
||||
output.println("> EOF");
|
||||
}
|
||||
|
||||
public static Patch<String> readContextRestricted(List<String> context, BufferedReader reader) throws IOException {
|
||||
Patch<String> newPatch = new Patch();
|
||||
|
||||
DeltaType currentDeltaType = null;
|
||||
int sourceStart = 0;
|
||||
int sourceLen = 0;
|
||||
int targetStart = 0;
|
||||
int targetLen = 0;
|
||||
List<String> targetLines = null;
|
||||
|
||||
String line;
|
||||
readLinesLoop: while((line = reader.readLine()) != null) {
|
||||
if(line.length() < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(line.charAt(1) != ' ') {
|
||||
throw new IOException("Unknown line type: " + line.substring(0, 2));
|
||||
}
|
||||
|
||||
char lineType = line.charAt(0);
|
||||
String value = line.substring(2);
|
||||
|
||||
switch(lineType) {
|
||||
case '#':
|
||||
int idx = value.indexOf(':');
|
||||
if(idx > 0) {
|
||||
String k = value.substring(0, idx).trim().toLowerCase();
|
||||
if(k.equals("version")) {
|
||||
String v = value.substring(idx + 1).trim();
|
||||
if(!v.equals("1.0")) {
|
||||
throw new IOException("Unsupported format version: " + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
|
||||
String[] split = value.trim().split("[\\s]+");
|
||||
|
||||
if(split.length == 1 && split[0].equals("EOF")) {
|
||||
break readLinesLoop;
|
||||
}
|
||||
|
||||
if(split.length < 4 ||
|
||||
!((split[2].equals("@") && (split.length == 4 || (split.length == 6 && split[4].equals(":")))) ||
|
||||
(split[2].equals(":") && ((split.length == 6 && split[4].equals("@")) || (split.length == 8 && split[4].equals("@") && split[6].equals(":")))))) {
|
||||
throw new IOException("Invalid block: [ " + String.join(" ", split) + " ]");
|
||||
}
|
||||
|
||||
if(currentDeltaType != null) {
|
||||
newPatch.addDelta(makeDelta(currentDeltaType, sourceStart, sourceLen, targetStart, targetLen, context, targetLines));
|
||||
}
|
||||
|
||||
switch(split[0]) {
|
||||
case "CHANGE":
|
||||
currentDeltaType = DeltaType.CHANGE;
|
||||
break;
|
||||
case "DELETE":
|
||||
currentDeltaType = DeltaType.DELETE;
|
||||
break;
|
||||
case "INSERT":
|
||||
currentDeltaType = DeltaType.INSERT;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unknown line block: " + split[0]);
|
||||
}
|
||||
|
||||
targetLines = null;
|
||||
|
||||
targetStart = parseInt(split[1]);
|
||||
|
||||
if(split[2].equals(":")) {
|
||||
targetLen = parseInt(split[3]) - targetStart;
|
||||
sourceStart = parseInt(split[5]);
|
||||
if(split.length == 8) {
|
||||
sourceLen = parseInt(split[7]) - sourceStart;
|
||||
}else {
|
||||
sourceLen = 0;
|
||||
}
|
||||
}else {
|
||||
targetLen = 0;
|
||||
sourceStart = parseInt(split[3]);
|
||||
if(split.length == 6) {
|
||||
sourceLen = parseInt(split[5]) - sourceStart;
|
||||
}else {
|
||||
sourceLen = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '~':
|
||||
if(currentDeltaType != DeltaType.CHANGE) {
|
||||
throw new IOException("Read an unexpected CHANGE line in a " + currentDeltaType + " block: " + line);
|
||||
}else {
|
||||
if(targetLines == null) targetLines = new ArrayList();
|
||||
targetLines.add(value);
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
if(currentDeltaType != DeltaType.DELETE) {
|
||||
throw new IOException("Read an unexpected DELETE line in a " + currentDeltaType + " block: " + line);
|
||||
}else {
|
||||
if(targetLines == null) targetLines = new ArrayList();
|
||||
targetLines.add(value);
|
||||
}
|
||||
break;
|
||||
case '+':
|
||||
if(currentDeltaType != DeltaType.INSERT) {
|
||||
throw new IOException("Read an unexpected INSERT line in a " + currentDeltaType + " block: " + line);
|
||||
}else {
|
||||
if(targetLines == null) targetLines = new ArrayList();
|
||||
targetLines.add(value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unknown line type: " + lineType);
|
||||
}
|
||||
}
|
||||
|
||||
if(currentDeltaType != null) {
|
||||
newPatch.addDelta(makeDelta(currentDeltaType, sourceStart, sourceLen, targetStart, targetLen, context, targetLines));
|
||||
}
|
||||
|
||||
return newPatch;
|
||||
}
|
||||
|
||||
private static int parseInt(String str) throws IOException {
|
||||
try {
|
||||
return Integer.parseInt(str);
|
||||
}catch(NumberFormatException ex) {
|
||||
throw new IOException("Value is not a valid integer: \"" + str + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
private static AbstractDelta<String> makeDelta(DeltaType deltaType, int sourceStart, int sourceLen,
|
||||
int targetStart, int targetLen, List<String> context, List<String> targetLines) throws IOException {
|
||||
List<String> sourceLines = new ArrayList(sourceLen);
|
||||
for(int i = 0; i < sourceLen; ++i) {
|
||||
sourceLines.add(context.get(sourceStart + i));
|
||||
}
|
||||
if(targetLines == null) {
|
||||
targetLines = new ArrayList(0);
|
||||
}
|
||||
if(targetLen != targetLines.size()) {
|
||||
throw new IOException("" + deltaType + " block at sourceStart " + sourceStart + " is " + targetLen
|
||||
+ " lines long but only " + targetLines.size() + " lines were read!");
|
||||
}
|
||||
switch(deltaType) {
|
||||
case CHANGE:
|
||||
return new ChangeDelta(new Chunk(sourceStart, sourceLines), new Chunk(targetStart, targetLines));
|
||||
case DELETE:
|
||||
return new DeleteDelta(new Chunk(sourceStart, sourceLines), new Chunk(targetStart, targetLines));
|
||||
case INSERT:
|
||||
return new InsertDelta(new Chunk(sourceStart, sourceLines), new Chunk(targetStart, targetLines));
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid delta type: " + deltaType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class JARMemoryCache {
|
||||
|
||||
public static Map<String,byte[]> loadJAR(InputStream is) throws IOException {
|
||||
Map<String,byte[]> ret = new HashMap();
|
||||
ZipInputStream isz = new ZipInputStream(is);
|
||||
ZipEntry et;
|
||||
while((et = isz.getNextEntry()) != null) {
|
||||
if(!et.isDirectory()) {
|
||||
String n = et.getName();
|
||||
if(n.startsWith("/")) {
|
||||
n = n.substring(1);
|
||||
}
|
||||
if(!n.startsWith("META-INF")) {
|
||||
byte[] data = IOUtils.toByteArray(isz);
|
||||
ret.put(n, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class Lines {
|
||||
|
||||
public static final Pattern splitPattern = Pattern.compile("(\\r\\n|\\n|\\r)");
|
||||
|
||||
public static String[] linesArray(String input) {
|
||||
return splitPattern.split(input);
|
||||
}
|
||||
|
||||
public static List<String> linesList(String input) {
|
||||
return Arrays.asList(splitPattern.split(input));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,529 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InsertJavaDoc;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.SetupWorkspace;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class MergePullRequest {
|
||||
|
||||
public static boolean mergeTask() {
|
||||
try {
|
||||
return mergeTask0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean mergeTask0() throws Throwable {
|
||||
File pullRequestDir = new File("pullrequest");
|
||||
|
||||
if(!pullRequestDir.isDirectory() || FileUtils.isEmptyDirectory(pullRequestDir)) {
|
||||
System.err.println("ERROR: the 'pullrequest' directory does not exist or is empty, aborting merge because there's nothing to merge");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((new File(pullRequestDir, "merged.txt")).exists()) {
|
||||
System.err.println("ERROR: the 'pullrequest' directory has already been merged, aborting merge because there's nothing to merge");
|
||||
System.err.println("To override, delete 'merged.txt' from the folder.");
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Warning: running 'merge' is a command only intended to be used");
|
||||
System.out.println("by the repository's owner, it will perminantly incorporate all");
|
||||
System.out.println("changes in the 'pullrequest' directory into this repository's");
|
||||
System.out.println("patch file directory!");
|
||||
System.out.println();
|
||||
System.out.println("Doing so will make it impossible to reliably create any future");
|
||||
System.out.println("pull requests back to this project's main repository, unless the");
|
||||
System.out.println("main repository has merged the same pull request into it's patch");
|
||||
System.out.println("file directory too.");
|
||||
System.out.println();
|
||||
System.out.println("Back up the current state of the patch file directory in a local");
|
||||
System.out.println("commit or branch to allow you to undo any unintentional changes");
|
||||
System.out.println("made to the directory as a result of running this command.");
|
||||
System.out.println();
|
||||
System.out.print("Do you really want to do this? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("OKAY THANK GOD, crisis averted!");
|
||||
System.out.println();
|
||||
System.out.println("Thank the author of this tool kindly for providing this check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Warning: close all programs that may have files or folders open");
|
||||
System.out.println("in the repository or the merge could fail catastrophically");
|
||||
System.out.println();
|
||||
System.out.println("This folder: " + (new File(".")).getAbsolutePath());
|
||||
System.out.println();
|
||||
System.out.println("Check for any file explorer windows displaying the contents of a");
|
||||
System.out.println("file or folder in this directory.");
|
||||
System.out.println();
|
||||
System.out.println("Close any programs with files open someplace in this folder.");
|
||||
System.out.println();
|
||||
System.out.println("If merging fails, revert all changes in this directory with git");
|
||||
System.out.println("or a backup, re-run 'init', then run 'pullrequest' and 'merge'");
|
||||
System.out.println();
|
||||
System.out.print("Did you close everything? [Y/n]: ");
|
||||
|
||||
ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("OKAY THANK GOD, crisis averted!");
|
||||
System.out.println();
|
||||
System.out.println("Thank the author of this tool kindly for providing this check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
File temporaryDirectory = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
System.out.println();
|
||||
|
||||
File pullRequestToSrc = new File(pullRequestDir, "source");
|
||||
File pullRequestToRes = new File(pullRequestDir, "resources");
|
||||
|
||||
boolean prSrcExist = pullRequestToSrc.isDirectory() && !FileUtils.isEmptyDirectory(pullRequestToSrc);
|
||||
boolean prResExist = pullRequestToRes.isDirectory() && !FileUtils.isEmptyDirectory(pullRequestToRes);
|
||||
|
||||
if(!prSrcExist && !prResExist) {
|
||||
System.err.println("ERROR: the 'pullrequest' directory does not exist or is empty, aborting merge because there's nothing to merge");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(prSrcExist) {
|
||||
File tmpOriginalUnpatched = new File(temporaryDirectory, "MinecraftSrc/minecraft_src.jar");
|
||||
if(!tmpOriginalUnpatched.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginalUnpatched.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpOriginal = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_patch.jar");
|
||||
if(!tmpOriginal.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginal.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpMerged = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_merge.jar");
|
||||
File tmpMergedDiffs = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_merge_diffs.zip");
|
||||
|
||||
System.out.println("Applying pull request to '" + tmpOriginal.getName() + "'...");
|
||||
System.out.println();
|
||||
ApplyPatchesToZip.applyPatches(tmpOriginal, tmpOriginalUnpatched, pullRequestToSrc, tmpMerged, true, false);
|
||||
|
||||
try {
|
||||
createMergeDiffs(tmpMerged, tmpOriginalUnpatched, tmpMergedDiffs);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
File patchOut = new File("./patches/minecraft");
|
||||
File patchTmpOut = new File("./patches.bak/minecraft");
|
||||
if(patchOut.exists()) {
|
||||
System.out.println("Backing up '" + patchOut.getAbsolutePath() + "'...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
FileUtils.moveDirectory(patchOut, patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
FileUtils.copyFile(new File(patchTmpOut, "output_license.txt"), new File(patchOut, "output_license.txt"));
|
||||
|
||||
System.out.println("Extracting '" + tmpMergedDiffs + "' to 'patches/minecraft'...");
|
||||
int cnt = SetupWorkspace.extractJarTo(tmpMergedDiffs, patchOut);
|
||||
|
||||
if(!tmpMergedDiffs.delete()) {
|
||||
System.err.println("ERROR: could not delete '" + tmpMergedDiffs.getName() + "'!");
|
||||
}
|
||||
|
||||
System.out.println("Wrote " + cnt + " files.");
|
||||
|
||||
System.out.println("Copying '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'...");
|
||||
|
||||
if((tmpOriginal.exists() && !tmpOriginal.delete()) || !tmpMerged.renameTo(tmpOriginal)) {
|
||||
System.err.println("ERROR: could not copy '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'!");
|
||||
System.err.println("Run the 'init' task again before proceeding");
|
||||
tmpOriginal.delete();
|
||||
}else {
|
||||
File javadocOut = new File(temporaryDirectory, "MinecraftSrc/minecraft_src_javadoc.jar");
|
||||
CSVMappings comments = new CSVMappings();
|
||||
if(!InsertJavaDoc.processSource(tmpOriginal, javadocOut, new File(temporaryDirectory, "ModCoderPack"), comments)) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not create javadoc!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(tmpMerged.exists()) {
|
||||
tmpMerged.delete();
|
||||
}
|
||||
|
||||
System.out.println("Deleting backup folder...");
|
||||
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: could not delete 'patches.bak/minecraft'!");
|
||||
System.err.println(t.toString());
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
if(prResExist) {
|
||||
File tmpOriginalUnpatched = new File(temporaryDirectory, "MinecraftSrc/minecraft_res.jar");
|
||||
if(!tmpOriginalUnpatched.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginalUnpatched.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpOriginal = new File(temporaryDirectory, "MinecraftSrc/minecraft_res_patch.jar");
|
||||
if(!tmpOriginal.isFile()) {
|
||||
System.err.println("ERROR: file '" + tmpOriginal.getName() + "' was not found!");
|
||||
System.err.println("Run the 'init' task again to re-generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpMerged = new File(temporaryDirectory, "MinecraftSrc/minecraft_res_merge.jar");
|
||||
File tmpMergedDiffs = new File(temporaryDirectory, "MinecraftSrc/minecraft_res_merge_diffs.zip");
|
||||
|
||||
System.out.println("Applying pull request to '" + tmpOriginal.getName() + "'...");
|
||||
System.out.println();
|
||||
ApplyPatchesToZip.applyPatches(tmpOriginal, tmpOriginalUnpatched, pullRequestToRes, tmpMerged, true, false);
|
||||
|
||||
try {
|
||||
createMergeDiffs(tmpMerged, tmpOriginalUnpatched, tmpMergedDiffs);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
File patchOut = new File("./patches/resources");
|
||||
File patchTmpOut = new File("./patches.bak/resources");
|
||||
if(patchOut.exists()) {
|
||||
System.out.println("Backing up '" + patchOut.getAbsolutePath() + "'...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
FileUtils.moveDirectory(patchOut, patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
tmpMerged.delete();
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Extracting '" + tmpMergedDiffs + "' to 'patches/resources'...");
|
||||
int cnt = SetupWorkspace.extractJarTo(tmpMergedDiffs, patchOut);
|
||||
|
||||
if(!tmpMergedDiffs.delete()) {
|
||||
System.err.println("ERROR: could not delete '" + tmpMergedDiffs.getName() + "'!");
|
||||
}
|
||||
|
||||
System.out.println("Wrote " + cnt + " files.");
|
||||
|
||||
System.out.println("Copying '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'...");
|
||||
|
||||
if((tmpOriginal.exists() && !tmpOriginal.delete()) || !tmpMerged.renameTo(tmpOriginal)) {
|
||||
System.err.println("ERROR: could not copy '" + tmpMerged.getName() + "' to '" + tmpOriginal.getName() + "'!");
|
||||
System.err.println("Run the 'init' task again before proceeding");
|
||||
tmpOriginal.delete();
|
||||
}
|
||||
|
||||
if(tmpMerged.exists()) {
|
||||
tmpMerged.delete();
|
||||
}
|
||||
|
||||
System.out.println("Deleting backup folder...");
|
||||
try {
|
||||
FileUtils.deleteDirectory(patchTmpOut);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: could not delete 'patches.bak/resources'!");
|
||||
System.err.println(t.getMessage());
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
(new File("./patches.bak")).delete();
|
||||
|
||||
System.out.println("Successfully merged pullrequest directory!");
|
||||
|
||||
try {
|
||||
SimpleDateFormat fmt1 = new SimpleDateFormat("MM-dd-yy");
|
||||
SimpleDateFormat fmt2 = new SimpleDateFormat("kk:mm:ss");
|
||||
Date dt = new Date();
|
||||
FileUtils.writeStringToFile(new File(pullRequestDir, "merged.txt"), "This pullrequest was merged on " +
|
||||
fmt1.format(new Date()) + " at " + fmt2.format(dt) + ".", "UTF-8");
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not write 'merged.txt' in pullrequest directory!");
|
||||
System.err.println("Creating a file called 'merged.txt' is important to tell buildtools that the");
|
||||
System.err.println("existing pullrequest has already been merged! Do not try to merge it again!");
|
||||
}
|
||||
|
||||
System.out.println("Backing up to 'pullrequest_merged_backup'...");
|
||||
|
||||
String pth = pullRequestDir.getAbsolutePath();
|
||||
if(pth.endsWith("/") || pth.endsWith("\\")) {
|
||||
pth = pth.substring(0, pth.length() - 1);
|
||||
}
|
||||
|
||||
File m0 = new File(pth + "_merged_backup");
|
||||
|
||||
if(m0.exists() && !FileUtils.deleteQuietly(m0)) {
|
||||
System.err.println("Could not delete old backup!");
|
||||
m0 = new File(pth + "_merged_backup1");
|
||||
if(m0.exists() && !FileUtils.deleteQuietly(m0)) {
|
||||
System.err.println("Could not delete 2nd old backup!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.moveDirectory(pullRequestDir, m0);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not create backup!");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void createMergeDiffs(File tmpMerged, File tmpOriginalUnpatched, File tmpMergedDiffs) throws Throwable {
|
||||
System.out.println("Creating patches from '" + tmpMerged.getName() + "'...");
|
||||
|
||||
System.out.println("Loading files from '" + tmpOriginalUnpatched.getName() + "'...");
|
||||
Map<String, byte[]> memoryCacheUnpatched;
|
||||
try(InputStream is = new FileInputStream(tmpOriginalUnpatched)) {
|
||||
memoryCacheUnpatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
|
||||
if(memoryCacheUnpatched == null) {
|
||||
throw new IOException("Failed to load JAR into memory: '" + tmpOriginalUnpatched.getName());
|
||||
}
|
||||
|
||||
System.out.println("Loading files from '" + tmpMerged.getName() + "'...");
|
||||
Map<String, byte[]> memoryCacheMerged;
|
||||
try(InputStream is = new FileInputStream(tmpMerged)) {
|
||||
memoryCacheMerged = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
|
||||
if(memoryCacheMerged == null) {
|
||||
throw new IOException("Failed to load JAR into memory: '" + tmpMerged.getName());
|
||||
}
|
||||
|
||||
Set<String> deleteList = new HashSet();
|
||||
deleteList.addAll(memoryCacheUnpatched.keySet());
|
||||
|
||||
System.out.println("Generating patch files..");
|
||||
System.out.println("(Writing to: " + tmpMergedDiffs.getName() + ")");
|
||||
System.out.println("(this may take a while)");
|
||||
System.out.print(" ");
|
||||
int cnt = 0;
|
||||
try(ZipOutputStream mgd = new ZipOutputStream(new FileOutputStream(tmpMergedDiffs))) {
|
||||
mgd.setLevel(5);
|
||||
for(Entry<String,byte[]> met : memoryCacheMerged.entrySet()) {
|
||||
String n = met.getKey();
|
||||
byte[] orig = memoryCacheUnpatched.get(n);
|
||||
if(orig == null) {
|
||||
System.err.println("Error: tried to patch file '" + n + "' that doesn't exist in the minecraft source");
|
||||
continue;
|
||||
}
|
||||
deleteList.remove(n);
|
||||
if(writeDiff(orig, met.getValue(), n, mgd)) {
|
||||
++cnt;
|
||||
if(cnt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Wrote " + cnt + " patch files.");
|
||||
|
||||
mgd.putNextEntry(new ZipEntry("delete.txt"));
|
||||
PrintWriter delWriter = new PrintWriter(mgd);
|
||||
delWriter.println("# " + deleteList.size() + " files to delete:");
|
||||
for(String s : deleteList) {
|
||||
delWriter.println(s);
|
||||
}
|
||||
delWriter.flush();
|
||||
|
||||
System.out.println("Wrote " + deleteList.size() + " deletes.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean writeDiff(byte[] old, byte[] _new, String outName, ZipOutputStream output) throws IOException {
|
||||
if(Arrays.equals(old, _new)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String oldStr = toStringIfValid(old);
|
||||
String newStr = oldStr == null ? null : toStringIfValid(_new);
|
||||
|
||||
if(oldStr == null || newStr == null) {
|
||||
output.putNextEntry(new ZipEntry(makeName(outName, "replace")));
|
||||
IOUtils.write(_new, output);
|
||||
return true;
|
||||
}else {
|
||||
List<String> oldLines = Lines.linesList(oldStr);
|
||||
List<String> newLines = Lines.linesList(newStr);
|
||||
Patch<String> deltas = DiffUtils.diff(oldLines, newLines);
|
||||
|
||||
// List<String> diffFile = UnifiedDiffUtils.generateUnifiedDiff(outName, outName, oldLines, deltas, ApplyPatchesToZip.patchContextLength);
|
||||
//
|
||||
// if(diffFile.size() == 0) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// output.putNextEntry(new ZipEntry(makeName(outName, "edit")));
|
||||
// PrintWriter foutStream = new PrintWriter(output);
|
||||
// for(int i = 0, l = diffFile.size(); i < l; ++i) {
|
||||
// foutStream.println(diffFile.get(i));
|
||||
// }
|
||||
// foutStream.flush();
|
||||
|
||||
output.putNextEntry(new ZipEntry(makeName(outName, "edit")));
|
||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"));
|
||||
EaglerContextRedacted.writeContextRedacted(deltas, writer);
|
||||
writer.flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String makeName(String input, String type) {
|
||||
int lastSlash = input.lastIndexOf('/');
|
||||
int lastDot = input.lastIndexOf('.');
|
||||
if(lastDot > lastSlash + 1) {
|
||||
return input.substring(0, lastDot) + "." + type + input.substring(lastDot);
|
||||
}else {
|
||||
return input + "." + type;
|
||||
}
|
||||
}
|
||||
|
||||
private static final CharsetDecoder utf8Decoder = StandardCharsets.UTF_8.newDecoder();
|
||||
|
||||
private static String toStringIfValid(byte[] in) {
|
||||
ByteBuffer inn = ByteBuffer.wrap(in);
|
||||
CharBuffer cb;
|
||||
try {
|
||||
cb = utf8Decoder.decode(inn);
|
||||
}catch(Throwable t) {
|
||||
return null;
|
||||
}
|
||||
return cb.toString();
|
||||
}
|
||||
|
||||
public static boolean mergeDirect() {
|
||||
try {
|
||||
return mergeDirect0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge_direct'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean mergeDirect0() throws Throwable {
|
||||
|
||||
if(!PullRequestTask.pullRequest()) {
|
||||
System.err.println();
|
||||
System.err.println("Error: could not create merge_direct pull request!");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if(!mergeTask0()) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge_direct'!");
|
||||
return false;
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'merge_direct'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,426 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.diff;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.formatter.EclipseFormatter;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.InsertJavaDoc;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class PullRequestTask {
|
||||
|
||||
public static boolean pullRequest() {
|
||||
try {
|
||||
return pullRequest0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'pullrequest'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean pullRequest0() throws Throwable {
|
||||
File originalUnpatchedSourceMainJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_src.jar");
|
||||
File originalSourceMainJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_src_patch.jar");
|
||||
File minecraftJavadocTmp = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_src_javadoc.jar");
|
||||
File originalSourceMain = new File(EaglerBuildTools.repositoryRoot, "sources/main/java");
|
||||
File originalSourceTeaVM = new File(EaglerBuildTools.repositoryRoot, "sources/teavm/java");
|
||||
File originalSourceLWJGL = new File(EaglerBuildTools.repositoryRoot, "sources/lwjgl/java");
|
||||
File originalUnpatchedSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res.jar");
|
||||
File originalSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res_patch.jar");
|
||||
File originalSourceResources = new File(EaglerBuildTools.repositoryRoot, "sources/resources");
|
||||
File diffFromMain = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/main/java");
|
||||
File diffFromTeaVM = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavm/java");
|
||||
File diffFromLWJGL = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/lwjgl/java");
|
||||
File diffFromResources = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "desktopRuntime/resources");
|
||||
File pullRequestTo = new File(EaglerBuildTools.repositoryRoot, "pullrequest");
|
||||
|
||||
boolean prExist = pullRequestTo.exists();
|
||||
if(prExist && !(pullRequestTo.isDirectory() && pullRequestTo.list().length == 0)) {
|
||||
System.out.println();
|
||||
System.out.print("Warning: The 'pullrequest' folder already exists in your repository. Overwrite? [Y/n]: ");
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("The pull request was cancelled.");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
FileUtils.deleteDirectory(pullRequestTo);
|
||||
prExist = false;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + pullRequestTo.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!prExist && !pullRequestTo.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create folder \"" + pullRequestTo.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
File pullRequestToMain = new File(pullRequestTo, "source");
|
||||
File pullRequestToResources = new File(pullRequestTo, "resources");
|
||||
|
||||
boolean flag = false;
|
||||
int i = copyAllModified(diffFromTeaVM, originalSourceTeaVM);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/teavm/java/");
|
||||
|
||||
i = copyAllModified(diffFromLWJGL, originalSourceLWJGL);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/lwjgl/java/");
|
||||
|
||||
i = createDiffFiles(originalSourceMain, minecraftJavadocTmp, originalUnpatchedSourceMainJar,
|
||||
originalSourceMainJar, diffFromMain, pullRequestToMain, true);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/main/java/");
|
||||
|
||||
i = createDiffFiles(originalSourceResources, originalSourceResourcesJar, originalUnpatchedSourceResourcesJar,
|
||||
null, diffFromResources, pullRequestToResources, false);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /desktopRuntime/resources/");
|
||||
|
||||
if(!flag) {
|
||||
System.out.println("ERROR: No modified files were found!");
|
||||
if(pullRequestTo.exists()) {
|
||||
pullRequestTo.delete();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int createDiffFiles(File folderOriginal, File jarOriginal, File jarOriginalUnpatched, File originalJarNoJavadoc,
|
||||
File folderEdited, File folderOut, boolean isJava) throws Throwable {
|
||||
if(!folderEdited.isDirectory()) {
|
||||
return 0;
|
||||
}
|
||||
boolean createdFolderOut = folderOut.isDirectory();
|
||||
int cnt = 0;
|
||||
Collection<File> workspaceFiles = FileUtils.listFiles(folderEdited, null, true);
|
||||
Map<String,byte[]> jarEntriesUnpatched;
|
||||
if(jarOriginalUnpatched != null) {
|
||||
System.out.println("Loading files from '" + jarOriginalUnpatched.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(jarOriginalUnpatched)) {
|
||||
jarEntriesUnpatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesUnpatched = new WeakHashMap();
|
||||
}
|
||||
Map<String,byte[]> jarEntriesPatched;
|
||||
if(jarOriginal != null) {
|
||||
System.out.println("Loading files from '" + jarOriginal.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(jarOriginal)) {
|
||||
jarEntriesPatched = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesPatched = new WeakHashMap();
|
||||
}
|
||||
Map<String,byte[]> jarEntries = new HashMap();
|
||||
jarEntries.putAll(jarEntriesUnpatched);
|
||||
jarEntries.putAll(jarEntriesPatched);
|
||||
Map<String,byte[]> jarEntriesNoJavadoc;
|
||||
if(originalJarNoJavadoc != null) {
|
||||
System.out.println("Loading files from '" + originalJarNoJavadoc.getName() + "'...");
|
||||
try(FileInputStream is = new FileInputStream(originalJarNoJavadoc)) {
|
||||
jarEntriesNoJavadoc = JARMemoryCache.loadJAR(is);
|
||||
}
|
||||
}else {
|
||||
jarEntriesNoJavadoc = new WeakHashMap();
|
||||
}
|
||||
System.out.println("Comparing...");
|
||||
System.out.println("(this may take a while)");
|
||||
String editedPrefix = folderEdited.getAbsolutePath();
|
||||
Set<String> filesReplaced = new HashSet();
|
||||
for(File wf : workspaceFiles) {
|
||||
String newPath = wf.getAbsolutePath().replace(editedPrefix, "");
|
||||
if(newPath.indexOf('\\') != -1) {
|
||||
newPath = newPath.replace('\\', '/');
|
||||
}
|
||||
if(newPath.startsWith("/")) {
|
||||
newPath = newPath.substring(1);
|
||||
}
|
||||
File orig = new File(folderOriginal, newPath);
|
||||
byte[] jarData = null;
|
||||
boolean replacedFileExists = orig.exists();
|
||||
if(replacedFileExists) {
|
||||
filesReplaced.add(newPath);
|
||||
if(copyFileIfChanged(wf, orig)) {
|
||||
++cnt;
|
||||
}
|
||||
}else if((jarData = jarEntries.get(newPath)) != null) {
|
||||
filesReplaced.add(newPath);
|
||||
byte [] o = jarData;
|
||||
byte [] n = FileUtils.readFileToByteArray(wf);
|
||||
boolean changed = false;
|
||||
if(o.length != n.length) {
|
||||
if(!createdFolderOut) {
|
||||
if(!folderOut.mkdirs()) {
|
||||
throw new IOException("Could not create folder: \"" + folderOut.getAbsolutePath() + "\"!");
|
||||
}
|
||||
createdFolderOut = true;
|
||||
}
|
||||
String noJavaDocString = null;
|
||||
byte[] noJavaDoc = jarEntriesNoJavadoc.get(newPath);
|
||||
if(noJavaDoc != null) {
|
||||
noJavaDocString = new String(noJavaDoc, StandardCharsets.UTF_8);
|
||||
}
|
||||
if(writeDiff(o, n, folderOut, newPath, isJava, noJavaDocString)) {
|
||||
changed = true;
|
||||
++cnt;
|
||||
}
|
||||
}else {
|
||||
for(int i = 0; i < o.length; ++i) {
|
||||
if(o[i] != n[i]) {
|
||||
if(!createdFolderOut) {
|
||||
if(!folderOut.mkdirs()) {
|
||||
throw new IOException("Could not create folder: \"" + folderOut.getAbsolutePath() + "\"!");
|
||||
}
|
||||
createdFolderOut = true;
|
||||
}
|
||||
String noJavaDocString = null;
|
||||
byte[] noJavaDoc = jarEntriesNoJavadoc.get(newPath);
|
||||
if(noJavaDoc != null) {
|
||||
noJavaDocString = new String(noJavaDoc, StandardCharsets.UTF_8);
|
||||
}
|
||||
if(writeDiff(o, n, folderOut, newPath, isJava, noJavaDocString)) {
|
||||
changed = true;
|
||||
++cnt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!changed && !jarEntriesPatched.containsKey(newPath)) {
|
||||
FileUtils.writeByteArrayToFile(new File(folderOut, makeName(newPath, "recreate")), jarData);
|
||||
++cnt;
|
||||
}
|
||||
}else {
|
||||
filesReplaced.add(newPath);
|
||||
FileUtils.copyFile(wf, orig);
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
if(jarEntriesPatched.size() > 0) {
|
||||
for(Entry<String,byte[]> etr : jarEntriesPatched.entrySet()) {
|
||||
if(filesReplaced.contains(etr.getKey())) {
|
||||
continue;
|
||||
}
|
||||
if(!(new File(folderEdited, etr.getKey())).exists()) {
|
||||
if(!createdFolderOut) {
|
||||
if(!folderOut.mkdirs()) {
|
||||
throw new IOException("Could not create folder: \"" + folderOut.getAbsolutePath() + "\"!");
|
||||
}
|
||||
createdFolderOut = true;
|
||||
}
|
||||
FileUtils.writeStringToFile(new File(folderOut, makeName(etr.getKey(), "delete")),
|
||||
"#hash: " + getCRC32(etr.getValue()), "UTF-8");
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private static boolean writeDiff(byte[] old, byte[] _new, File outDir, String outName, boolean isJava, String javaNotJavadoc) throws IOException {
|
||||
String oldStr = toStringIfValid(old);
|
||||
String newStr = oldStr == null ? null : toStringIfValid(_new);
|
||||
if(oldStr == null || newStr == null) {
|
||||
FileUtils.writeByteArrayToFile(new File(outDir, makeName(outName, "replace")), _new);
|
||||
}else {
|
||||
if(javaNotJavadoc != null) {
|
||||
oldStr = javaNotJavadoc;
|
||||
}
|
||||
//oldStr = stripJavadocAndFormat(oldStr);
|
||||
newStr = stripJavadocAndFormat(newStr);
|
||||
List<String> oldLines = Lines.linesList(oldStr);
|
||||
List<String> newLines = Lines.linesList(newStr);
|
||||
Patch<String> deltas = DiffUtils.diff(oldLines, newLines);
|
||||
|
||||
List<String> diffFile = UnifiedDiffUtils.generateUnifiedDiff(outName, outName, oldLines, deltas, ApplyPatchesToZip.patchContextLength);
|
||||
|
||||
if(diffFile.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File fout = new File(outDir, makeName(outName, "edit"));
|
||||
File p = fout.getParentFile();
|
||||
if(!p.isDirectory()) {
|
||||
if(!p.mkdirs()) {
|
||||
throw new IOException("Failed to create directory \"" + p.getAbsolutePath() + "\"!");
|
||||
}
|
||||
}
|
||||
try(PrintWriter foutStream = new PrintWriter(new FileWriterUTF(fout))) {
|
||||
for(int i = 0, l = diffFile.size(); i < l; ++i) {
|
||||
foutStream.println(diffFile.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String stripJavadocAndFormat(String input) {
|
||||
input = InsertJavaDoc.stripDocForDiff(input);
|
||||
input = EclipseFormatter.processSource(input, System.lineSeparator());
|
||||
return input;
|
||||
}
|
||||
|
||||
private static int copyAllModified(File inDir, File outDir) throws IOException {
|
||||
if(!inDir.isDirectory()) {
|
||||
return 0;
|
||||
}
|
||||
int cnt = 0;
|
||||
Collection<File> workspaceFiles = FileUtils.listFiles(inDir, null, true);
|
||||
String editedPrefix = inDir.getAbsolutePath();
|
||||
for(File wf : workspaceFiles) {
|
||||
String newPath = wf.getAbsolutePath().replace(editedPrefix, "");
|
||||
if(newPath.indexOf('\\') != -1) {
|
||||
newPath = newPath.replace('\\', '/');
|
||||
}
|
||||
if(newPath.startsWith("/")) {
|
||||
newPath = newPath.substring(1);
|
||||
}
|
||||
File orig = new File(outDir, newPath);
|
||||
if(copyFileIfChanged(wf, orig)) {
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private static String makeName(String input, String type) {
|
||||
int lastSlash = input.lastIndexOf('/');
|
||||
int lastDot = input.lastIndexOf('.');
|
||||
if(lastDot > lastSlash + 1) {
|
||||
return input.substring(0, lastDot) + "." + type + input.substring(lastDot);
|
||||
}else {
|
||||
return input + "." + type;
|
||||
}
|
||||
}
|
||||
|
||||
private static final CharsetDecoder utf8Decoder = StandardCharsets.UTF_8.newDecoder();
|
||||
|
||||
private static String toStringIfValid(byte[] in) {
|
||||
ByteBuffer inn = ByteBuffer.wrap(in);
|
||||
CharBuffer cb;
|
||||
try {
|
||||
cb = utf8Decoder.decode(inn);
|
||||
}catch(Throwable t) {
|
||||
return null;
|
||||
}
|
||||
return cb.toString();
|
||||
}
|
||||
|
||||
private static final String hex = "0123456789ABCDEF";
|
||||
|
||||
private static String hex32(long in) {
|
||||
char[] ret = new char[8];
|
||||
for(int i = 7; i >= 0; --i) {
|
||||
ret[i] = hex.charAt((int)((in >> (i << 2)) & 0xF));
|
||||
}
|
||||
return new String(ret);
|
||||
}
|
||||
|
||||
private static String getCRC32(File in) throws IOException {
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(FileUtils.readFileToByteArray(in));
|
||||
return hex32(crc.getValue());
|
||||
}
|
||||
|
||||
private static String getCRC32(byte[] in) {
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(in);
|
||||
return hex32(crc.getValue());
|
||||
}
|
||||
|
||||
private static boolean checkCRC32(File in1, File in2) throws IOException {
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(FileUtils.readFileToByteArray(in1));
|
||||
long v1 = crc.getValue();
|
||||
crc.reset();
|
||||
crc.update(FileUtils.readFileToByteArray(in2));
|
||||
return v1 != crc.getValue();
|
||||
}
|
||||
|
||||
private static boolean copyFileIfChanged(File in1, File in2) throws IOException {
|
||||
if(!in2.exists()) {
|
||||
FileUtils.copyFile(in1, in2);
|
||||
return true;
|
||||
}
|
||||
if(in1.lastModified() == in2.lastModified()) {
|
||||
return false;
|
||||
}
|
||||
CRC32 crc = new CRC32();
|
||||
byte[] f1 = FileUtils.readFileToByteArray(in1);
|
||||
crc.update(f1);
|
||||
long v1 = crc.getValue();
|
||||
crc.reset();
|
||||
byte[] f2 = FileUtils.readFileToByteArray(in2);
|
||||
crc.update(f2);
|
||||
if(v1 != crc.getValue()) {
|
||||
//System.out.println("changed: " + in1.getAbsolutePath());
|
||||
FileUtils.writeByteArrayToFile(in2, f1);
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.formatter;
|
||||
|
||||
import org.eclipse.jdt.core.formatter.CodeFormatter;
|
||||
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
|
||||
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
|
||||
import org.eclipse.jface.text.Document;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.text.edits.TextEdit;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class EclipseFormatter {
|
||||
|
||||
private static final DefaultCodeFormatter formatter = new DefaultCodeFormatter(DefaultCodeFormatterOptions.getEclipseDefaultSettings());
|
||||
|
||||
public static String processSource(String input, String lineSeparator) {
|
||||
try {
|
||||
IDocument doc = new Document();
|
||||
doc.set(input);
|
||||
TextEdit edit = formatter.format(CodeFormatter.K_COMPILATION_UNIT |
|
||||
CodeFormatter.F_INCLUDE_COMMENTS, input, 0, input.length(), 0, lineSeparator);
|
||||
edit.apply(doc);
|
||||
return doc.get();
|
||||
}catch(Throwable t) {
|
||||
System.err.println("Code formatting failed!");
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CSVMappings {
|
||||
|
||||
public final Map<String, Symbol> csvFieldsMappings = new HashMap();
|
||||
public final Map<String, Symbol> csvMethodsMappings = new HashMap();
|
||||
public final Map<String, Param> csvParamsMappings = new HashMap();
|
||||
public final Map<String, Param[]> csvParamsForFunction = new HashMap();
|
||||
|
||||
public static class Symbol {
|
||||
|
||||
public final String name;
|
||||
public final int mod;
|
||||
public final String comment;
|
||||
|
||||
public Symbol(String name, int mod, String comment) {
|
||||
this.name = name;
|
||||
this.mod = mod;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Param {
|
||||
|
||||
public final String name;
|
||||
public final int mod;
|
||||
|
||||
public Param(String name, int mod) {
|
||||
this.name = name;
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void loadMethodsFile(Reader reader) throws IOException {
|
||||
loadSymbols(reader, csvMethodsMappings, "methods.csv");
|
||||
}
|
||||
|
||||
public void loadFieldsFile(Reader reader) throws IOException {
|
||||
loadSymbols(reader, csvFieldsMappings, "fields.csv");
|
||||
}
|
||||
|
||||
private void loadSymbols(Reader reader, Map<String, Symbol> map, String debugFileName) throws IOException {
|
||||
try {
|
||||
CSVParser ps = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader);
|
||||
Iterator<CSVRecord> rows = ps.iterator();
|
||||
while(rows.hasNext()) {
|
||||
CSVRecord rec = rows.next();
|
||||
String srgName = rec.get("searge");
|
||||
String deobfName = rec.get("name");
|
||||
int mod = Integer.parseInt(rec.get("side"));
|
||||
String comment = rec.get("desc");
|
||||
map.put(srgName, new Symbol(deobfName, mod, comment));
|
||||
}
|
||||
System.out.println(" Loaded " + map.size() + " symbols from " + debugFileName);
|
||||
}catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
throw new IOException("Invalid " + debugFileName + " file!");
|
||||
}
|
||||
}
|
||||
|
||||
public void loadParamsFile(Reader reader) throws IOException {
|
||||
try {
|
||||
CSVParser ps = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader);
|
||||
Iterator<CSVRecord> rows = ps.iterator();
|
||||
while(rows.hasNext()) {
|
||||
CSVRecord rec = rows.next();
|
||||
String srgName = rec.get("param");
|
||||
String deobfName = rec.get("name");
|
||||
int mod = Integer.parseInt(rec.get("side"));
|
||||
csvParamsMappings.put(srgName, new Param(deobfName, mod));
|
||||
String fName = srgName.substring(srgName.indexOf('_') + 1);
|
||||
if(!fName.startsWith("i")) {
|
||||
int i2 = fName.indexOf('_');
|
||||
if(i2 != -1) {
|
||||
int ordinal = -1;
|
||||
String ordStr = fName.substring(i2 + 1);
|
||||
if(ordStr.length() >= 2) {
|
||||
try {
|
||||
ordinal = Integer.parseInt(ordStr.substring(0, ordStr.length() - 1));
|
||||
}catch(NumberFormatException ex) {
|
||||
}
|
||||
}
|
||||
if(ordinal >= 0) {
|
||||
fName = "func_" + fName.substring(0, i2);
|
||||
Param[] prm = csvParamsForFunction.get(fName);
|
||||
if(prm == null || prm.length <= ordinal) {
|
||||
Param[] prm2 = new Param[ordinal + 1];
|
||||
if(prm != null) {
|
||||
System.arraycopy(prm, 0, prm2, 0, prm.length);
|
||||
}
|
||||
prm = prm2;
|
||||
}
|
||||
prm[ordinal] = new Param(deobfName, mod);
|
||||
csvParamsForFunction.put(fName, prm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(" Loaded " + csvParamsMappings.size() + " symbols from params.csv");
|
||||
}catch(Throwable t) {
|
||||
throw new IOException("Invalid params.csv file!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class CreateUnpatched {
|
||||
|
||||
public static boolean createUnpatched() {
|
||||
try {
|
||||
return createUnpatched0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'unpatched'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean createUnpatched0() throws Throwable {
|
||||
File tmpDirectory = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
File mcpDir = new File(tmpDirectory, "ModCoderPack");
|
||||
File minecraftSrc = new File(tmpDirectory, "MinecraftSrc/minecraft_src.jar");
|
||||
File minecraftRes = new File(tmpDirectory, "MinecraftSrc/minecraft_res.jar");
|
||||
File outputFile = new File("./MinecraftSrc.zip");
|
||||
|
||||
if(outputFile.exists()) {
|
||||
System.err.println("ERROR: The file 'MinecraftSrc.zip' already exists in this directory!");
|
||||
System.err.println("Delete it and re-run 'unpatched' to try again");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!mcpDir.isDirectory()) {
|
||||
System.err.println("The '" + mcpDir.getName() + "' directory was not found in the temporary directory!");
|
||||
System.err.println("Please run the 'init' command to create it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!minecraftSrc.isFile()) {
|
||||
System.err.println("The '" + minecraftSrc.getName() + "' file was not found in the temporary directory!");
|
||||
System.err.println("Please run the 'init' command to create it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!minecraftRes.isFile()) {
|
||||
System.err.println("The '" + minecraftRes.getName() + "' file was not found in the temporary directory!");
|
||||
System.err.println("Please run the 'init' command to create it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File tmpJavadocOut = new File(tmpDirectory, "MinecraftSrc/minecraft_unpatched_javadoc.jar");
|
||||
System.out.println();
|
||||
System.out.println("Preparing source in '" + minecraftSrc.getName() + "'...");
|
||||
System.out.println();
|
||||
CSVMappings mp = new CSVMappings();
|
||||
InsertJavaDoc.processSource(minecraftSrc, tmpJavadocOut, mcpDir, mp, false);
|
||||
|
||||
try(ZipOutputStream zot = new ZipOutputStream(new FileOutputStream(outputFile))) {
|
||||
zot.setLevel(0);
|
||||
int tl;
|
||||
System.out.println("Extracting '" + tmpJavadocOut.getName() + "' into '" + outputFile.getName() + "'...");
|
||||
try(FileInputStream fin = new FileInputStream(tmpJavadocOut)) {
|
||||
tl = extractZipTo(new ZipInputStream(fin), zot, "src");
|
||||
}
|
||||
System.out.println("Extracted " + tl + " files.");
|
||||
System.out.println();
|
||||
System.out.println("Extracting '" + minecraftRes.getName() + "' into '" + outputFile.getName() + "'...");
|
||||
try(FileInputStream fin = new FileInputStream(minecraftRes)) {
|
||||
tl = extractZipTo(new ZipInputStream(fin), zot, "res");
|
||||
}
|
||||
System.out.println("Extracted " + tl + " files.");
|
||||
}
|
||||
|
||||
if(!tmpJavadocOut.delete()) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: failed to delete '" + tmpJavadocOut.getName() + "' from temporary directory!");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static int extractZipTo(ZipInputStream zin, ZipOutputStream zout, String pfx) throws IOException {
|
||||
int cnt = 0;
|
||||
ZipEntry in;
|
||||
while((in = zin.getNextEntry()) != null) {
|
||||
if(in.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String n = in.getName();
|
||||
if(n.startsWith("/")) {
|
||||
n = n.substring(1);
|
||||
}
|
||||
if(n.startsWith("META-INF")) {
|
||||
continue;
|
||||
}
|
||||
ZipEntry out = new ZipEntry(pfx + "/" + n);
|
||||
zout.putNextEntry(out);
|
||||
IOUtils.copy(zin, zout, 8192);
|
||||
++cnt;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,241 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.ApplyPatchesToZip;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.formatter.EclipseFormatter;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.JARSubprocess;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class DecompileMinecraft {
|
||||
|
||||
public static boolean decompileMinecraft(File mcpDataTMP, File minecraftJar, File minecraftSrc, File assetsJson, boolean writeJavaDoc) throws Throwable {
|
||||
|
||||
File filterOut = new File(minecraftSrc, "minecraft_classes.jar");
|
||||
System.out.println();
|
||||
System.out.println("Extracting '" + minecraftJar.getAbsolutePath() + "\" to \"" + filterOut.getAbsolutePath() + "\"...");
|
||||
|
||||
int xt = 0;
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(minecraftJar));
|
||||
ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(filterOut))) {
|
||||
jarOut.setLevel(0);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
ZipEntry et;
|
||||
String nm;
|
||||
while((et = jarIn.getNextEntry()) != null) {
|
||||
if(!et.isDirectory() && (nm = et.getName()).endsWith(".class")) {
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.copy(jarIn, jarOut);
|
||||
++xt;
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to extract \"" + minecraftJar.getAbsolutePath() + "\" to \"" + filterOut.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
if(filterOut.exists()) {
|
||||
filterOut.delete();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
System.out.println("Extracted " + xt + " class files.");
|
||||
|
||||
File deobfOut = new File(minecraftSrc, "minecraft_specialsource.jar");
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Running SpecialSource...");
|
||||
int ex = JARSubprocess.runJava(mcpDataTMP, new String[] {
|
||||
"-cp", filterOut.getAbsolutePath() + JARSubprocess.classPathSeperator + "runtime.jar",
|
||||
"net.md_5.specialsource.SpecialSource", "-i", filterOut.getAbsolutePath(), "-o",
|
||||
deobfOut.getAbsolutePath(), "-m", "minecraft.srg", "--kill-source"
|
||||
}, " [SpecialSource]");
|
||||
|
||||
filterOut.delete();
|
||||
|
||||
if(ex == 0) {
|
||||
System.out.println("SpecialSource completed successfully.");
|
||||
}else {
|
||||
System.err.println("ERROR: MCP SpecialSource execution failed!");
|
||||
return false;
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
File deobfOut2 = new File(minecraftSrc, "minecraft_mcinjector.jar");
|
||||
|
||||
System.out.println("Running MCInjector...");
|
||||
ex = JARSubprocess.runJava(mcpDataTMP, new String[] {
|
||||
"-cp", filterOut.getAbsolutePath() + JARSubprocess.classPathSeperator + "runtime.jar",
|
||||
"de.oceanlabs.mcp.mcinjector.MCInjector", "--jarIn", deobfOut.getAbsolutePath(), "--jarOut",
|
||||
deobfOut2.getAbsolutePath(), "--mapIn", "minecraft.exc", "--jsonIn", "exceptor.json",
|
||||
"--lvt", "STRIP"
|
||||
}, " [MCInjector]");
|
||||
|
||||
deobfOut.delete();
|
||||
|
||||
if(ex == 0) {
|
||||
System.out.println("MCInjector completed successfully.");
|
||||
}else {
|
||||
System.err.println("ERROR: MCP MCInjector execution failed!");
|
||||
return false;
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
File ffOut = new File(minecraftSrc, "fernflower.tmp");
|
||||
|
||||
if(ffOut.isFile()) {
|
||||
ffOut.delete();
|
||||
}else if(ffOut.isDirectory()) {
|
||||
FileUtils.deleteDirectory(ffOut);
|
||||
}
|
||||
|
||||
if(!ffOut.mkdir()) {
|
||||
System.err.println("ERROR: Could not create Fernflower output directory!");
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println("Decompiling with Fernflower...");
|
||||
System.out.println("This will take a while, go get a drink or something lol.");
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Staying hydrated is important when u work on a fucked up project that");
|
||||
System.out.println("will make you angry enough put your fists through your bedroom wall");
|
||||
System.out.println();
|
||||
|
||||
ex = JARSubprocess.runJava(mcpDataTMP, new String[] {
|
||||
"-jar", "fernflower.jar", "-din=1", "-rbr=1", "-dgs=1", "-asc=1", "-rsy=1", "-iec=1",
|
||||
"-ren=0", "-jvn=1", "-udv=1", "-ump=1", "-log=WARN", deobfOut2.getAbsolutePath(),
|
||||
ffOut.getAbsolutePath()
|
||||
}, " [Fernflower]");
|
||||
|
||||
deobfOut2.delete();
|
||||
|
||||
if(ex == 0) {
|
||||
System.out.println("Decompiler completed successfully.");
|
||||
}else {
|
||||
System.err.println("ERROR: Fernflower decompiler failed!");
|
||||
return false;
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
File[] ff = ffOut.listFiles();
|
||||
File decomp = null;
|
||||
for(int i = 0; i < ff.length; ++i) {
|
||||
if(ff[i].getName().endsWith(".jar")) {
|
||||
if(ff[i].getName().equalsIgnoreCase("minecraft_mcinjector.jar")) {
|
||||
decomp = ff[i];
|
||||
}else {
|
||||
if(decomp == null) {
|
||||
decomp = ff[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(decomp == null) {
|
||||
System.err.println("Could not find Fernflower output jar! (in " + ffOut.getAbsolutePath() + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
File formatOut = new File(minecraftSrc, "minecraft_src.jar");
|
||||
|
||||
System.out.println("Formatting source for patches...");
|
||||
System.out.println(" (Using default Eclipse format)");
|
||||
System.out.print(" ");
|
||||
xt = 0;
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(decomp));
|
||||
ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(formatOut))) {
|
||||
jarOut.setLevel(5);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
ZipEntry et;
|
||||
String nm;
|
||||
while((et = jarIn.getNextEntry()) != null) {
|
||||
if((nm = et.getName()).endsWith(".java")) {
|
||||
String txt = IOUtils.toString(jarIn, "UTF-8");
|
||||
txt = EclipseFormatter.processSource(txt, "\n");
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.write(txt, jarOut, "UTF-8");
|
||||
++xt;
|
||||
if(xt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}else {
|
||||
if(!nm.startsWith("META-INF")) {
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.copy(jarIn, jarOut, 4096);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Formatted " + xt + " classes.");
|
||||
System.out.println();
|
||||
|
||||
try {
|
||||
FileUtils.deleteDirectory(ffOut);
|
||||
}catch(IOException exx) {
|
||||
}
|
||||
|
||||
File patchOut = new File(minecraftSrc, "minecraft_src_patch.jar");
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(formatOut, null, new File(EaglerBuildTools.repositoryRoot, "patches/minecraft"), patchOut, true, true);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: Could not apply 'patches' directory to: " + patchOut.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
File javadocOut = new File(minecraftSrc, "minecraft_src_javadoc.jar");
|
||||
CSVMappings comments = writeJavaDoc ? new CSVMappings() : null;
|
||||
if(!InsertJavaDoc.processSource(patchOut, javadocOut, mcpDataTMP, comments)) {
|
||||
System.err.println("ERROR: Could not create javadoc!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File resourcesOut = new File(minecraftSrc, "minecraft_res.jar");
|
||||
if(!LoadResources.loadResources(minecraftJar, assetsJson, resourcesOut, mcpDataTMP, new File(minecraftSrc, "minecraft_languages.zip"))) {
|
||||
System.err.println("ERROR: Could not copy resources!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File patchResourcesOut = new File(minecraftSrc, "minecraft_res_patch.jar");
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(resourcesOut, null, new File(EaglerBuildTools.repositoryRoot, "patches/resources"), patchResourcesOut, true, true);
|
||||
}catch(Throwable t) {
|
||||
System.err.println("ERROR: Could not apply 'patches' directory to: " + patchResourcesOut.getName());
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FFMPEG {
|
||||
|
||||
public static final boolean windows = System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
|
||||
public static String foundFFMPEG = null;
|
||||
|
||||
public static void confirmFFMPEG() {
|
||||
if(checkFFMPEGOnPath()) {
|
||||
foundFFMPEG = "ffmpeg";
|
||||
return;
|
||||
}
|
||||
if(windows) {
|
||||
File f = new File("mcp918/ffmpeg.exe");
|
||||
if(!f.isFile()) {
|
||||
System.out.println();
|
||||
System.out.println("ERROR: 'ffmpeg.exe' wasn't found in the 'mcp918' folder!");
|
||||
System.out.println();
|
||||
System.out.println("Please visit one of the following URLs to download it:");
|
||||
System.out.println(" - https://www.gyan.dev/ffmpeg/builds/");
|
||||
System.out.println(" - https://github.com/BtbN/FFmpeg-Builds/releases");
|
||||
System.out.println();
|
||||
System.out.println("Locate 'bin/ffmpeg.exe' in the .zip file you download and");
|
||||
System.out.println("place it in the 'mcp918' folder and press enter to continue");
|
||||
System.out.println();
|
||||
try {
|
||||
while(System.in.read() != '\n') {
|
||||
try {
|
||||
Thread.sleep(20l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
}
|
||||
confirmFFMPEG();
|
||||
}else {
|
||||
foundFFMPEG = f.getAbsolutePath();
|
||||
}
|
||||
}else {
|
||||
do {
|
||||
File f = new File("mcp918/ffmpeg");
|
||||
if(f.isFile() && f.canExecute()) {
|
||||
foundFFMPEG = f.getAbsolutePath();
|
||||
return;
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println("ERROR: ffmpeg is not installed on this system!");
|
||||
System.out.println();
|
||||
System.out.println("Please install it to continue, you can use the package");
|
||||
System.out.println("manager on most distros to do this automatically:");
|
||||
System.out.println(" - Debian: apt install ffmpeg");
|
||||
System.out.println(" - Ubuntu: apt install ffmpeg");
|
||||
System.out.println(" - Fedora: dnf install ffmpeg");
|
||||
System.out.println(" - Arch: pacman -S ffmpeg");
|
||||
System.out.println();
|
||||
System.out.println("Alternatively, place the 'ffmpeg' executable in the");
|
||||
System.out.println("'mcp918' folder of this repository");
|
||||
System.out.println();
|
||||
System.out.println("Make sure it has chmod +x");
|
||||
System.out.println();
|
||||
System.out.println("Press enter to continue once it has installed");
|
||||
System.out.println();
|
||||
try {
|
||||
while(System.in.read() != '\n') {
|
||||
try {
|
||||
Thread.sleep(20l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
}
|
||||
}while(!checkFFMPEGOnPath());
|
||||
foundFFMPEG = "ffmpeg";
|
||||
}
|
||||
}
|
||||
|
||||
public static int run(File rundir, String... args) {
|
||||
String[] e = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, e, 1, args.length);
|
||||
|
||||
if(foundFFMPEG == null) {
|
||||
confirmFFMPEG();
|
||||
}
|
||||
|
||||
e[0] = foundFFMPEG;
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(e);
|
||||
pb.directory(rundir);
|
||||
pb.redirectOutput(Redirect.INHERIT);
|
||||
pb.redirectError(Redirect.INHERIT);
|
||||
|
||||
try {
|
||||
Process p = pb.start();
|
||||
while(true) {
|
||||
try {
|
||||
return p.waitFor();
|
||||
} catch (InterruptedException ee) {
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Could not start ffmpeg process!");
|
||||
ex.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static byte[] encodeOgg(File temporaryDir, byte[] bytesInput, int samples, int bitrate, boolean stereo) throws IOException {
|
||||
File src = new File(temporaryDir, "temp.src.ogg");
|
||||
FileUtils.writeByteArrayToFile(src, bytesInput);
|
||||
|
||||
File dst = new File(temporaryDir, "temp.dst.ogg");
|
||||
|
||||
int i;
|
||||
if (stereo) {
|
||||
i = run(temporaryDir, "-y", "-v", "error", "-i", "temp.src.ogg", "-c:a", "libvorbis", "-ac", "2",
|
||||
"-apply_phase_inv", "1", "-b:a", "" + bitrate + "k", "-ar", "" + samples, "temp.dst.ogg");
|
||||
} else {
|
||||
i = run(temporaryDir, "-y", "-v", "error", "-i", "temp.src.ogg", "-c:a", "libvorbis", "-ac", "1",
|
||||
"-apply_phase_inv", "0", "-b:a", "" + bitrate + "k", "-ar", "" + samples, "temp.dst.ogg");
|
||||
}
|
||||
|
||||
src.delete();
|
||||
|
||||
if(i != 0) {
|
||||
throw new IOException("FFMPEG returned error code: " + i);
|
||||
}
|
||||
|
||||
byte[] read = FileUtils.readFileToByteArray(dst);
|
||||
|
||||
dst.delete();
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
public static boolean checkFFMPEGOnPath() {
|
||||
ProcessBuilder pb = new ProcessBuilder("ffmpeg", "-version");
|
||||
Process proc;
|
||||
try {
|
||||
proc = pb.start();
|
||||
}catch(IOException ex) {
|
||||
return false;
|
||||
}
|
||||
int exitCode;
|
||||
while(true) {
|
||||
try {
|
||||
exitCode = proc.waitFor();
|
||||
break;
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return exitCode == 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,231 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.decompiler.ParameterSplitter;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Param;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Symbol;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class GenerateEXCs {
|
||||
|
||||
public static boolean generateEXCs(File mcpDataTMP, File excOut, CSVMappings params) {
|
||||
System.out.println();
|
||||
System.out.println("Generating \"" + excOut.getName() + "\" from \"" + mcpDataTMP.getName() + "\"...");
|
||||
|
||||
File paramsCSV = new File(mcpDataTMP, "params.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(paramsCSV)) {
|
||||
params.loadParamsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + paramsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<Integer,String> paramsTmp = new HashMap();
|
||||
Set<String> definedFunctions = new HashSet();
|
||||
|
||||
int pcount = 0;
|
||||
int mcount = 0;
|
||||
int pgcount = 0;
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.exc")));
|
||||
PrintWriter os = new PrintWriter(new FileWriterUTF(excOut));) {
|
||||
String s;
|
||||
while((s = is.readLine()) != null) {
|
||||
int idx = s.lastIndexOf('|');
|
||||
if(idx != -1) {
|
||||
String pfx = s.substring(0, idx);
|
||||
String func = null;
|
||||
int p1 = pfx.indexOf('(');
|
||||
if(p1 != -1) {
|
||||
func = pfx.substring(0, p1);
|
||||
func = pfx.substring(func.lastIndexOf('.') + 1);
|
||||
}
|
||||
if(func != null) {
|
||||
definedFunctions.add(func);
|
||||
}
|
||||
if(idx != s.length() - 1) {
|
||||
paramsTmp.clear();
|
||||
String[] prms = s.substring(idx + 1).split(",");
|
||||
String[] nprms = new String[prms.length];
|
||||
int lpc = 0;
|
||||
for(int i = 0; i < prms.length; ++i) {
|
||||
Param p = params.csvParamsMappings.get(prms[i]);
|
||||
if(p != null) {
|
||||
nprms[i] = p.name;
|
||||
++pcount;
|
||||
++lpc;
|
||||
}
|
||||
}
|
||||
if(lpc != prms.length) {
|
||||
if(p1 != -1) {
|
||||
String sig = pfx.substring(p1);
|
||||
sig = sig.substring(0, sig.indexOf('='));
|
||||
pgcount += ParameterSplitter.getParameterArray(sig, nprms);
|
||||
}
|
||||
for(int i = 0; i < nprms.length; ++i) {
|
||||
if(nprms[i] == null) {
|
||||
nprms[i] = "param0" + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
s = pfx + "|" + String.join(",", nprms);
|
||||
}else if(func != null) {
|
||||
int idxx = func.indexOf('_');
|
||||
int idxx2 = func.lastIndexOf('_');
|
||||
if(idxx2 > idxx) {
|
||||
func = func.substring(0, idxx2 - 1);
|
||||
}
|
||||
Param[] pars = params.csvParamsForFunction.get(func);
|
||||
String sig = null;
|
||||
if(p1 != -1) {
|
||||
sig = pfx.substring(p1);
|
||||
sig = sig.substring(0, sig.indexOf('='));
|
||||
}
|
||||
if(pars == null) {
|
||||
if(sig != null) {
|
||||
String[] sg = ParameterSplitter.getParameterSigArray(sig, "par");
|
||||
if(sg != null) {
|
||||
s = pfx + "|" + String.join(",", sg);
|
||||
}
|
||||
pgcount += sg.length;
|
||||
}
|
||||
}else {
|
||||
int notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
++notNullLen;
|
||||
}
|
||||
}
|
||||
String[] sg = new String[notNullLen];
|
||||
notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
sg[notNullLen++] = pars[i].name;
|
||||
++pcount;
|
||||
}
|
||||
}
|
||||
s = pfx + "|" + String.join(",", sg);
|
||||
}
|
||||
}
|
||||
}
|
||||
int idx3 = s.indexOf('(');
|
||||
if(idx3 != -1) {
|
||||
int idx4 = s.lastIndexOf('.', idx3);
|
||||
if(idx4 != -1) {
|
||||
String func = s.substring(idx4 + 1, idx3);
|
||||
Symbol rp = params.csvMethodsMappings.get(func);
|
||||
if(rp != null) {
|
||||
String pfx = s.substring(0, idx4);
|
||||
String pofx = s.substring(idx3);
|
||||
s = pfx + "." + rp.name + pofx;
|
||||
++mcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
os.println(s);
|
||||
}
|
||||
os.println();
|
||||
os.println("# auto generated entries start here:");
|
||||
try(BufferedReader iss = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.srg")))) {
|
||||
while((s = iss.readLine()) != null) {
|
||||
if(s.startsWith("MD:")) {
|
||||
int idx = s.lastIndexOf(' ');
|
||||
if(idx > 0) {
|
||||
int idx2 = s.lastIndexOf(' ', idx - 1);
|
||||
String fname = s.substring(idx2 + 1, idx);
|
||||
String fnameShort = fname;
|
||||
String fsig = s.substring(idx + 1);
|
||||
fnameShort = fname.substring(fname.lastIndexOf('/') + 1);
|
||||
int idx3 = fnameShort.lastIndexOf('_');
|
||||
if(idx3 != -1 && fnameShort.lastIndexOf('_', idx3 - 1) > 0) {
|
||||
fnameShort = fnameShort.substring(0, idx3);
|
||||
}
|
||||
if(definedFunctions.add(fnameShort)) {
|
||||
String[] sg = ParameterSplitter.getParameterSigArray(fsig, "par");
|
||||
Param[] pars = params.csvParamsForFunction.get(fnameShort);
|
||||
if(pars != null) {
|
||||
int notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
++notNullLen;
|
||||
}
|
||||
}
|
||||
if(notNullLen > 0) {
|
||||
notNullLen = 0;
|
||||
for(int i = 0; i < pars.length; ++i) {
|
||||
if(pars[i] != null) {
|
||||
int ii = notNullLen++;
|
||||
if(ii < sg.length) {
|
||||
sg[ii] = pars[i].name;
|
||||
++pcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
int idx4 = fname.lastIndexOf('/');
|
||||
String ppfx = fname.substring(0, idx4);
|
||||
String ppfunc = fname.substring(idx4 + 1);
|
||||
Symbol rp = params.csvMethodsMappings.get(ppfunc);
|
||||
if(rp != null) {
|
||||
ppfunc = rp.name;
|
||||
++mcount;
|
||||
}
|
||||
fname = ppfx + "." + ppfunc;
|
||||
os.println(fname + fsig + "=|" + String.join(",", sg));
|
||||
}
|
||||
}else {
|
||||
if(sg != null) {
|
||||
if(sg.length > 0) {
|
||||
pgcount += sg.length;
|
||||
int idx4 = fname.lastIndexOf('/');
|
||||
String ppfx = fname.substring(0, idx4);
|
||||
String ppfunc = fname.substring(idx4 + 1);
|
||||
Symbol rp = params.csvMethodsMappings.get(ppfunc);
|
||||
if(rp != null) {
|
||||
ppfunc = rp.name;
|
||||
++mcount;
|
||||
}
|
||||
fname = ppfx + "." + ppfunc;
|
||||
os.println(fname + fsig + "=|" + String.join(",", sg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to write \"" + excOut.getName() + "\" from \"joined.exc\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println(" - Deobf " + pcount + " params to \"" + excOut.getName() + "\"");
|
||||
System.out.println(" - Generate " + pgcount + " params to \"" + excOut.getName() + "\"");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Symbol;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileWriterUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class GenerateSRGs {
|
||||
|
||||
public static boolean generate(File mcpDataTMP, File srgOut, CSVMappings csv) throws Throwable {
|
||||
System.out.println();
|
||||
System.out.println("Generating \"" + srgOut.getName() + "\" from \"" + mcpDataTMP.getName() + "\"...");
|
||||
|
||||
File methodsCSV = new File(mcpDataTMP, "methods.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(methodsCSV)) {
|
||||
csv.loadMethodsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + methodsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
File fieldsCSV = new File(mcpDataTMP, "fields.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(fieldsCSV)) {
|
||||
csv.loadFieldsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + fieldsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
int ccount = 0;
|
||||
int mcount = 0;
|
||||
int fcount = 0;
|
||||
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.srg")));
|
||||
PrintWriter os = new PrintWriter(new FileWriterUTF(srgOut));) {
|
||||
String s;
|
||||
while((s = is.readLine()) != null) {
|
||||
if(s.startsWith("MD:")) {
|
||||
int lastSpace = s.lastIndexOf(' ');
|
||||
String sig = s.substring(lastSpace + 1);
|
||||
s = s.substring(0, lastSpace);
|
||||
int lastSlash = s.lastIndexOf('/');
|
||||
String fd = s.substring(lastSlash + 1);
|
||||
s = s.substring(0, lastSlash);
|
||||
Symbol sm = csv.csvMethodsMappings.get(fd);
|
||||
if(sm != null) {
|
||||
++mcount;
|
||||
fd = sm.name;
|
||||
}
|
||||
os.println(s + "/" + fd + " " + sig);
|
||||
}else if(s.startsWith("FD:")) {
|
||||
int lastSlash = s.lastIndexOf('/');
|
||||
String fd = s.substring(lastSlash + 1);
|
||||
s = s.substring(0, lastSlash);
|
||||
Symbol sm = csv.csvFieldsMappings.get(fd);
|
||||
if(sm != null) {
|
||||
++fcount;
|
||||
fd = sm.name;
|
||||
}
|
||||
os.println(s + "/" + fd);
|
||||
}else if(s.startsWith("CL:")) {
|
||||
++ccount;
|
||||
os.println(s);
|
||||
}else {
|
||||
os.println(s);
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to write \"" + srgOut.getName() + "\" from \"joined.srg\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println(" - Deobf " + ccount + " classes to \"" + srgOut.getName() + "\"");
|
||||
System.out.println(" - Deobf " + mcount + " methods to \"" + srgOut.getName() + "\"");
|
||||
System.out.println(" - Deobf " + fcount + " fields to \"" + srgOut.getName() + "\"");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class InitMCP {
|
||||
|
||||
public static boolean initTask(File f, File mcpDataTMP) throws Throwable {
|
||||
File mcpUnifiedJar = new File(mcpDataTMP, "runtime.jar");
|
||||
String[] jarsToUnify = new String[] { "mcinjector.jar", "specialsource.jar" }; //, "retroguard.jar" };
|
||||
boolean[] jarsFound = new boolean[jarsToUnify.length];
|
||||
String[] configToCopy = new String[] { "exceptor.json", "fields.csv", "joined.exc",
|
||||
"joined.srg", "methods.csv", "params.csv", "fernflower.jar" };
|
||||
boolean[] configFound = new boolean[configToCopy.length];
|
||||
Set<String> copiedFiles = new HashSet();
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Extracting \"" + f.getAbsolutePath() + "\" to \"" + mcpDataTMP.getAbsolutePath() + "\"...");
|
||||
|
||||
try(ZipInputStream is = new ZipInputStream(new FileInputStream(f));
|
||||
ZipOutputStream os = new ZipOutputStream(new FileOutputStream(mcpUnifiedJar))) {
|
||||
|
||||
os.setLevel(0);
|
||||
os.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
os.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
ZipEntry e;
|
||||
entry_read: while((e = is.getNextEntry()) != null) {
|
||||
String zn = e.getName();
|
||||
if(zn.startsWith("/")) {
|
||||
zn = zn.substring(1);
|
||||
}
|
||||
for(int ii = 0; ii < jarsToUnify.length; ++ii) {
|
||||
if(zn.endsWith(jarsToUnify[ii])) {
|
||||
System.out.println(" " + jarsToUnify[ii] + " -> " + mcpUnifiedJar.getName());
|
||||
ZipInputStream iis = new ZipInputStream(is);
|
||||
ZipEntry e2;
|
||||
while((e2 = iis.getNextEntry()) != null) {
|
||||
if(e2.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String n = e2.getName();
|
||||
int i = n.indexOf("META-INF");
|
||||
if(i == 0 || i == 1) {
|
||||
continue;
|
||||
}
|
||||
if(copiedFiles.add(n)) {
|
||||
ZipEntry e3 = new ZipEntry(e2.getName());
|
||||
os.putNextEntry(e3);
|
||||
IOUtils.copy(iis, os, 4096);
|
||||
}
|
||||
}
|
||||
jarsFound[ii] = true;
|
||||
continue entry_read;
|
||||
}
|
||||
}
|
||||
|
||||
for(int ii = 0; ii < configToCopy.length; ++ii) {
|
||||
if(zn.endsWith(configToCopy[ii])) {
|
||||
System.out.println(" " + configToCopy[ii] + " -> " + configToCopy[ii]);
|
||||
try(OutputStream oss = new FileOutputStream(new File(mcpDataTMP, configToCopy[ii]))) {
|
||||
IOUtils.copy(is, oss, 32768);
|
||||
}
|
||||
configFound[ii] = true;
|
||||
continue entry_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to extract \"" + f.getAbsolutePath() + "\" to \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean err = false;
|
||||
for(int ii = 0; ii < jarsToUnify.length; ++ii) {
|
||||
if(!jarsFound[ii]) {
|
||||
err = true;
|
||||
System.err.println("JAR not found: \"" + jarsToUnify[ii] + "\"!");
|
||||
}
|
||||
}
|
||||
for(int ii = 0; ii < configToCopy.length; ++ii) {
|
||||
if(!configFound[ii]) {
|
||||
err = true;
|
||||
System.err.println("Config not found: \"" + configToCopy[ii] + "\"!");
|
||||
}
|
||||
}
|
||||
|
||||
if(err) {
|
||||
System.err.println("ERROR: Could not extract all required MCP files from \"" + f.getName() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
CSVMappings mappings = new CSVMappings();
|
||||
|
||||
File srgsOut = new File(mcpDataTMP, "minecraft.srg");
|
||||
if(!GenerateSRGs.generate(mcpDataTMP, srgsOut, mappings)) {
|
||||
System.err.println("ERROR: could not generate joined \"minecraft.srg\" file from conf in \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File excsOut = new File(mcpDataTMP, "minecraft.exc");
|
||||
if(!GenerateEXCs.generateEXCs(mcpDataTMP, excsOut, mappings)) {
|
||||
System.err.println("ERROR: could not generate joined \"minecraft.exc\" file from conf in \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class InitTask {
|
||||
|
||||
private static File locatedMCPZip = null;
|
||||
private static File locatedMinecraftJar = null;
|
||||
private static File locatedAssetsJson = null;
|
||||
|
||||
public static boolean initTask() {
|
||||
try {
|
||||
return initTask0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'init'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean initTask0() throws Throwable {
|
||||
System.out.println("Scanning 'mcp918' folder...");
|
||||
File mcp918dir = new File(EaglerBuildTools.repositoryRoot, "mcp918");
|
||||
|
||||
if(!mcp918dir.isDirectory()) {
|
||||
System.err.println("ERROR: \"" + mcp918dir.getAbsolutePath() + "\" is not a directory!");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(File f : mcp918dir.listFiles()) {
|
||||
if(f.getName().equalsIgnoreCase("mcp918.zip")) {
|
||||
locatedMCPZip = f;
|
||||
}
|
||||
if(locatedMCPZip == null && f.getName().endsWith(".zip")) {
|
||||
locatedMCPZip = f;
|
||||
}
|
||||
if(f.getName().equalsIgnoreCase("1.8.8.jar")) {
|
||||
locatedMinecraftJar = f;
|
||||
}
|
||||
if(locatedMinecraftJar == null && f.getName().endsWith(".jar")) {
|
||||
locatedMinecraftJar = f;
|
||||
}
|
||||
if(f.getName().equalsIgnoreCase("1.8.json")) {
|
||||
locatedAssetsJson = f;
|
||||
}
|
||||
if(locatedAssetsJson == null && f.getName().endsWith(".json")) {
|
||||
locatedAssetsJson = f;
|
||||
}
|
||||
}
|
||||
|
||||
if(locatedMCPZip == null) {
|
||||
System.err.println("ERROR: could not find ./mcp918/mcp918.zip! Please locate it and copy it into the 'mcp918' folder.");
|
||||
return false;
|
||||
}
|
||||
if(locatedMinecraftJar == null) {
|
||||
locatedMinecraftJar = MinecraftLocator.locateMinecraftVersionJar("1.8.8");
|
||||
if(locatedMinecraftJar == null) {
|
||||
System.err.println("ERROR: could not find ./mcp918/1.8.8.jar! Please locate it and copy it into the 'mcp918' folder.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(locatedAssetsJson == null) {
|
||||
locatedAssetsJson = MinecraftLocator.locateMinecraftVersionAssets("1.8");
|
||||
if(locatedAssetsJson == null) {
|
||||
System.err.println("ERROR: could not find ./mcp918/1.8.json! Please locate it and copy it into the 'mcp918' folder.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
FFMPEG.confirmFFMPEG();
|
||||
|
||||
File buildToolsTmp = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
boolean btExist = buildToolsTmp.exists();
|
||||
if(btExist && !(buildToolsTmp.isDirectory() && buildToolsTmp.list().length == 0)) {
|
||||
System.out.println();
|
||||
System.out.println("Notice: BuildTools is already initialized.");
|
||||
System.out.println();
|
||||
System.out.println("you must revert all changes in the 'patches' directory of");
|
||||
System.out.println("this repo back to the main repository's current commits,");
|
||||
System.out.println("otherwise the 'pullrequest' command wll not work properly");
|
||||
System.out.println();
|
||||
System.out.print("Do you want to re-initialize? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("Ok nice, the re-init will be cancelled. (thank god)");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
FileUtils.deleteDirectory(buildToolsTmp);
|
||||
btExist = false;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + buildToolsTmp.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File mcpDataTMP = new File(buildToolsTmp, "ModCoderPack");
|
||||
if(!mcpDataTMP.isDirectory() && !mcpDataTMP.mkdirs()) {
|
||||
System.err.println("ERROR: failed to create \"" + mcpDataTMP.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean skipMCP = false;
|
||||
|
||||
if(!skipMCP && !InitMCP.initTask(locatedMCPZip, mcpDataTMP)) {
|
||||
System.err.println("ERROR: could not initialize MCP from \"" + locatedMCPZip.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
File minecraftSrcTmp = new File(buildToolsTmp, "MinecraftSrc");
|
||||
if(!minecraftSrcTmp.isDirectory() && !minecraftSrcTmp.mkdirs()) {
|
||||
System.err.println("ERROR: failed to create \"" + minecraftSrcTmp.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!DecompileMinecraft.decompileMinecraft(mcpDataTMP, locatedMinecraftJar, minecraftSrcTmp, locatedAssetsJson, true)) {
|
||||
System.err.println("ERROR: could not decompile and patch 1.8.8.jar from \"" + locatedMinecraftJar.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,389 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.Lines;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.init.CSVMappings.Symbol;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.util.FileReaderUTF;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class InsertJavaDoc {
|
||||
|
||||
public static final String enumImport = "import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;";
|
||||
|
||||
private static final String[] typeModifiersFields = new String[] {
|
||||
"public", "private", "protected", "static",
|
||||
"final", "volatile", "transient"
|
||||
};
|
||||
|
||||
private static boolean isTypeModifierField(String tk) {
|
||||
for(int i = 0; i < typeModifiersFields.length; ++i) {
|
||||
if(typeModifiersFields[i].equals(tk)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final String[] typeModifiersMethods = new String[] {
|
||||
"public", "private", "protected", "static",
|
||||
"final", "synchronized", "abstract", "default"
|
||||
};
|
||||
|
||||
private static final Pattern illegalCharactersNotATypeName = Pattern.compile("[^a-zA-Z0-9_\\-\\$\\[\\]<>\\.]");
|
||||
|
||||
private static boolean isTypeModifierMethod(String tk) {
|
||||
for(int i = 0; i < typeModifiersMethods.length; ++i) {
|
||||
if(typeModifiersMethods[i].equals(tk)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean processSource(File fileIn, File fileOut, File mcpDataTMP, CSVMappings csv) throws Throwable {
|
||||
return processSource(fileIn, fileOut, mcpDataTMP, csv, true);
|
||||
}
|
||||
|
||||
public static boolean processSource(File fileIn, File fileOut, File mcpDataTMP, CSVMappings csv, boolean compress) throws Throwable {
|
||||
System.out.println("Adding javadoc...");
|
||||
|
||||
if(csv == null) {
|
||||
System.out.println("(writing enums only, skipping field/method annotations)");
|
||||
}
|
||||
|
||||
//RealOpenGLEnums.initEnums();
|
||||
//System.out.println("Loaded " + RealOpenGLEnums.enumNames.size() + " OpenGL enums");
|
||||
|
||||
List<String> copyrightComment = null;
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(EaglerBuildTools.repositoryRoot, "patches/minecraft/output_license.txt")))) {
|
||||
copyrightComment = new ArrayList();
|
||||
copyrightComment.add("/**+");
|
||||
String ln;
|
||||
while((ln = is.readLine()) != null) {
|
||||
copyrightComment.add(" * " + ln);
|
||||
}
|
||||
copyrightComment.add(" * ");
|
||||
copyrightComment.add(" */");
|
||||
}
|
||||
|
||||
Map<String, List<Symbol>> methodsInClasses = new HashMap();
|
||||
Map<String, List<Symbol>> fieldsInClasses = new HashMap();
|
||||
|
||||
if(csv != null) {
|
||||
File methodsCSV = new File(mcpDataTMP, "methods.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(methodsCSV)) {
|
||||
csv.loadMethodsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + methodsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
File fieldsCSV = new File(mcpDataTMP, "fields.csv");
|
||||
try(FileReaderUTF fr = new FileReaderUTF(fieldsCSV)) {
|
||||
csv.loadFieldsFile(fr);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to read \"" + fieldsCSV.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
try(BufferedReader is = new BufferedReader(new FileReaderUTF(new File(mcpDataTMP, "joined.srg")))) {
|
||||
String s;
|
||||
while((s = is.readLine()) != null) {
|
||||
if(s.startsWith("MD:")) {
|
||||
s = s.trim();
|
||||
int idxx = s.lastIndexOf(' ');
|
||||
int idxx2 = s.lastIndexOf(' ', idxx - 1);
|
||||
s = s.substring(idxx2 + 1, idxx);
|
||||
idxx = s.lastIndexOf('/');
|
||||
String s1 = s.substring(0, idxx);
|
||||
String s2 = s.substring(idxx + 1);
|
||||
Symbol sm = csv.csvMethodsMappings.get(s2);
|
||||
if(sm != null && sm.comment != null && sm.comment.length() > 0) {
|
||||
List<Symbol> sbls = methodsInClasses.get(s1);
|
||||
if(sbls == null) {
|
||||
methodsInClasses.put(s1, sbls = new ArrayList());
|
||||
}
|
||||
sbls.add(sm);
|
||||
}
|
||||
}else if(s.startsWith("FD:")) {
|
||||
s = s.trim();
|
||||
int idxx = s.lastIndexOf(' ');
|
||||
s = s.substring(idxx + 1);
|
||||
idxx = s.lastIndexOf('/');
|
||||
String s1 = s.substring(0, idxx);
|
||||
String s2 = s.substring(idxx + 1);
|
||||
Symbol sm = csv.csvFieldsMappings.get(s2);
|
||||
if(sm != null && sm.comment != null && sm.comment.length() > 0) {
|
||||
List<Symbol> sbls = fieldsInClasses.get(s1);
|
||||
if(sbls == null) {
|
||||
fieldsInClasses.put(s1, sbls = new ArrayList());
|
||||
}
|
||||
sbls.add(sm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLEnumManager.loadEnumMap();
|
||||
|
||||
System.out.print(" ");
|
||||
int xt = 0;
|
||||
int modm = 0;
|
||||
int modf = 0;
|
||||
final int[] enums = new int[1];
|
||||
|
||||
Consumer<Integer> enumCounter = new Consumer<Integer>() {
|
||||
@Override
|
||||
public void accept(Integer t) {
|
||||
enums[0] += t.intValue();
|
||||
}
|
||||
};
|
||||
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(fileIn));
|
||||
ZipOutputStream jarOut = new ZipOutputStream(new FileOutputStream(fileOut))) {
|
||||
jarOut.setLevel(compress ? 5 : 0);
|
||||
jarOut.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
jarOut.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
ZipEntry et;
|
||||
String nm;
|
||||
while((et = jarIn.getNextEntry()) != null) {
|
||||
if(et.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
nm = et.getName();
|
||||
if(nm.endsWith(".java")) {
|
||||
String fs = IOUtils.toString(jarIn, "UTF-8");
|
||||
List<String> linesLst = new ArrayList();
|
||||
linesLst.addAll(Lines.linesList(fs));
|
||||
if(copyrightComment != null) {
|
||||
for(int i = 0; i < linesLst.size(); ++i) {
|
||||
String ln = linesLst.get(i);
|
||||
if(!ln.startsWith("import")) {
|
||||
if(ln.startsWith("public")) {
|
||||
ln = ln.substring(6).trim();
|
||||
}
|
||||
if(ln.startsWith("class") || ln.startsWith("enum") || ln.startsWith("interface") || ln.startsWith("@interface")) {
|
||||
linesLst.addAll(i, copyrightComment);
|
||||
i += copyrightComment.size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String cnm = nm.substring(0, nm.length() - 5);
|
||||
List<Symbol> meths = csv == null ? null : methodsInClasses.get(cnm);
|
||||
List<Symbol> fields = csv == null ? null : fieldsInClasses.get(cnm);
|
||||
if(meths != null || fields != null) {
|
||||
for(int i = 0; i < linesLst.size(); ++i) {
|
||||
String ln2 = linesLst.get(i);
|
||||
boolean notMethod = ln2.endsWith(";");
|
||||
String ln = ln2;
|
||||
String indent = "";
|
||||
while(ln.length() > 0 && Character.isWhitespace(ln.charAt(0))) {
|
||||
indent += ln.charAt(0);
|
||||
ln = ln.substring(1);
|
||||
}
|
||||
String[] tokens = ln.split("\\s+");
|
||||
boolean hasTypeDecl = false;
|
||||
boolean hasMethodDecl = false;
|
||||
boolean hasType = false;
|
||||
for(int j = 0; j < tokens.length; ++j) {
|
||||
if(tokens[j].length() > 0) {
|
||||
boolean b1 = false;
|
||||
boolean b2 = false;
|
||||
if(isTypeModifierField(tokens[j])) {
|
||||
b1 = true;
|
||||
hasTypeDecl = true;
|
||||
}
|
||||
if(!notMethod && isTypeModifierMethod(tokens[j])) {
|
||||
b2 = true;
|
||||
hasMethodDecl = true;
|
||||
}
|
||||
if(b1 || b2) {
|
||||
continue;
|
||||
}else if(!hasType) {
|
||||
if(illegalCharactersNotATypeName.matcher(tokens[j]).find()) {
|
||||
break;
|
||||
}else {
|
||||
hasType = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int idx = 0;
|
||||
if(hasTypeDecl && j < tokens.length - 1 && tokens[j + 1].equals("=")) {
|
||||
if(fields != null) {
|
||||
for(int k = 0, l = fields.size(); k < l; ++k) {
|
||||
Symbol ss = fields.get(k);
|
||||
if(ss.name.equals(tokens[j])) {
|
||||
List<String> lines = wordWrapComment(ss.comment, indent);
|
||||
linesLst.addAll(i, lines);
|
||||
i += lines.size();
|
||||
++modf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(((idx = tokens[j].indexOf('(')) != -1 && j > 0) || hasMethodDecl) {
|
||||
if(meths != null) {
|
||||
if(idx > 0) {
|
||||
String sss = tokens[j].substring(0, idx);
|
||||
for(int k = 0, l = meths.size(); k < l; ++k) {
|
||||
Symbol ss = meths.get(k);
|
||||
if(ss.name.equals(sss)) {
|
||||
List<String> lines = wordWrapComment(ss.comment, indent);
|
||||
linesLst.addAll(i, lines);
|
||||
i += lines.size();
|
||||
++modm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int cnt0 = enums[0];
|
||||
for(int i = 0, l = linesLst.size(); i < l; ++i) {
|
||||
linesLst.set(i, OpenGLEnumManager.insertIntoLine(linesLst.get(i), enumCounter));
|
||||
}
|
||||
|
||||
if(cnt0 != enums[0]) {
|
||||
for(int i = 0, l = linesLst.size(); i < l; ++i) {
|
||||
String line = linesLst.get(i);
|
||||
if(line.startsWith("package")) {
|
||||
linesLst.addAll(i + 1, Arrays.asList("", enumImport));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.write(String.join(System.lineSeparator(), linesLst), jarOut, "UTF-8");
|
||||
++xt;
|
||||
if(xt % 75 == 74) {
|
||||
System.out.print(".");
|
||||
}
|
||||
}else {
|
||||
if(!nm.startsWith("META-INF")) {
|
||||
ZipEntry z2 = new ZipEntry(nm);
|
||||
jarOut.putNextEntry(z2);
|
||||
IOUtils.copy(jarIn, jarOut, 4096);
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Failed to process jar '" + fileIn.getName() + "' and write it to '" + fileOut.getName() + "!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Added " + enums[0] + " OpenGL enums");
|
||||
if(csv != null) {
|
||||
System.out.println("Added " + modm + " comments to methods");
|
||||
System.out.println("Added " + modf + " comments to fields");
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<String> wordWrapComment(String strIn, String indent) {
|
||||
String[] wds = strIn.split("\\s+");
|
||||
List<String> ret = new ArrayList();
|
||||
ret.add(indent + "/**+");
|
||||
String ln = "";
|
||||
for(int i = 0; i < wds.length; ++i) {
|
||||
if(ln.length() > 0 && wds[i].length() + ln.length() > 60) {
|
||||
ret.add(indent + " * " + ln);
|
||||
ln = "";
|
||||
}
|
||||
ln += ln.length() > 0 ? " " + wds[i] : wds[i];
|
||||
}
|
||||
if(ln.length() > 0) {
|
||||
ret.add(indent + " * " + ln);
|
||||
}
|
||||
ret.add(indent + " */");
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static String stripDocForDiff(String fileIn) {
|
||||
List<String> linesIn = Lines.linesList(fileIn);
|
||||
OpenGLEnumManager.loadEnumMap();
|
||||
List<String> linesOut = new ArrayList();
|
||||
boolean addOpenGLImport = false;
|
||||
for(int i = 0, l = linesIn.size(); i < l; ++i) {
|
||||
String line = linesIn.get(i);
|
||||
if(line.trim().startsWith("/**+")) {
|
||||
for(; i < l; ++i) {
|
||||
if(linesIn.get(i).endsWith("*/")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
String line2 = OpenGLEnumManager.stripFromLine(line);
|
||||
if(line2 != null) {
|
||||
linesOut.add(line2);
|
||||
addOpenGLImport = true;
|
||||
}else {
|
||||
linesOut.add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(addOpenGLImport) {
|
||||
int idx = linesOut.indexOf(enumImport);
|
||||
if(idx != -1) {
|
||||
if(idx - 1 >= 0 && linesOut.get(idx - 1).trim().length() == 0 && linesOut.size() > 1) {
|
||||
idx -= 1;
|
||||
linesOut.remove(idx);
|
||||
linesOut.remove(idx);
|
||||
}else {
|
||||
linesOut.remove(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return String.join(System.lineSeparator(), linesOut);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildTools;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class LoadResources {
|
||||
|
||||
public static boolean loadResources(File minecraftJarIn, File assetsIndexIn, File assetsJarOut, File tmpDir, File languagesZipOut) {
|
||||
System.out.println("Copying resources from '" + minecraftJarIn.getName() + "' into '" + assetsJarOut.getName() + "'");
|
||||
try(ZipOutputStream os = new ZipOutputStream(new FileOutputStream(assetsJarOut))) {
|
||||
os.setLevel(5);
|
||||
os.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
os.write("Manifest-Version: 1.0\nCreated-By: Eaglercraft BuildTools\n".getBytes(StandardCharsets.UTF_8));
|
||||
try(ZipInputStream is = new ZipInputStream(new FileInputStream(minecraftJarIn))) {
|
||||
ZipEntry e;
|
||||
while((e = is.getNextEntry()) != null) {
|
||||
if(e.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String zn = e.getName();
|
||||
if(zn.startsWith("/")) {
|
||||
zn = zn.substring(1);
|
||||
}
|
||||
if(zn.startsWith("META-INF") || zn.endsWith(".class")) {
|
||||
continue;
|
||||
}
|
||||
os.putNextEntry(e);
|
||||
IOUtils.copy(is, os, 4096);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Reading 'assetsIndexTransformer.json'...");
|
||||
|
||||
ResourceRulesList rules;
|
||||
|
||||
try {
|
||||
rules = ResourceRulesList.loadResourceRules(new File(EaglerBuildTools.repositoryRoot, "mcp918/assetsIndexTransformer.json"));
|
||||
}catch(IOException ex) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: failed to read 'mcp918/assetsIndexTransformer.json'!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Reading asset index '" + assetsIndexIn.getAbsolutePath() + "'...");
|
||||
|
||||
try(ZipOutputStream os2 = new ZipOutputStream(new FileOutputStream(languagesZipOut))) {
|
||||
os2.setLevel(5);
|
||||
|
||||
try {
|
||||
JSONObject json = (new JSONObject(FileUtils.readFileToString(assetsIndexIn, StandardCharsets.UTF_8))).getJSONObject("objects");
|
||||
Iterator<String> itr = json.keys();
|
||||
|
||||
System.out.println("Downloading assets from 'https://resources.download.minecraft.net/'...");
|
||||
|
||||
while(itr.hasNext()) {
|
||||
String name = itr.next();
|
||||
JSONObject obj = json.getJSONObject(name);
|
||||
|
||||
|
||||
ResourceRulesList.ResourceRule r = rules.get(name);
|
||||
if(r.action == ResourceRulesList.Action.EXCLUDE) {
|
||||
System.out.println("Skipping file '" + name + "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
String hash = obj.getString("hash");
|
||||
int len = obj.getInt("size");
|
||||
|
||||
System.out.println("Downloading '" + name + "' (" + formatByteLength(len) + ") ...");
|
||||
|
||||
URL url;
|
||||
try {
|
||||
url = new URL("https://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash);
|
||||
}catch(MalformedURLException ex) {
|
||||
System.err.println("Resource file '" + name + "' had an invalid URL!");
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] downloadedFile = new byte[len];
|
||||
|
||||
try(InputStream is = url.openStream()) {
|
||||
int dl = 0;
|
||||
int i = 0;
|
||||
while(dl != len && (i = is.read(downloadedFile, dl, len - dl)) > 0) {
|
||||
dl += i;
|
||||
}
|
||||
int a = is.available();
|
||||
if(dl != len || a > 0) {
|
||||
throw new IOException("File '" + url.toString() + "' was the wrong length! " + (a > 0 ? "" + a + " bytes remaining" : "" + (len - dl) + " bytes missing"));
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Resource file '" + url.toString() + "' could not be downloaded!");
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(r.action == ResourceRulesList.Action.ENCODE) {
|
||||
try {
|
||||
System.out.println(" - encoding ogg: " + (r.ffmpegSamples / 1000) + "kHz, " + r.ffmpegBitrate + "kbps, " + (r.ffmpegStereo ? "stereo" : "mono"));
|
||||
downloadedFile = FFMPEG.encodeOgg(tmpDir, downloadedFile, r.ffmpegSamples, r.ffmpegBitrate, r.ffmpegStereo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("Resource file '" + name + "' could not be encoded!");
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}else if(r.action == ResourceRulesList.Action.LANGUAGES_ZIP) {
|
||||
int j = name.lastIndexOf('/');
|
||||
if(j != -1) {
|
||||
name = name.substring(j + 1);
|
||||
}
|
||||
System.out.println(" - writing language '" + name + "' to '" + languagesZipOut.getName() + "'");
|
||||
os2.putNextEntry(new ZipEntry(name));
|
||||
os2.write(downloadedFile);
|
||||
continue;
|
||||
}
|
||||
|
||||
os.putNextEntry(new ZipEntry("assets/" + name));
|
||||
os.write(downloadedFile);
|
||||
}
|
||||
}catch(IOException | JSONException ex) {
|
||||
System.err.println("ERROR: failed to download additional assets from '" + assetsIndexIn.getName() + "'!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: failed to copy from '" + minecraftJarIn.getName() + "' -> '" +assetsJarOut.getName() + "'!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String formatByteLength(int len) {
|
||||
if(len < 4096) {
|
||||
return "" + len;
|
||||
}else if(len < 1024 * 4096) {
|
||||
return "" + (len / 1024) + "k";
|
||||
}else {
|
||||
return "" + (len / 1024 / 1024) + "M";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class MinecraftLocator {
|
||||
|
||||
private static boolean hasTriedToFind = false;
|
||||
private static File directory = null;
|
||||
|
||||
private static File locateOrCopyFile(String name, String copyPath) {
|
||||
File f = new File("./mcp918/" + name);
|
||||
if(f.isFile()) {
|
||||
return f;
|
||||
}
|
||||
if(!hasTriedToFind) {
|
||||
hasTriedToFind = true;
|
||||
String var0 = System.getProperty("os.name").toLowerCase();
|
||||
if(var0.contains("win")) {
|
||||
String ad = System.getenv("APPDATA");
|
||||
if(ad != null) {
|
||||
directory = new File(ad, ".minecraft");
|
||||
}else {
|
||||
directory = new File(System.getProperty("user.home"), ".minecraft");
|
||||
}
|
||||
}else if(var0.contains("mac")) {
|
||||
directory = new File(System.getProperty("user.home"), "Library/Application Support/minecraft");
|
||||
}else {
|
||||
directory = new File(System.getProperty("user.home"), ".minecraft");
|
||||
}
|
||||
if(!directory.isDirectory()) {
|
||||
directory = new File(System.getProperty("user.home"), "minecraft");
|
||||
if(!directory.isDirectory()) {
|
||||
directory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(directory == null) {
|
||||
return null;
|
||||
}else {
|
||||
File f2 = new File(directory, copyPath);
|
||||
if(f2.isFile()) {
|
||||
try {
|
||||
System.out.println("Copying '" + copyPath + "' from your .minecraft directory into './mcp918'...");
|
||||
FileUtils.copyFile(f2, f, true);
|
||||
return f;
|
||||
} catch (IOException e) {
|
||||
System.err.println("ERROR: failed to copy '" + copyPath + "' from your .minecraft directory into './mcp918'!");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static File locateMinecraftVersionJar(String name) {
|
||||
return locateOrCopyFile(name + ".jar", "versions/" + name + "/" + name + ".jar");
|
||||
}
|
||||
|
||||
public static File locateMinecraftVersionAssets(String name) {
|
||||
return locateOrCopyFile(name + ".json", "assets/indexes/" + name + ".json");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class OpenGLEnumManager {
|
||||
|
||||
private static boolean hasLoaded = false;
|
||||
public static final Set<String> classNames = new HashSet();
|
||||
public static final Map<String,String> enumsForGLStateManager = new HashMap();
|
||||
public static final Map<String,Map<Integer,String>> enumsForFunctionKV = new HashMap();
|
||||
public static final Map<String,Map<String,Integer>> enumsForFunctionVK = new HashMap();
|
||||
|
||||
public static boolean loadEnumMap() {
|
||||
if(hasLoaded) {
|
||||
return true;
|
||||
}
|
||||
hasLoaded = true;
|
||||
try {
|
||||
|
||||
String enumsPath = "/lang/enums.json";
|
||||
System.out.println("Loading OpenGL enums: " + enumsPath);
|
||||
|
||||
int fcnt = 0;
|
||||
int ecnt = 0;
|
||||
|
||||
String jsonData;
|
||||
try(InputStream is = OpenGLEnumManager.class.getResourceAsStream(enumsPath)) {
|
||||
if(is == null) {
|
||||
throw new FileNotFoundException("classpath:/" + enumsPath);
|
||||
}
|
||||
jsonData = IOUtils.toString(is, "UTF-8");
|
||||
}
|
||||
|
||||
JSONArray enumJSON = (new JSONObject(jsonData)).getJSONArray("enums");
|
||||
for(Object o : enumJSON.toList()) {
|
||||
List<Object> enumData = (List<Object>) o;
|
||||
|
||||
List<String> functionsToAdd = new ArrayList();
|
||||
Map<Integer,String> enumsToAddKV = new HashMap();
|
||||
Map<String,Integer> enumsToAddVK = new HashMap();
|
||||
|
||||
Map<String,Object> functionSet = (Map<String,Object>)enumData.get(0);
|
||||
|
||||
for(Entry<String,Object> etr : functionSet.entrySet()) {
|
||||
classNames.add(etr.getKey());
|
||||
List<Object> functionArr = (List<Object>)etr.getValue();
|
||||
for(Object func : functionArr) {
|
||||
functionsToAdd.add(etr.getKey() + "." + (String)func);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String,Object> enumSet = (Map<String,Object>)enumData.get(1);
|
||||
|
||||
for(Entry<String,Object> etr : enumSet.entrySet()) {
|
||||
Map<String,Object> enumEnums = (Map<String,Object>)etr.getValue();
|
||||
for(Entry<String,Object> etr2 : enumEnums.entrySet()) {
|
||||
Integer intg = Integer.parseInt(etr2.getKey());
|
||||
enumsToAddKV.put(intg, (String)etr2.getValue());
|
||||
enumsToAddVK.put((String)etr2.getValue(), intg);
|
||||
++ecnt;
|
||||
}
|
||||
}
|
||||
|
||||
for(String fn : functionsToAdd) {
|
||||
if(!enumsForFunctionKV.containsKey(fn)) {
|
||||
++fcnt;
|
||||
enumsForFunctionKV.put(fn, enumsToAddKV);
|
||||
enumsForFunctionVK.put(fn, enumsToAddVK);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String glStateEnumsPath = "/lang/statemgr.json";
|
||||
System.out.println("Loading OpenGL enums: " + glStateEnumsPath);
|
||||
|
||||
try(InputStream is = OpenGLEnumManager.class.getResourceAsStream(glStateEnumsPath)) {
|
||||
if(is == null) {
|
||||
throw new FileNotFoundException("classpath:/" + glStateEnumsPath);
|
||||
}
|
||||
jsonData = IOUtils.toString(is, "UTF-8");
|
||||
}
|
||||
|
||||
JSONObject enumStateJSON = (new JSONObject(jsonData)).getJSONObject("statemgr_mappings");
|
||||
for(Entry<String,Object> etr : enumStateJSON.toMap().entrySet()) {
|
||||
String f = etr.getKey();
|
||||
String m = (String)etr.getValue();
|
||||
enumsForGLStateManager.put(f, m);
|
||||
if(!enumsForFunctionKV.containsKey(f) && enumsForFunctionKV.containsKey(m)) {
|
||||
enumsForFunctionKV.put(f, enumsForFunctionKV.get(m));
|
||||
enumsForFunctionVK.put(f, enumsForFunctionVK.get(m));
|
||||
++fcnt;
|
||||
}
|
||||
}
|
||||
|
||||
for(String str : enumsForGLStateManager.keySet()) {
|
||||
int idx = str.indexOf('.');
|
||||
if(idx != -1) {
|
||||
classNames.add(str.substring(0, idx));
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Loaded " + ecnt + " enums for " + fcnt + " functions");
|
||||
|
||||
return true;
|
||||
}catch(Throwable ex) {
|
||||
System.err.println("ERROR: could not load opengl enum map!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String insertIntoLine(String input, Consumer<Integer> progressCallback) {
|
||||
int idx1 = input.indexOf('.');
|
||||
if(idx1 != -1) {
|
||||
String pfx = input.substring(0, idx1);
|
||||
String p2 = pfx.trim();
|
||||
if(classNames.contains(p2)) {
|
||||
String fn = input.substring(idx1 + 1);
|
||||
int idx2 = fn.indexOf('(');
|
||||
if(idx2 != -1) {
|
||||
String argz = fn.substring(idx2 + 1);
|
||||
fn = fn.substring(0, idx2);
|
||||
int idx3 = argz.lastIndexOf(')');
|
||||
String pofx = "";
|
||||
if(idx3 == -1) {
|
||||
idx3 = argz.length();
|
||||
}else {
|
||||
pofx = argz.substring(idx3);
|
||||
}
|
||||
Map<Integer,String> repValues = enumsForFunctionKV.get(p2 + "." + fn);
|
||||
if(repValues != null) {
|
||||
argz = argz.substring(0, idx3);
|
||||
String[] args = argz.split(", ");
|
||||
int cnt = 0;
|
||||
for(int i = 0; i < args.length; ++i) {
|
||||
Integer j;
|
||||
try {
|
||||
j = Integer.valueOf(args[i]);
|
||||
}catch(NumberFormatException ex) {
|
||||
continue;
|
||||
}
|
||||
String estr = repValues.get(j);
|
||||
if(estr != null) {
|
||||
args[i] = estr;
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
if(cnt > 0) {
|
||||
input = pfx + "." + fn + "(" + String.join(", ", args) + pofx;
|
||||
if(progressCallback != null) {
|
||||
progressCallback.accept(cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String stripFromLine(String input) {
|
||||
int idx1 = input.indexOf('.');
|
||||
if(idx1 != -1) {
|
||||
String pfx = input.substring(0, idx1);
|
||||
String p2 = pfx.trim();
|
||||
if(classNames.contains(p2)) {
|
||||
String fn = input.substring(idx1 + 1);
|
||||
int idx2 = fn.indexOf('(');
|
||||
if(idx2 != -1) {
|
||||
String argz = fn.substring(idx2 + 1);
|
||||
fn = fn.substring(0, idx2);
|
||||
int idx3 = argz.lastIndexOf(')');
|
||||
String pofx = "";
|
||||
if(idx3 == -1) {
|
||||
idx3 = argz.length();
|
||||
}else {
|
||||
pofx = argz.substring(idx3);
|
||||
}
|
||||
Map<String,Integer> repValues = enumsForFunctionVK.get(p2 + "." + fn);
|
||||
if(repValues != null) {
|
||||
argz = argz.substring(0, idx3);
|
||||
String[] args = argz.split(", ");
|
||||
int cnt = 0;
|
||||
for(int i = 0; i < args.length; ++i) {
|
||||
Integer estr = repValues.get(args[i]);
|
||||
if(estr != null) {
|
||||
args[i] = estr.toString();
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
if(cnt > 0) {
|
||||
return pfx + "." + fn + "(" + String.join(", ", args) + pofx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class ResourceRulesList {
|
||||
|
||||
public static ResourceRulesList loadResourceRules(File conf) throws IOException {
|
||||
List<ResourceRule> list = new ArrayList();
|
||||
|
||||
try {
|
||||
JSONArray rulesArray = new JSONObject(FileUtils.readFileToString(conf, StandardCharsets.UTF_8)).getJSONArray("rules");
|
||||
for(int i = 0, l = rulesArray.length(); i < l; ++i) {
|
||||
JSONObject obj = rulesArray.getJSONObject(i);
|
||||
|
||||
Iterator<String> itr = obj.keys();
|
||||
while(itr.hasNext()) {
|
||||
String name = itr.next();
|
||||
JSONObject a = obj.getJSONObject(name);
|
||||
boolean wildcard = name.endsWith("*");
|
||||
|
||||
if(wildcard) {
|
||||
name = name.substring(0, name.length() - 1);
|
||||
}
|
||||
|
||||
Action action = Action.valueOf(a.getString("action").toUpperCase());
|
||||
|
||||
int ffmpegSamples = 16000;
|
||||
int ffmpegBitrate = 48;
|
||||
boolean ffmpegStereo = false;
|
||||
|
||||
if(action == Action.ENCODE) {
|
||||
JSONObject ffmpegObj = a.optJSONObject("ffmpeg", null);
|
||||
if(ffmpegObj != null) {
|
||||
ffmpegSamples = ffmpegObj.optInt("samples", ffmpegSamples);
|
||||
ffmpegBitrate = ffmpegObj.optInt("bitrate", ffmpegBitrate);
|
||||
ffmpegStereo = ffmpegObj.optBoolean("stereo", ffmpegStereo);
|
||||
}
|
||||
}
|
||||
|
||||
list.add(new ResourceRule(name, wildcard, action, ffmpegSamples, ffmpegBitrate, ffmpegStereo));
|
||||
}
|
||||
}
|
||||
}catch(JSONException ex) {
|
||||
throw new IOException("Invalid JSON file: " + conf.getAbsolutePath(), ex);
|
||||
}
|
||||
|
||||
return new ResourceRulesList(list);
|
||||
}
|
||||
|
||||
private final List<ResourceRule> list;
|
||||
|
||||
private ResourceRulesList(List<ResourceRule> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public ResourceRule get(String str) {
|
||||
|
||||
for(int i = 0, l = list.size(); i < l; ++i) {
|
||||
ResourceRule r = list.get(i);
|
||||
if(r.wildcard) {
|
||||
if(str.startsWith(r.path)) {
|
||||
return r;
|
||||
}
|
||||
}else {
|
||||
if(str.equals(r.path)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defaultRule;
|
||||
}
|
||||
|
||||
private static final ResourceRule defaultRule = new ResourceRule("", true, Action.EXCLUDE, 16000, 48, false);
|
||||
|
||||
public static class ResourceRule {
|
||||
|
||||
private final String path;
|
||||
private final boolean wildcard;
|
||||
public final Action action;
|
||||
|
||||
public final int ffmpegSamples;
|
||||
public final int ffmpegBitrate;
|
||||
public final boolean ffmpegStereo;
|
||||
|
||||
protected ResourceRule(String path, boolean wildcard, Action action, int ffmpegSamples, int ffmpegBitrate,
|
||||
boolean ffmpegStereo) {
|
||||
this.path = path;
|
||||
this.wildcard = wildcard;
|
||||
this.action = action;
|
||||
this.ffmpegSamples = ffmpegSamples;
|
||||
this.ffmpegBitrate = ffmpegBitrate;
|
||||
this.ffmpegStereo = ffmpegStereo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static enum Action {
|
||||
INCLUDE, EXCLUDE, ENCODE, LANGUAGES_ZIP
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,396 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.task.diff.ApplyPatchesToZip;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class SetupWorkspace {
|
||||
|
||||
public static boolean setupWorkspace() {
|
||||
return setupWorkspace0(false);
|
||||
}
|
||||
|
||||
public static boolean pullRequestTest() {
|
||||
return setupWorkspace0(true);
|
||||
}
|
||||
|
||||
private static boolean setupWorkspace0(boolean applyPullRequest) {
|
||||
File tmp = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
File dst = EaglerBuildToolsConfig.getWorkspaceDirectory();
|
||||
try {
|
||||
return setupWorkspace1(tmp, dst, applyPullRequest);
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
if(applyPullRequest) {
|
||||
System.err.println("Exception encountered while running task 'pullrequest_test'!");
|
||||
}else {
|
||||
System.err.println("Exception encountered while running task 'workspace'!");
|
||||
}
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean setupWorkspace1(File btTmpDirectory, File workspaceDirectory, boolean applyPullRequest) throws Throwable {
|
||||
|
||||
boolean wsExist = workspaceDirectory.exists();
|
||||
if(wsExist && !(workspaceDirectory.isDirectory() && workspaceDirectory.list().length == 0)) {
|
||||
System.err.println();
|
||||
System.err.println("WARNING: A workspace already exists in \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
System.err.println();
|
||||
System.err.println("Any changes you've made to the code will be lost!");
|
||||
System.err.println();
|
||||
System.out.print("Do you want to reset the workspace? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("Ok nice, the workspace folder will not be reset. (thank god)");
|
||||
System.out.println();
|
||||
System.out.println("Edit 'buildtools_config.json' to set up a different workspace folder");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
FileUtils.deleteDirectory(workspaceDirectory);
|
||||
wsExist = false;
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File mcTmpDirectory = new File(btTmpDirectory, "MinecraftSrc");
|
||||
File minecraftResJar = new File(mcTmpDirectory, "minecraft_res_patch.jar");
|
||||
File minecraftJavadocTmp = new File(mcTmpDirectory, "minecraft_src_javadoc.jar");
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Setting up dev workspace in \"" + workspaceDirectory.getAbsolutePath() + "\"...");
|
||||
System.out.println();
|
||||
|
||||
if(!workspaceDirectory.isDirectory() && !workspaceDirectory.mkdirs()) {
|
||||
System.err.println("ERROR: could not create \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
throw new IOException("Could not create \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
}
|
||||
|
||||
if(!minecraftJavadocTmp.isFile()) {
|
||||
System.err.println("ERROR: could not find 'minecraft_src_javadoc.jar' in your current temporary directory!");
|
||||
System.err.println("Run the 'init' command again to generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!minecraftResJar.isFile()) {
|
||||
System.err.println("ERROR: could not find 'minecraft_res_patch.jar' in your current temporary directory!");
|
||||
System.err.println("Run the 'init' command again to generate it");
|
||||
return false;
|
||||
}
|
||||
|
||||
File repoSources = new File("./sources");
|
||||
File repoSourcesSetup = new File(repoSources, "setup/workspace_template");
|
||||
File repoSourcesGame = new File(repoSources, "main/java");
|
||||
File repoSourcesTeaVM = new File(repoSources, "teavm/java");
|
||||
File repoSourcesLWJGL = new File(repoSources, "lwjgl/java");
|
||||
File repoSourcesResources = new File(repoSources, "resources");
|
||||
File srcMainJava = new File(workspaceDirectory, "src/main/java");
|
||||
File srcLWJGLJava = new File(workspaceDirectory, "src/lwjgl/java");
|
||||
File srcTeaVMJava = new File(workspaceDirectory, "src/teavm/java");
|
||||
File resourcesExtractTo = new File(workspaceDirectory, "desktopRuntime/resources");
|
||||
File mcLanguagesZip = new File(mcTmpDirectory, "minecraft_languages.zip");
|
||||
File mcLanguagesExtractTo = new File(workspaceDirectory, "javascript/lang");
|
||||
|
||||
System.out.println("Copying files from \"/setup/workspace_template/\" to \"" + workspaceDirectory.getName() + "\"...");
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(repoSourcesSetup, workspaceDirectory);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/setup/workspace_template/\" to \"" + workspaceDirectory.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if(os.contains("linux") || os.contains("macos") || os.contains("osx")) {
|
||||
File gradleW = new File(workspaceDirectory, "gradlew");
|
||||
if(!gradleW.setExecutable(true)) {
|
||||
System.err.println("ERROR: could not set executable bit on 'gradlew'!");
|
||||
System.err.println("Enter the root directory of the repository and run 'chmod +x gradlew' if you need access to the gradlew command");
|
||||
}
|
||||
}
|
||||
|
||||
File existingGi = new File(workspaceDirectory, ".gitignore");
|
||||
if((existingGi.exists() && !existingGi.delete()) || !(new File(workspaceDirectory, ".gitignore.default").renameTo(existingGi))) {
|
||||
System.err.println("ERROR: Could not rename \".gitignore.default\" to \".gitignore\" in the workspace directory!");
|
||||
}
|
||||
|
||||
if(repoSourcesTeaVM.isDirectory()) {
|
||||
System.out.println("Copying files from \"/sources/teavm/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!srcTeaVMJava.isDirectory() && !srcTeaVMJava.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesTeaVM, srcTeaVMJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/teavm/java/\" to \"" + srcTeaVMJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Copying files from \"/sources/main/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(repoSourcesGame, srcMainJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/main/java/\" to \"" + srcMainJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(repoSourcesLWJGL.isDirectory()) {
|
||||
System.out.println("Copying files from \"/sources/lwjgl/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!srcLWJGLJava.isDirectory() && !srcLWJGLJava.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesLWJGL, srcLWJGLJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/lwjgl/java/\" to \"" + srcLWJGLJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Copying files from \"/sources/resources/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!resourcesExtractTo.isDirectory() && !resourcesExtractTo.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesResources, resourcesExtractTo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/resources/\" to \"" + resourcesExtractTo.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(applyPullRequest) {
|
||||
System.out.println();
|
||||
System.out.println("Applying \"pullrequest\" directory to \"minecraft_src_patch.jar\"...");
|
||||
|
||||
File unpatchOut = new File(mcTmpDirectory, "minecraft_src.jar");
|
||||
File patchOut = new File(mcTmpDirectory, "minecraft_src_patch.jar");
|
||||
File unpatchResOut = new File(mcTmpDirectory, "minecraft_res.jar");
|
||||
File patchResOut = new File(mcTmpDirectory, "minecraft_res_patch.jar");
|
||||
File tmpPatchedPatchOut = new File(mcTmpDirectory, "minecraft_src_pullrequest_patch.jar");
|
||||
File tmpPatchedPatchJavadocOut = new File(mcTmpDirectory, "minecraft_src_pullrequest_javadoc.jar");
|
||||
File tmpPatchedPatchResOut = new File(mcTmpDirectory, "minecraft_res_pullrequest_patch.jar");
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(patchOut, unpatchOut, new File("./pullrequest/source"), tmpPatchedPatchOut, false, false);
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not apply pullrequest directory patches to: " + patchOut.getName());
|
||||
System.err.println(t.toString());
|
||||
tmpPatchedPatchOut.delete();
|
||||
return false;
|
||||
}
|
||||
|
||||
CSVMappings comments = new CSVMappings();
|
||||
if(!InsertJavaDoc.processSource(tmpPatchedPatchOut, tmpPatchedPatchJavadocOut,
|
||||
new File(btTmpDirectory, "ModCoderPack"), comments)) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not create pullrequest javadoc!");
|
||||
return false;
|
||||
}
|
||||
|
||||
tmpPatchedPatchOut.delete();
|
||||
|
||||
try {
|
||||
ApplyPatchesToZip.applyPatches(patchResOut, unpatchResOut, new File("./pullrequest/resources"), tmpPatchedPatchResOut, false, false);
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("ERROR: Could not apply pullrequest directory patches to: " + patchResOut.getName());
|
||||
System.err.println(t.toString());
|
||||
tmpPatchedPatchOut.delete();
|
||||
tmpPatchedPatchResOut.delete();
|
||||
return false;
|
||||
}
|
||||
|
||||
minecraftJavadocTmp = tmpPatchedPatchJavadocOut;
|
||||
minecraftResJar = tmpPatchedPatchResOut;
|
||||
|
||||
}else {
|
||||
System.out.println("Extracting files from \"minecraft_src_javadoc.jar\" to \"/src/main/java/\"...");
|
||||
}
|
||||
|
||||
try {
|
||||
if(!srcMainJava.isDirectory() && !srcMainJava.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
extractJarTo(minecraftJavadocTmp, srcMainJava);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not extract \"" + minecraftJavadocTmp.getName() + ".jar\" to \"" +
|
||||
srcMainJava.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
System.out.println("Extracting files from \"minecraft_res_patch.jar\" to \"/desktopRuntime/resources/\"...");
|
||||
|
||||
try {
|
||||
extractJarTo(minecraftResJar, resourcesExtractTo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not extract \"" + minecraftResJar.getName() + "\" to \"" +
|
||||
resourcesExtractTo.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(applyPullRequest) {
|
||||
minecraftJavadocTmp.delete();
|
||||
minecraftResJar.delete();
|
||||
}
|
||||
|
||||
System.out.println("Extracting files from \"minecraft_languages.zip\" to \"/javascript/lang/\"...");
|
||||
|
||||
try {
|
||||
extractJarTo(mcLanguagesZip, mcLanguagesExtractTo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not extract \"" + mcLanguagesZip.getName() + "\" to \"" +
|
||||
mcLanguagesExtractTo.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
System.out.println("Creating eclipse project for desktop runtime...");
|
||||
if(!createDesktopRuntimeProject(new File(repoSources, "setup/eclipseProjectFiles"), workspaceDirectory)) {
|
||||
System.err.println("ERROR: could not create eclipse project for desktop runtime!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int extractJarTo(File in, File out) throws IOException {
|
||||
int cnt = 0;
|
||||
try(ZipInputStream jarIn = new ZipInputStream(new FileInputStream(in))) {
|
||||
ZipEntry e;
|
||||
while((e = jarIn.getNextEntry()) != null) {
|
||||
if(e.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String n = e.getName();
|
||||
if(n.startsWith("/")) {
|
||||
n = n.substring(1);
|
||||
}
|
||||
if(!n.startsWith("META-INF")) {
|
||||
File o = new File(out, n);
|
||||
if(!o.exists()) {
|
||||
File p = o.getParentFile();
|
||||
if(!p.isDirectory() && !p.mkdirs()) {
|
||||
throw new IOException("Could not create directory: " + p.getAbsolutePath());
|
||||
}
|
||||
try(FileOutputStream os = new FileOutputStream(o)) {
|
||||
IOUtils.copy(jarIn, os, 4096);
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private static boolean createDesktopRuntimeProject(File templateFolderIn, File workspaceDirectory) throws Throwable {
|
||||
File desktopRuntimeDirectory = new File(workspaceDirectory, "desktopRuntime");
|
||||
File desktopRuntimeProjectDir = new File(desktopRuntimeDirectory, "eclipseProject");
|
||||
if(!desktopRuntimeProjectDir.isDirectory() && !desktopRuntimeProjectDir.mkdirs()) {
|
||||
System.err.println("ERROR: failed to create directory: \"" + desktopRuntimeProjectDir.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
File binFolder = new File(desktopRuntimeProjectDir, "bin");
|
||||
if(!binFolder.isDirectory() && !binFolder.mkdir()) {
|
||||
System.err.println("ERROR: failed to create directory: \"" + binFolder.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
String dotClasspathFile = FileUtils.readFileToString(new File(templateFolderIn, ".classpath"), "UTF-8");
|
||||
String dotClasspathEntryFile = FileUtils.readFileToString(new File(templateFolderIn, "classpath_entry.txt"), "UTF-8");
|
||||
String dotProjectFile = FileUtils.readFileToString(new File(templateFolderIn, ".project"), "UTF-8");
|
||||
String debugRuntimeLaunchConfig = FileUtils.readFileToString(new File(templateFolderIn, "eaglercraftDebugRuntime.launch"), "UTF-8");
|
||||
String mainClassConfFile = FileUtils.readFileToString(new File(templateFolderIn, "main_class.txt"), "UTF-8");
|
||||
|
||||
List<String> classpathEntries = new ArrayList();
|
||||
File[] flist = desktopRuntimeDirectory.listFiles();
|
||||
for(int i = 0; i < flist.length; ++i) {
|
||||
File f = flist[i];
|
||||
if(f.getName().endsWith(".jar")) {
|
||||
classpathEntries.add(dotClasspathEntryFile.replace("${JAR_PATH}", bsToS(f.getAbsolutePath())));
|
||||
}
|
||||
}
|
||||
|
||||
dotClasspathFile = dotClasspathFile.replace("${LIBRARY_CLASSPATH}", String.join(System.lineSeparator(), classpathEntries));
|
||||
FileUtils.writeStringToFile(new File(desktopRuntimeProjectDir, ".classpath"), dotClasspathFile, "UTF-8");
|
||||
|
||||
dotProjectFile = dotProjectFile.replace("${LWJGL_SRC_FOLDER}", bsToS((new File(workspaceDirectory, "src/lwjgl/java")).getAbsolutePath()));
|
||||
dotProjectFile = dotProjectFile.replace("${MAIN_SRC_FOLDER}", bsToS((new File(workspaceDirectory, "src/main/java")).getAbsolutePath()));
|
||||
FileUtils.writeStringToFile(new File(desktopRuntimeProjectDir, ".project"), dotProjectFile, "UTF-8");
|
||||
|
||||
debugRuntimeLaunchConfig = debugRuntimeLaunchConfig.replace("${MAIN_CLASS_FILE}", mainClassConfFile);
|
||||
|
||||
String mainClassSubstr = mainClassConfFile.substring(mainClassConfFile.indexOf('/') + 1);
|
||||
if(mainClassSubstr.endsWith(".java")) {
|
||||
mainClassSubstr = mainClassSubstr.substring(0, mainClassSubstr.length() - 5);
|
||||
}
|
||||
mainClassSubstr = mainClassSubstr.replace('/', '.');
|
||||
debugRuntimeLaunchConfig = debugRuntimeLaunchConfig.replace("${MAIN_CLASS_NAME}", mainClassSubstr);
|
||||
debugRuntimeLaunchConfig = debugRuntimeLaunchConfig.replace("${WORKING_DIRECTORY}", bsToS(desktopRuntimeDirectory.getAbsolutePath()));
|
||||
FileUtils.writeStringToFile(new File(desktopRuntimeProjectDir, "eaglercraftDebugRuntime.launch"), debugRuntimeLaunchConfig, "UTF-8");
|
||||
|
||||
File dotSettingsPrefFile = new File(templateFolderIn, "org.eclipse.jdt.core.prefs");
|
||||
File destDotSettingsFolder = new File(desktopRuntimeProjectDir, ".settings");
|
||||
if(!destDotSettingsFolder.isDirectory() && !destDotSettingsFolder.mkdir()) {
|
||||
System.err.println("ERROR: failed to create directory: \"" + destDotSettingsFolder.getAbsolutePath() + "\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
FileUtils.copyFile(dotSettingsPrefFile, new File(destDotSettingsFolder, "org.eclipse.jdt.core.prefs"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String bsToS(String in) {
|
||||
return in.replace('\\', '/');
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.init;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.EaglerBuildToolsConfig;
|
||||
|
||||
public class TaskClean {
|
||||
|
||||
public static boolean taskClean() {
|
||||
try {
|
||||
return taskClean0();
|
||||
}catch(Throwable t) {
|
||||
System.err.println();
|
||||
System.err.println("Exception encountered while running task 'clean'!");
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean taskClean0() throws Throwable {
|
||||
File buildToolsTmp = EaglerBuildToolsConfig.getTemporaryDirectory();
|
||||
File pullRequestTo = new File("pullrequest");
|
||||
boolean btExist = buildToolsTmp.exists();
|
||||
boolean prExist = pullRequestTo.exists();
|
||||
if((btExist && !(buildToolsTmp.isDirectory() && buildToolsTmp.list().length == 0)) ||
|
||||
(prExist && !(pullRequestTo.isDirectory() && pullRequestTo.list().length == 0))) {
|
||||
System.out.println();
|
||||
System.out.println("Notice: Clean will delete the init directory and also");
|
||||
System.out.println("all of the files in the current pull request");
|
||||
System.out.println();
|
||||
System.out.println("you must revert all changes in the 'patches' directory of");
|
||||
System.out.println("this repo back to the main repository's current commits,");
|
||||
System.out.println("otherwise the 'pullrequest' command wll not work properly");
|
||||
System.out.println();
|
||||
System.out.print("Do you want to clean? [Y/n]: ");
|
||||
|
||||
String ret = "n";
|
||||
try {
|
||||
ret = (new BufferedReader(new InputStreamReader(System.in))).readLine();
|
||||
}catch(IOException ex) {
|
||||
// ?
|
||||
}
|
||||
ret = ret.toLowerCase();
|
||||
if(!ret.startsWith("y")) {
|
||||
System.out.println();
|
||||
System.out.println("Ok nice, the clean will be cancelled. (thank god)");
|
||||
return true;
|
||||
}else {
|
||||
try {
|
||||
if(prExist) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting pull request...");
|
||||
FileUtils.deleteDirectory(pullRequestTo);
|
||||
prExist = false;
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + pullRequestTo.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if(btExist) {
|
||||
System.out.println();
|
||||
System.out.println("Deleting init directory...");
|
||||
FileUtils.deleteDirectory(buildToolsTmp);
|
||||
btExist = false;
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: Could not delete \"" + buildToolsTmp.getAbsolutePath() + "\"!");
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.buildtools.gui.TeaVMBinaries;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class TeaVMBridge {
|
||||
|
||||
private static URLClassLoader classLoader = null;
|
||||
|
||||
/**
|
||||
* <h3>List of required options:</h3>
|
||||
* <table>
|
||||
* <tr><td><b>classPathEntries</b></td><td>-> BuildStrategy.setClassPathEntries(List<String>)</td></tr>
|
||||
* <tr><td><b>entryPointName</b></td><td>-> BuildStrategy.setEntryPointName(String)</td></tr>
|
||||
* <tr><td><b>mainClass</b></td><td>-> BuildStrategy.setMainClass(String)</td></tr>
|
||||
* <tr><td><b>minifying</b></td><td>-> BuildStrategy.setMinifying(boolean)</td></tr>
|
||||
* <tr><td><b>optimizationLevel</b></td><td>-> BuildStrategy.setOptimizationLevel(TeaVMOptimizationLevel)</td></tr>
|
||||
* <tr><td><b>generateSourceMaps</b></td><td>-> BuildStrategy.setSourceMapsFileGenerated(boolean)</td></tr>
|
||||
* <tr><td><b>targetDirectory</b></td><td>-> BuildStrategy.setTargetDirectory(String)</td></tr>
|
||||
* <tr><td><b>targetFileName</b></td><td>-> BuildStrategy.setTargetFileName(String)</td></tr>
|
||||
* </table>
|
||||
* <br>
|
||||
*/
|
||||
public static boolean compileTeaVM(Map<String, Object> options) throws TeaVMClassLoadException, TeaVMRuntimeException {
|
||||
File[] cp = TeaVMBinaries.getTeaVMCompilerClasspath();
|
||||
URL[] urls = new URL[cp.length];
|
||||
|
||||
for(int i = 0; i < cp.length; ++i) {
|
||||
try {
|
||||
urls[i] = cp[i].toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new TeaVMClassLoadException("Could not resolve URL for: " + cp[i].getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
Method found = null;
|
||||
|
||||
try {
|
||||
if(classLoader == null) {
|
||||
classLoader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
Class c = classLoader.loadClass("net.lax1dude.eaglercraft.v1_8.buildtools.task.teavm.TeaVMBridgeImpl");
|
||||
Method[] methods = c.getDeclaredMethods();
|
||||
for(int i = 0; i < methods.length; ++i) {
|
||||
Method m = methods[i];
|
||||
if(m.getName().equals("compileTeaVM")) {
|
||||
found = m;
|
||||
}
|
||||
}
|
||||
if(found == null) {
|
||||
throw new NoSuchMethodException("compileTeaVM");
|
||||
}
|
||||
}catch(TeaVMClassLoadException | NoSuchMethodException | ClassNotFoundException t) {
|
||||
throw new TeaVMClassLoadException("Could not link TeaVM compiler!", t);
|
||||
}catch(RuntimeException t) {
|
||||
String msg = t.getMessage();
|
||||
if(msg.startsWith("[TeaVMBridge]")) {
|
||||
throw new TeaVMRuntimeException(msg.substring(13).trim(), t.getCause());
|
||||
}else {
|
||||
throw new TeaVMRuntimeException("Uncaught exception was thrown!", t);
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
throw new TeaVMRuntimeException("Uncaught exception was thrown!", t);
|
||||
}
|
||||
|
||||
try {
|
||||
Object ret = found.invoke(null, options);
|
||||
return ret != null && (ret instanceof Boolean) && ((Boolean)ret).booleanValue();
|
||||
}catch(InvocationTargetException ex) {
|
||||
throw new TeaVMRuntimeException("Uncaught exception was thrown!", ex.getCause());
|
||||
} catch (Throwable t) {
|
||||
throw new TeaVMRuntimeException("Failed to invoke 'compileTeaVM'!", t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TeaVMClassLoadException extends RuntimeException {
|
||||
public TeaVMClassLoadException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
public TeaVMClassLoadException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TeaVMRuntimeException extends RuntimeException {
|
||||
public TeaVMRuntimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
public TeaVMRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void free() {
|
||||
if(classLoader != null) {
|
||||
try {
|
||||
classLoader.close();
|
||||
classLoader = null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Memory leak, failed to release TeaVM JAR ClassLoader!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FileReaderUTF extends InputStreamReader {
|
||||
|
||||
public FileReaderUTF(File file) throws FileNotFoundException {
|
||||
super(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class FileWriterUTF extends OutputStreamWriter {
|
||||
|
||||
public FileWriterUTF(File file) throws IOException {
|
||||
super(new FileOutputStream(file), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.buildtools.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
|
||||
*
|
||||
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
|
||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
||||
*
|
||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
||||
*
|
||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
||||
*
|
||||
*/
|
||||
public class JARSubprocess {
|
||||
|
||||
public static final char classPathSeperator;
|
||||
|
||||
static {
|
||||
classPathSeperator = System.getProperty("os.name").toLowerCase().contains("windows") ? ';' : ':';
|
||||
}
|
||||
|
||||
public static int runJava(File directory, String[] javaExeArguments, String logPrefix) throws IOException {
|
||||
if(logPrefix.length() > 0 && !logPrefix.endsWith(" ")) {
|
||||
logPrefix = logPrefix + " ";
|
||||
}
|
||||
String javaHome = System.getProperty("java.home");
|
||||
if(classPathSeperator == ';') {
|
||||
File javaExe = new File(javaHome, "bin/java.exe");
|
||||
if(!javaExe.isFile()) {
|
||||
javaExe = new File(javaHome, "java.exe");
|
||||
if(!javaExe.isFile()) {
|
||||
throw new IOException("Could not find /bin/java.exe equivelant on java.home! (java.home=" + javaHome + ")");
|
||||
}
|
||||
}
|
||||
javaHome = javaExe.getAbsolutePath();
|
||||
}else {
|
||||
File javaExe = new File(javaHome, "bin/java");
|
||||
if(!javaExe.isFile()) {
|
||||
javaExe = new File(javaHome, "java");
|
||||
if(!javaExe.isFile()) {
|
||||
throw new IOException("Could not find /bin/java equivelant on java.home! (java.home=" + javaHome + ")");
|
||||
}
|
||||
}
|
||||
javaHome = javaExe.getAbsolutePath();
|
||||
}
|
||||
|
||||
String[] fullArgs = new String[javaExeArguments.length + 1];
|
||||
fullArgs[0] = javaHome;
|
||||
System.arraycopy(javaExeArguments, 0, fullArgs, 1, javaExeArguments.length);
|
||||
|
||||
ProcessBuilder exec = new ProcessBuilder(fullArgs);
|
||||
exec.directory(directory);
|
||||
|
||||
Process ps = exec.start();
|
||||
InputStream is = ps.getInputStream();
|
||||
InputStream ise = ps.getErrorStream();
|
||||
BufferedReader isb = new BufferedReader(new InputStreamReader(is));
|
||||
BufferedReader iseb = new BufferedReader(new InputStreamReader(ise));
|
||||
|
||||
String isbl = "";
|
||||
String isebl = "";
|
||||
int maxReadPerLoop = 128;
|
||||
int c = 0;
|
||||
do {
|
||||
boolean tick = false;
|
||||
c = 0;
|
||||
while(isb.ready() && (!iseb.ready() || ++c < maxReadPerLoop)) {
|
||||
char cc = (char)isb.read();
|
||||
if(cc != '\r') {
|
||||
if(cc == '\n') {
|
||||
System.out.println(logPrefix + isbl);
|
||||
isbl = "";
|
||||
}else {
|
||||
isbl += cc;
|
||||
}
|
||||
}
|
||||
tick = true;
|
||||
}
|
||||
c = 0;
|
||||
while(iseb.ready() && (!isb.ready() || ++c < maxReadPerLoop)) {
|
||||
char cc = (char)iseb.read();
|
||||
if(cc != '\r') {
|
||||
if(cc == '\n') {
|
||||
System.err.println(logPrefix + isebl);
|
||||
isebl = "";
|
||||
}else {
|
||||
isebl += cc;
|
||||
}
|
||||
}
|
||||
tick = true;
|
||||
}
|
||||
if(!tick) {
|
||||
try {
|
||||
Thread.sleep(10l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
} while(ps.isAlive());
|
||||
|
||||
while(true) {
|
||||
try {
|
||||
return ps.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user