Skip to content

Commit

Permalink
Merge pull request #43 from ShaneBeeStudios/feature/revamp-version
Browse files Browse the repository at this point in the history
Version - complete revamp
  • Loading branch information
ShaneBeee authored Mar 1, 2024
2 parents b93561f + 26d2699 commit d027a26
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 369 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<artifactId>slf4j-simple</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.1.0</version>
</dependency>
</dependencies>

<build>
Expand Down
17 changes: 10 additions & 7 deletions src/main/java/com/shanebeestudios/mcdeop/McDeob.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
public class McDeob {

public static void main(String[] args) {
Version.initVersions();
if (args.length == 0) {
try {
if (Util.isRunningMacOS()) {
Expand All @@ -34,11 +35,11 @@ public static void main(String[] args) {
parser.accepts("help", "Shows help and exits");
parser.accepts("versions", "Prints a list of all Minecraft versions available to deobfuscate");
parser.accepts("version", "Minecraft version for which we're deobfuscating")
.withRequiredArg()
.ofType(String.class);
.withRequiredArg()
.ofType(String.class);
parser.accepts("type", "What we should deobfuscate: client or server")
.withRequiredArg()
.ofType(String.class);
.withRequiredArg()
.ofType(String.class);
parser.accepts("decompile", "Marks that we should decompile the deobfuscated source");

OptionSet options = parser.parse(args);
Expand Down Expand Up @@ -72,19 +73,21 @@ public static void main(String[] args) {
String versionString = (String) options.valueOf("version");
String typeString = (String) options.valueOf("type");

Version.Type type;
try {
Version.Type.valueOf(typeString.toUpperCase());
type = Version.Type.valueOf(typeString.toUpperCase());
} catch (IllegalArgumentException e) {
Logger.error("Invalid type specified, shutting down...");
System.exit(1);
return;
}

Version.Type type = Version.Type.valueOf(typeString.toUpperCase());
Version version = Version.getByVersion(versionString, type);
Version version = Version.getByVersion(versionString);
if (version == null) {
Logger.error("Invalid or unsupported version was specified, shutting down...");
System.exit(1);
}
version.setType(type);

boolean decompile = options.has("decompile");

Expand Down
214 changes: 58 additions & 156 deletions src/main/java/com/shanebeestudios/mcdeop/Processor.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,12 @@
import com.shanebeestudios.mcdeop.util.Util;
import io.github.lxgaming.reconstruct.common.Reconstruct;
import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InvalidObjectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Expand All @@ -28,15 +20,6 @@
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class Processor {
private static final URL LATEST_INFO;

static {
try {
LATEST_INFO = new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json");
} catch (MalformedURLException e) {
throw new AssertionError("Impossible");
}
}

private final Version version;
private final boolean decompile;
Expand All @@ -46,8 +29,6 @@ public class Processor {
private Path jarPath;
private Path mappingsPath;
private Path remappedJar;
private String mappingsUrl;
private String jarUrl;

private String minecraftJarName;
private String mappingsName;
Expand All @@ -57,75 +38,75 @@ public class Processor {

public Processor(Version version, boolean decompile, App app) {
this.version = version;
this.decompile = decompile;
this.app = app;
if (Util.isRunningMacOS()) {
// If running on macOS, put the output directory in the user home directory.
// This is due to how macOS APPs work — their '.' directory resolves to one inside the APP itself.
dataFolderPath = Paths.get(System.getProperty("user.home"), "McDeob");
this.dataFolderPath = Paths.get(System.getProperty("user.home"), "McDeob");
}
try {
Files.createDirectories(dataFolderPath);
Files.createDirectories(this.dataFolderPath);
} catch (IOException ignore) {
}

minecraftJarName = String.format("minecraft_%s_%s.jar", version.getType().getName(), version.getVersion());
mappingsName = String.format("mappings_%s_%s.txt", version.getType().getName(), version.getVersion());
mappedJarName = String.format("remapped_%s_%s.jar", version.getType().getName(), version.getVersion());
jarUrl = version.getJar();
mappingsUrl = version.getMappings();
this.decompile = decompile;
this.reconstruct = new Reconstruct(new ReconConfig());
}

@SuppressWarnings("CallToPrintStackTrace")
public void init() {
try {
long start = System.currentTimeMillis();
if (app != null) {
app.toggleControls();
}

if (version.isLatest()) {
String trueVersion = prepareLatest();
if (app != null) {
app.addVersionBox(trueVersion);
// Prepare version and check if valid
String versionName = this.version.getVersion();
if (!this.version.prepareVersion()) {
if (this.app != null) {
this.app.fail();
} else {
System.out.println("Invalid version: " + versionName);
}
return;
}
if (this.app != null) {
this.app.toggleControls();
}

String versionTypeName = this.version.getType().getName();
this.minecraftJarName = String.format("minecraft_%s_%s.jar", versionTypeName, versionName);
this.mappingsName = String.format("mappings_%s_%s.txt", versionTypeName, versionName);
this.mappedJarName = String.format("remapped_%s_%s.jar", versionTypeName, versionName);
this.reconstruct = new Reconstruct(new ReconConfig());

downloadJar();
downloadMappings();
remapJar();
if (decompile) {
if (this.decompile) {
decompileJar();
}
cleanup();

TimeStamp timeStamp = TimeStamp.fromNow(start);
Logger.info("Completed in %s!", timeStamp);
if (app != null) {
app.updateStatusBox(String.format("Completed in %s!", timeStamp));
app.updateButton("Start!");
if (this.app != null) {
this.app.updateStatusBox(String.format("Completed in %s!", timeStamp));
this.app.updateButton("Start!");
this.app.toggleControls();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (app != null) {
app.toggleControls();
}
}
}

public void downloadJar() throws IOException {
long start = System.currentTimeMillis();
Logger.info("Downloading JAR file from Mojang.");
if (app != null) {
app.updateStatusBox("Downloading JAR...");
app.updateButton("Downloading JAR...", Color.BLUE);
if (this.app != null) {
this.app.updateStatusBox("Downloading JAR...");
this.app.updateButton("Downloading JAR...", Color.BLUE);
}

jarPath = dataFolderPath.resolve(minecraftJarName);
final URL parsedURL = new URL(jarUrl);
final HttpURLConnection connection = (HttpURLConnection) parsedURL.openConnection();
this.jarPath = this.dataFolderPath.resolve(this.minecraftJarName);
final URL jarURL = new URL(this.version.getJarURL());
final HttpURLConnection connection = (HttpURLConnection) jarURL.openConnection();
final long length = connection.getContentLengthLong();
if (Files.exists(jarPath) && Files.size(jarPath) == length) {
Logger.info("Already have JAR, skipping download.");
Expand All @@ -140,18 +121,18 @@ public void downloadJar() throws IOException {
public void downloadMappings() throws IOException {
long start = System.currentTimeMillis();
Logger.info("Downloading mappings file from Mojang...");
if (app != null) {
app.updateStatusBox("Downloading mappings...");
app.updateButton("Downloading mappings...", Color.BLUE);
if (this.app != null) {
this.app.updateStatusBox("Downloading mappings...");
this.app.updateButton("Downloading mappings...", Color.BLUE);
}
final URL parsedURL = new URL(mappingsUrl);
final HttpURLConnection connection = (HttpURLConnection) parsedURL.openConnection();
final URL mappingURL = new URL(this.version.getMapURL());
final HttpURLConnection connection = (HttpURLConnection) mappingURL.openConnection();
final long length = connection.getContentLengthLong();
mappingsPath = dataFolderPath.resolve(mappingsName);
if (Files.exists(mappingsPath) && Files.size(mappingsPath) == length) {
this.mappingsPath = this.dataFolderPath.resolve(this.mappingsName);
if (Files.exists(this.mappingsPath) && Files.size(this.mappingsPath) == length) {
Logger.info("Already have mappings, skipping download.");
} else try (final InputStream inputStream = connection.getInputStream()) {
Files.copy(inputStream, mappingsPath, REPLACE_EXISTING);
Files.copy(inputStream, this.mappingsPath, REPLACE_EXISTING);
}

TimeStamp timeStamp = TimeStamp.fromNow(start);
Expand All @@ -160,41 +141,41 @@ public void downloadMappings() throws IOException {

public void remapJar() {
long start = System.currentTimeMillis();
if (app != null) {
app.updateStatusBox("Remapping...");
app.updateButton("Remapping...", Color.BLUE);
if (this.app != null) {
this.app.updateStatusBox("Remapping...");
this.app.updateButton("Remapping...", Color.BLUE);
}
remappedJar = dataFolderPath.resolve(mappedJarName);
this.remappedJar = this.dataFolderPath.resolve(this.mappedJarName);

if (!Files.exists(remappedJar)) {
Logger.info("Remapping %s file...", minecraftJarName);
reconstruct.getConfig().setInputPath(jarPath.toAbsolutePath());
reconstruct.getConfig().setMappingPath(mappingsPath.toAbsolutePath());
reconstruct.getConfig().setOutputPath(remappedJar.toAbsolutePath());
reconstruct.load();
Logger.info("Remapping %s file...", this.minecraftJarName);
this.reconstruct.getConfig().setInputPath(this.jarPath.toAbsolutePath());
this.reconstruct.getConfig().setMappingPath(this.mappingsPath.toAbsolutePath());
this.reconstruct.getConfig().setOutputPath(this.remappedJar.toAbsolutePath());
this.reconstruct.load();

TimeStamp timeStamp = TimeStamp.fromNow(start);
Logger.info("Remapping completed in %s!", timeStamp);
} else {
Logger.info("%s already remapped... skipping mapping.", mappedJarName);
Logger.info("%s already remapped... skipping mapping.", this.mappedJarName);
}
}

public void decompileJar() throws IOException {
long start = System.currentTimeMillis();
Logger.info("Decompiling final JAR file.");
if (app != null) {
app.updateStatusBox("Decompiling... This will take a while!");
app.updateButton("Decompiling...", Color.BLUE);
if (this.app != null) {
this.app.updateStatusBox("Decompiling... This will take a while!");
this.app.updateButton("Decompiling...", Color.BLUE);
}
final Path decompileDir = dataFolderPath.resolve("final-decompile");
final Path decompileDir = this.dataFolderPath.resolve("final-decompile");
Files.createDirectories(decompileDir);

// Setup FernFlower to properly decompile the jar file
String[] args = new String[]{
"-dgs=1", "-hdc=0", "-rbr=0",
"-asc=1", "-udv=0", "-rsy=1",
remappedJar.toAbsolutePath().toString(),
this.remappedJar.toAbsolutePath().toString(),
decompileDir.toAbsolutePath().toString()
};

Expand All @@ -214,90 +195,11 @@ public void decompileJar() throws IOException {
Logger.info("Decompiling completed in %s!", timeStamp);
}

public String prepareLatest() throws IOException {
if (app != null) {
app.updateStatusBox("Fetching version list from Mojang...");
app.updateButton("Fetching...");
}

URLConnection connection = LATEST_INFO.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
final JSONObject versions = new JSONObject(new JSONTokener(in));
in.close();


if (!versions.has("latest")) {
String s = "Failed! Could not locate the latest data from the downloaded manifest file!";
Logger.error(s);
if (app != null) {
app.updateStatusBox(s);
app.updateButton("Exit");
}
throw new InvalidObjectException(s);
}

String type = version == Version.SERVER_LATEST_RELEASE || version == Version.CLIENT_LATEST_RELEASE ? "release" : "snapshot";

String trueVersion = versions.getJSONObject("latest").getString(type);
Logger.info("Finding the URL for " + trueVersion);
if (app != null) {
app.updateStatusBox("Finding the URL for " + trueVersion);
}

String versionURL = null;

JSONArray versionArray = versions.getJSONArray("versions");
for (int i = 0; i < versionArray.length(); i++) {
JSONObject innerVersion = versionArray.getJSONObject(i);

String id = innerVersion.getString("id");
if (id.equalsIgnoreCase(trueVersion)) {
versionURL = innerVersion.getString("url");
break;
}
}

if (versionURL == null) {
String s = "Failed! Could not find information for version " + trueVersion + "!";
Logger.error(s);
if (app != null) {
app.updateStatusBox(s);
app.updateButton("Exit");
}
throw new InvalidObjectException(s);
}

Logger.info("Download data for " + trueVersion + "...");
if (app != null) {
app.updateStatusBox("Download data for " + trueVersion + "...");
}

connection = new URL(versionURL).openConnection();
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
JSONObject versionManifest = new JSONObject(new JSONTokener(in));
in.close();

JSONObject downloads = versionManifest.getJSONObject("downloads");
String clientOrServer = version.getType().getName().toLowerCase();
jarUrl = downloads.getJSONObject(clientOrServer).getString("url");
mappingsUrl = downloads.getJSONObject(clientOrServer + "_mappings").getString("url");

minecraftJarName = String.format("minecraft_%s_%s.jar", clientOrServer, trueVersion);
mappingsName = String.format("mappings_%s_%s.txt", clientOrServer, trueVersion);
mappedJarName = String.format("remapped_%s_%s.jar", clientOrServer, trueVersion);

Logger.info("Found the jar and mappings url for " + trueVersion + "!");
if (app != null) {
app.updateStatusBox("Found the JAR and mappings URL for " + trueVersion + "!");
}
return trueVersion;
}

private void cleanup() {
jarPath = null;
mappingsPath = null;
remappedJar = null;
reconstruct = null;
this.jarPath = null;
this.mappingsPath = null;
this.remappedJar = null;
this.reconstruct = null;
System.gc();
}

Expand Down
Loading

0 comments on commit d027a26

Please sign in to comment.