diff --git a/.gitignore b/.gitignore
index 74dc7ea2..de408ec0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
run/
autotest/
+dist/
# Gradle
build/
diff --git a/.travis.yml b/.travis.yml
index c54706cf..a8344ba0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,7 @@ install:
- travis_retry docker build -t cabaletta/baritone .
script:
-- docker run --name baritone cabaletta/baritone /bin/sh -c "set -e; /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; sh scripts/build.sh; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient"
+- docker run --name baritone cabaletta/baritone /bin/sh -c "set -e; /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient"
- docker cp baritone:/code/dist dist
- ls dist
- cat dist/checksums.txt
diff --git a/build.gradle b/build.gradle
index 2d3137ff..34020ece 100755
--- a/build.gradle
+++ b/build.gradle
@@ -37,6 +37,10 @@ buildscript {
}
}
+
+import baritone.gradle.task.CreateDistTask
+import baritone.gradle.task.ProguardTask
+
apply plugin: 'java'
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
apply plugin: 'org.spongepowered.mixin'
@@ -99,3 +103,13 @@ jar {
preserveFileTimestamps = false
reproducibleFileOrder = true
}
+
+task proguard(type: ProguardTask) {
+ url 'https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip'
+ extract 'proguard6.0.3/lib/proguard.jar'
+ versionManifest 'https://launchermeta.mojang.com/mc/game/version_manifest.json'
+}
+
+task createDist(type: CreateDistTask, dependsOn: proguard)
+
+build.finalizedBy(createDist)
diff --git a/buildSrc/.gitignore b/buildSrc/.gitignore
new file mode 100644
index 00000000..daf21d56
--- /dev/null
+++ b/buildSrc/.gitignore
@@ -0,0 +1,3 @@
+build/
+.gradle/
+out/
\ No newline at end of file
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
new file mode 100644
index 00000000..2ac49af0
--- /dev/null
+++ b/buildSrc/build.gradle
@@ -0,0 +1,25 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
+ compile group: 'commons-io', name: 'commons-io', version: '2.6'
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/baritone/gradle/task/BaritoneGradleTask.java b/buildSrc/src/main/java/baritone/gradle/task/BaritoneGradleTask.java
new file mode 100644
index 00000000..22dac86e
--- /dev/null
+++ b/buildSrc/src/main/java/baritone/gradle/task/BaritoneGradleTask.java
@@ -0,0 +1,102 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.gradle.task;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import org.gradle.api.DefaultTask;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+/**
+ * @author Brady
+ * @since 10/12/2018
+ */
+class BaritoneGradleTask extends DefaultTask {
+
+ static final JsonParser PARSER = new JsonParser();
+
+ static final String
+ PROGUARD_ZIP = "proguard.zip",
+ PROGUARD_JAR = "proguard.jar",
+ PROGUARD_CONFIG_TEMPLATE = "scripts/proguard.pro",
+ PROGUARD_CONFIG_DEST = "template.pro",
+ PROGUARD_API_CONFIG = "api.pro",
+ PROGUARD_STANDALONE_CONFIG = "standalone.pro",
+ PROGUARD_EXPORT_PATH = "proguard_out.jar",
+
+ VERSION_MANIFEST = "version_manifest.json",
+
+ TEMP_LIBRARY_DIR = "tempLibraries/",
+
+ ARTIFACT_STANDARD = "%s-%s.jar",
+ ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
+ ARTIFACT_API = "%s-api-%s.jar",
+ ARTIFACT_STANDALONE = "%s-standalone-%s.jar";
+
+ String artifactName, artifactVersion;
+ Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut;
+
+ void verifyArtifacts() throws Exception {
+ this.artifactName = getProject().getName();
+ this.artifactVersion = getProject().getVersion().toString();
+
+ this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD));
+ this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED));
+ this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API));
+ this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE));
+
+ this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
+
+ if (!Files.exists(this.artifactPath)) {
+ throw new Exception("Artifact not found! Run build first!");
+ }
+ }
+
+ void write(InputStream stream, Path file) throws Exception {
+ if (Files.exists(file)) {
+ Files.delete(file);
+ }
+ Files.copy(stream, file);
+ }
+
+ String formatVersion(String string) {
+ return String.format(string, this.artifactName, this.artifactVersion);
+ }
+
+ Path getRelativeFile(String file) {
+ return Paths.get(new File(file).getAbsolutePath());
+ }
+
+ Path getTemporaryFile(String file) {
+ return Paths.get(new File(getTemporaryDir(), file).getAbsolutePath());
+ }
+
+ Path getBuildFile(String file) {
+ return getRelativeFile("build/libs/" + file);
+ }
+
+ JsonElement readJson(List lines) {
+ return PARSER.parse(String.join("\n", lines));
+ }
+}
diff --git a/buildSrc/src/main/java/baritone/gradle/task/CreateDistTask.java b/buildSrc/src/main/java/baritone/gradle/task/CreateDistTask.java
new file mode 100644
index 00000000..f0d3e547
--- /dev/null
+++ b/buildSrc/src/main/java/baritone/gradle/task/CreateDistTask.java
@@ -0,0 +1,81 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.gradle.task;
+
+import org.gradle.api.tasks.TaskAction;
+
+import javax.xml.bind.DatatypeConverter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
+/**
+ * @author Brady
+ * @since 10/12/2018
+ */
+public class CreateDistTask extends BaritoneGradleTask {
+
+ private static MessageDigest SHA1_DIGEST;
+
+ @TaskAction
+ private void exec() throws Exception {
+ super.verifyArtifacts();
+
+ // Define the distribution file paths
+ Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API));
+ Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE));
+ Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED));
+
+ // NIO will not automatically create directories
+ Path dir = getRelativeFile("dist/");
+ if (!Files.exists(dir)) {
+ Files.createDirectory(dir);
+ }
+
+ // Copy build jars to dist/
+ Files.copy(this.artifactApiPath, api, REPLACE_EXISTING);
+ Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING);
+ Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING);
+
+ // Calculate all checksums and format them like "shasum"
+ List shasum = Stream.of(api, standalone, unoptimized)
+ .map(path -> sha1(path) + " " + path.getFileName().toString())
+ .collect(Collectors.toList());
+
+ // Write the checksums to a file
+ Files.write(getRelativeFile("dist/checksums.txt"), shasum);
+ }
+
+ private static String sha1(Path path) {
+ try {
+ if (SHA1_DIGEST == null) {
+ SHA1_DIGEST = MessageDigest.getInstance("SHA-1");
+ }
+ return DatatypeConverter.printHexBinary(SHA1_DIGEST.digest(Files.readAllBytes(path))).toLowerCase();
+ } catch (Exception e) {
+ // haha no thanks
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java
new file mode 100644
index 00000000..ad0db8cc
--- /dev/null
+++ b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java
@@ -0,0 +1,260 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.gradle.task;
+
+import baritone.gradle.util.Determinizer;
+import com.google.gson.*;
+import org.apache.commons.io.IOUtils;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.internal.Pair;
+
+import java.io.*;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
+/**
+ * @author Brady
+ * @since 10/11/2018
+ */
+public class ProguardTask extends BaritoneGradleTask {
+
+ private static final Pattern TEMP_LIBRARY_PATTERN = Pattern.compile("-libraryjars 'tempLibraries\\/([a-zA-Z0-9/_\\-\\.]+)\\.jar'");
+
+ @Input
+ private String url;
+
+ @Input
+ private String extract;
+
+ @Input
+ private String versionManifest;
+
+ private Map versionDownloadMap;
+ private List requiredLibraries;
+
+ @TaskAction
+ private void exec() throws Exception {
+ super.verifyArtifacts();
+
+ // "Haha brady why don't you make separate tasks"
+ processArtifact();
+ downloadProguard();
+ extractProguard();
+ generateConfigs();
+ downloadVersionManifest();
+ acquireDependencies();
+ proguardApi();
+ proguardStandalone();
+ cleanup();
+ }
+
+ private void processArtifact() throws Exception {
+ if (Files.exists(this.artifactUnoptimizedPath)) {
+ Files.delete(this.artifactUnoptimizedPath);
+ }
+
+ Determinizer.main(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString());
+ }
+
+ private void downloadProguard() throws Exception {
+ Path proguardZip = getTemporaryFile(PROGUARD_ZIP);
+ if (!Files.exists(proguardZip)) {
+ write(new URL(this.url).openStream(), proguardZip);
+ }
+ }
+
+ private void extractProguard() throws Exception {
+ Path proguardJar = getTemporaryFile(PROGUARD_JAR);
+ if (!Files.exists(proguardJar)) {
+ ZipFile zipFile = new ZipFile(getTemporaryFile(PROGUARD_ZIP).toFile());
+ ZipEntry zipJarEntry = zipFile.getEntry(this.extract);
+ write(zipFile.getInputStream(zipJarEntry), proguardJar);
+ zipFile.close();
+ }
+ }
+
+ private void generateConfigs() throws Exception {
+ Files.copy(getRelativeFile(PROGUARD_CONFIG_TEMPLATE), getTemporaryFile(PROGUARD_CONFIG_DEST), REPLACE_EXISTING);
+
+ // Setup the template that will be used to derive the API and Standalone configs
+ List template = Files.readAllLines(getTemporaryFile(PROGUARD_CONFIG_DEST));
+ template.add(0, "-injars " + this.artifactPath.toString());
+ template.add(1, "-outjars " + this.getTemporaryFile(PROGUARD_EXPORT_PATH));
+
+ // Acquire the RT jar using "java -verbose". This doesn't work on Java 9+
+ Process p = new ProcessBuilder("java", "-verbose").start();
+ String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
+ template.add(2, "-libraryjars '" + out + "'");
+
+ // API config doesn't require any changes from the changes that we made to the template
+ Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);
+
+ // For the Standalone config, don't keep the API package
+ List standalone = new ArrayList<>(template);
+ standalone.removeIf(s -> s.contains("# this is the keep api"));
+ Files.write(getTemporaryFile(PROGUARD_STANDALONE_CONFIG), standalone);
+
+ // Discover all of the libraries that we will need to acquire from gradle
+ this.requiredLibraries = new ArrayList<>();
+ template.forEach(line -> {
+ if (!line.startsWith("#")) {
+ Matcher m = TEMP_LIBRARY_PATTERN.matcher(line);
+ if (m.find()) {
+ this.requiredLibraries.add(m.group(1));
+ }
+ }
+ });
+ }
+
+ private void downloadVersionManifest() throws Exception {
+ Path manifestJson = getTemporaryFile(VERSION_MANIFEST);
+ write(new URL(this.versionManifest).openStream(), manifestJson);
+
+ // Place all the versions in the map with their download URL
+ this.versionDownloadMap = new HashMap<>();
+ JsonObject json = readJson(Files.readAllLines(manifestJson)).getAsJsonObject();
+ JsonArray versions = json.getAsJsonArray("versions");
+ versions.forEach(element -> {
+ JsonObject object = element.getAsJsonObject();
+ this.versionDownloadMap.put(object.get("id").getAsString(), object.get("url").getAsString());
+ });
+ }
+
+ private void acquireDependencies() throws Exception {
+
+ // Create a map of all of the dependencies that we are able to access in this project
+ // Likely a better way to do this, I just pair the dependency with the first valid configuration
+ Map> dependencyLookupMap = new HashMap<>();
+ getProject().getConfigurations().stream().filter(Configuration::isCanBeResolved).forEach(config ->
+ config.getAllDependencies().forEach(dependency ->
+ dependencyLookupMap.putIfAbsent(dependency.getName() + "-" + dependency.getVersion(), Pair.of(config, dependency))));
+
+ // Create the directory if it doesn't already exist
+ Path tempLibraries = getTemporaryFile(TEMP_LIBRARY_DIR);
+ if (!Files.exists(tempLibraries)) {
+ Files.createDirectory(tempLibraries);
+ }
+
+ // Iterate the required libraries to copy them to tempLibraries
+ for (String lib : this.requiredLibraries) {
+ // Download the version jar from the URL acquired from the version manifest
+ if (lib.startsWith("minecraft")) {
+ String version = lib.split("-")[1];
+ Path versionJar = getTemporaryFile("tempLibraries/" + lib + ".jar");
+ if (!Files.exists(versionJar)) {
+ JsonObject versionJson = PARSER.parse(new InputStreamReader(new URL(this.versionDownloadMap.get(version)).openStream())).getAsJsonObject();
+ String url = versionJson.getAsJsonObject("downloads").getAsJsonObject("client").getAsJsonPrimitive("url").getAsString();
+ write(new URL(url).openStream(), versionJar);
+ }
+ continue;
+ }
+
+ // Find a configuration/dependency pair that matches the desired library
+ Pair pair = null;
+ for (Map.Entry> entry : dependencyLookupMap.entrySet()) {
+ if (entry.getKey().startsWith(lib)) {
+ pair = entry.getValue();
+ }
+ }
+
+ // The pair must be non-null
+ Objects.requireNonNull(pair);
+
+ // Find the library jar file, and copy it to tempLibraries
+ for (File file : pair.getLeft().files(pair.getRight())) {
+ if (file.getName().startsWith(lib)) {
+ Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING);
+ }
+ }
+ }
+ }
+
+ private void proguardApi() throws Exception {
+ runProguard(getTemporaryFile(PROGUARD_API_CONFIG));
+ Determinizer.main(this.proguardOut.toString(), this.artifactApiPath.toString());
+ }
+
+ private void proguardStandalone() throws Exception {
+ runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG));
+ Determinizer.main(this.proguardOut.toString(), this.artifactStandalonePath.toString());
+ }
+
+ private void cleanup() {
+ try {
+ Files.delete(this.proguardOut);
+ } catch (IOException ignored) {}
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public void setExtract(String extract) {
+ this.extract = extract;
+ }
+
+ public void setVersionManifest(String versionManifest) {
+ this.versionManifest = versionManifest;
+ }
+
+ private void runProguard(Path config) throws Exception {
+ // Delete the existing proguard output file. Proguard probably handles this already, but why not do it ourselves
+ if (Files.exists(this.proguardOut)) {
+ Files.delete(this.proguardOut);
+ }
+
+ Path proguardJar = getTemporaryFile(PROGUARD_JAR);
+ Process p = new ProcessBuilder("java", "-jar", proguardJar.toString(), "@" + config.toString())
+ .directory(getTemporaryFile("").toFile()) // Set the working directory to the temporary folder]
+ .start();
+
+ // We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this
+ this.printOutputLog(p.getInputStream());
+ this.printOutputLog(p.getErrorStream());
+
+ // Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
+ int exitCode;
+ if ((exitCode = p.waitFor()) != 0) {
+ throw new Exception("Proguard exited with code " + exitCode);
+ }
+ }
+
+ private void printOutputLog(InputStream stream) {
+ new Thread(() -> {
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ System.out.println(line);
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }).start();
+ }
+}
diff --git a/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java
new file mode 100644
index 00000000..a4dcaca3
--- /dev/null
+++ b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java
@@ -0,0 +1,181 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.gradle.util;
+
+import com.google.gson.*;
+import com.google.gson.internal.LazilyParsedNumber;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.stream.Collectors;
+
+/**
+ * Make a .jar file deterministic by sorting all entries by name, and setting all the last modified times to 0.
+ * This makes the build 100% reproducible since the timestamp when you built it no longer affects the final file.
+ *
+ * @author leijurv
+ */
+public class Determinizer {
+
+ public static void main(String... args) throws IOException {
+ System.out.println("Running Determinizer");
+ System.out.println(" Input path: " + args[0]);
+ System.out.println(" Output path: " + args[1]);
+
+ JarFile jarFile = new JarFile(new File(args[0]));
+ JarOutputStream jos = new JarOutputStream(new FileOutputStream(new File(args[1])));
+
+ List entries = jarFile.stream()
+ .sorted(Comparator.comparing(JarEntry::getName))
+ .collect(Collectors.toList());
+
+ for (JarEntry entry : entries) {
+ if (entry.getName().equals("META-INF/fml_cache_annotation.json")) {
+ continue;
+ }
+ if (entry.getName().equals("META-INF/fml_cache_class_versions.json")) {
+ continue;
+ }
+ JarEntry clone = new JarEntry(entry.getName());
+ clone.setTime(0);
+ jos.putNextEntry(clone);
+ if (entry.getName().endsWith(".refmap.json")) {
+ JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject();
+ copy(writeSorted(object), jos);
+ } else {
+ copy(jarFile.getInputStream(entry), jos);
+ }
+ }
+
+ jos.finish();
+ jos.close();
+ jarFile.close();
+ }
+
+ private static void copy(InputStream is, OutputStream os) throws IOException {
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = is.read(buffer)) != -1) {
+ os.write(buffer, 0, len);
+ }
+ }
+
+ private static void copy(String s, OutputStream os) throws IOException {
+ os.write(s.getBytes());
+ }
+
+ private static String writeSorted(JsonObject in) throws IOException {
+ StringWriter writer = new StringWriter();
+ JsonWriter jw = new JsonWriter(writer);
+ JSON_ELEMENT.write(jw, in);
+ return writer.toString() + "\n";
+ }
+
+ /**
+ * All credits go to GSON and its contributors. GSON is licensed under the Apache 2.0 License.
+ * This implementation has been modified to write {@link JsonObject} keys in order.
+ *
+ * @see GSON License
+ * @see Original Source
+ */
+ private static final TypeAdapter JSON_ELEMENT = new TypeAdapter() {
+
+ @Override
+ public JsonElement read(JsonReader in) throws IOException {
+ switch (in.peek()) {
+ case STRING:
+ return new JsonPrimitive(in.nextString());
+ case NUMBER:
+ String number = in.nextString();
+ return new JsonPrimitive(new LazilyParsedNumber(number));
+ case BOOLEAN:
+ return new JsonPrimitive(in.nextBoolean());
+ case NULL:
+ in.nextNull();
+ return JsonNull.INSTANCE;
+ case BEGIN_ARRAY:
+ JsonArray array = new JsonArray();
+ in.beginArray();
+ while (in.hasNext()) {
+ array.add(read(in));
+ }
+ in.endArray();
+ return array;
+ case BEGIN_OBJECT:
+ JsonObject object = new JsonObject();
+ in.beginObject();
+ while (in.hasNext()) {
+ object.add(in.nextName(), read(in));
+ }
+ in.endObject();
+ return object;
+ case END_DOCUMENT:
+ case NAME:
+ case END_OBJECT:
+ case END_ARRAY:
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void write(JsonWriter out, JsonElement value) throws IOException {
+ if (value == null || value.isJsonNull()) {
+ out.nullValue();
+ } else if (value.isJsonPrimitive()) {
+ JsonPrimitive primitive = value.getAsJsonPrimitive();
+ if (primitive.isNumber()) {
+ out.value(primitive.getAsNumber());
+ } else if (primitive.isBoolean()) {
+ out.value(primitive.getAsBoolean());
+ } else {
+ out.value(primitive.getAsString());
+ }
+
+ } else if (value.isJsonArray()) {
+ out.beginArray();
+ for (JsonElement e : value.getAsJsonArray()) {
+ write(out, e);
+ }
+ out.endArray();
+
+ } else if (value.isJsonObject()) {
+ out.beginObject();
+
+ List> entries = new ArrayList<>(value.getAsJsonObject().entrySet());
+ entries.sort(Comparator.comparing(Map.Entry::getKey));
+ for (Map.Entry e : entries) {
+ out.name(e.getKey());
+ write(out, e.getValue());
+ }
+ out.endObject();
+
+ } else {
+ throw new IllegalArgumentException("Couldn't write " + value.getClass());
+ }
+ }
+ };
+}
diff --git a/scripts/Determinizer.java b/scripts/Determinizer.java
deleted file mode 100644
index e15f0b2c..00000000
--- a/scripts/Determinizer.java
+++ /dev/null
@@ -1,49 +0,0 @@
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.stream.Collectors;
-
-/**
- * Make a .jar file deterministic by sorting all entries by name, and setting all the last modified times to 0.
- * This makes the build 100% reproducible since the timestamp when you built it no longer affects the final file.
- * @author leijurv
- */
-public class Determinizer {
-
- public static void main(String[] args) throws IOException {
- System.out.println("Input path: " + args[0] + " Output path: " + args[1]);
- JarFile jarFile = new JarFile(new File(args[0]));
- JarOutputStream jos = new JarOutputStream(new FileOutputStream(new File(args[1])));
- ArrayList entries = jarFile.stream().collect(Collectors.toCollection(ArrayList::new));
- entries.sort(Comparator.comparing(JarEntry::getName));
- for (JarEntry entry : entries) {
- if (entry.getName().equals("META-INF/fml_cache_annotation.json")) {
- continue;
- }
- if (entry.getName().equals("META-INF/fml_cache_class_versions.json")) {
- continue;
- }
- JarEntry clone = new JarEntry(entry.getName());
- clone.setTime(0);
- jos.putNextEntry(clone);
- copy(jarFile.getInputStream(entry), jos);
- }
- jos.finish();
- jarFile.close();
- }
-
- public static void copy(InputStream is, OutputStream os) throws IOException {
- byte[] buffer = new byte[1024];
- int len;
- while ((len = is.read(buffer)) != -1) {
- os.write(buffer, 0, len);
- }
- }
-}
diff --git a/scripts/build.sh b/scripts/build.sh
deleted file mode 100644
index 4f0bc608..00000000
--- a/scripts/build.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-set -e # this makes the whole script fail immediately if any one of these commands fails
-./gradlew build
-export VERSION=$(cat build.gradle | grep "version '" | cut -d "'" -f 2-2)
-
-unzip -p build/libs/baritone-$VERSION.jar "mixins.baritone.refmap.json" | jq --sort-keys -c -M '.' > mixins.baritone.refmap.json
-zip -u build/libs/baritone-$VERSION.jar mixins.baritone.refmap.json
-rm mixins.baritone.refmap.json
-
-cd scripts
-javac Determinizer.java
-java Determinizer ../build/libs/baritone-$VERSION.jar temp.jar
-mv temp.jar ../build/libs/baritone-$VERSION.jar
-cd ..
-
-
-wget -nv https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip
-unzip proguard6.0.3.zip 2>&1 > /dev/null
-cd build/libs
-rm -rf api.pro
-echo "-injars 'baritone-$VERSION.jar'" >> api.pro # insert current version
-cat ../../scripts/proguard.pro | grep -v "this is the rt jar" | grep -v "\-injars" >> api.pro # remove default rt jar and injar lines
-echo "-libraryjars '$(java -verbose 2>/dev/null | sed -ne '1 s/\[Opened \(.*\)\]/\1/p')'" >> api.pro # insert correct rt.jar location
-tail api.pro # debug, print out what the previous two commands generated
-cat api.pro | grep -v "this is the keep api" > standalone.pro # standalone doesn't keep baritone api
-
-#instead of downloading these jars from my dropbox in a zip, just assume gradle's already got them for us
-mkdir -p tempLibraries
-cat ../../scripts/proguard.pro | grep tempLibraries | grep .jar | cut -d "/" -f 2- | cut -d "'" -f -1 | xargs -n1 -I{} bash -c "find ~/.gradle -name {}" | tee /dev/stderr | xargs -n1 -I{} cp {} tempLibraries
-
-rm -rf ../../dist
-mkdir ../../dist
-java -jar ../../proguard6.0.3/lib/proguard.jar @api.pro
-cd ../../scripts
-java Determinizer ../build/libs/Obfuscated/baritone-$VERSION.jar ../dist/baritone-api-$VERSION.jar
-cd ../build/libs
-rm -rf Obfuscated/*
-java -jar ../../proguard6.0.3/lib/proguard.jar @standalone.pro
-cd ../../scripts
-java Determinizer ../build/libs/Obfuscated/baritone-$VERSION.jar ../dist/baritone-standalone-$VERSION.jar
-cd ../build/libs
-mv baritone-$VERSION.jar ../../dist/baritone-unoptimized-$VERSION.jar
-cd ../../dist
-shasum * | tee checksums.txt
-cd ..
\ No newline at end of file
diff --git a/scripts/proguard.pro b/scripts/proguard.pro
index 8b406e69..4baa4b2a 100644
--- a/scripts/proguard.pro
+++ b/scripts/proguard.pro
@@ -1,7 +1,3 @@
--injars baritone-0.0.8.jar
--outjars Obfuscated
-
-
-keepattributes Signature
-keepattributes *Annotation*
@@ -29,7 +25,6 @@
-keep class baritone.launch.** { *; }
# copy all necessary libraries into tempLibraries to build
--libraryjars '/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/rt.jar' # this is the rt jar
-libraryjars 'tempLibraries/minecraft-1.12.2.jar'
@@ -49,7 +44,6 @@
-libraryjars 'tempLibraries/httpclient-4.3.3.jar'
-libraryjars 'tempLibraries/httpcore-4.3.2.jar'
-libraryjars 'tempLibraries/icu4j-core-mojang-51.2.jar'
--libraryjars 'tempLibraries/java-objc-bridge-1.0.0.jar'
-libraryjars 'tempLibraries/jinput-2.0.5.jar'
-libraryjars 'tempLibraries/jna-4.4.0.jar'
-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar'
@@ -60,13 +54,10 @@
-libraryjars 'tempLibraries/log4j-api-2.8.1.jar'
-libraryjars 'tempLibraries/log4j-core-2.8.1.jar'
-# linux / travis
--libraryjars 'tempLibraries/lwjgl-2.9.4-nightly-20150209.jar'
--libraryjars 'tempLibraries/lwjgl_util-2.9.4-nightly-20150209.jar'
-
-# mac
-#-libraryjars 'tempLibraries/lwjgl_util-2.9.2-nightly-20140822.jar'
-#-libraryjars 'tempLibraries/lwjgl-2.9.2-nightly-20140822.jar'
+# startsWith is used to check the library, and mac/linux differ in which version they use
+# this is FINE
+-libraryjars 'tempLibraries/lwjgl-.jar'
+-libraryjars 'tempLibraries/lwjgl_util-.jar'
-libraryjars 'tempLibraries/netty-all-4.1.9.Final.jar'
-libraryjars 'tempLibraries/oshi-core-1.1.jar'