Skip to content

Commit

Permalink
Minor refactoring + Beta Forge patch
Browse files Browse the repository at this point in the history
  • Loading branch information
notdevcody committed Jun 14, 2024
1 parent 32320d6 commit c0c67b2
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 146 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# LegacyFix
![](/.github/img/banner.webp)
<div align="center">
<h1>LegacyFix</h1>
<span>A utility made to patch old and misbehaving versions of Minecraft.</span>
</div>

## What is it?
LegacyFix is a utility made to patch old and misbehaving versions of Minecraft.
![](/.github/img/banner.webp)

### What does it patch?
It aims to patch all known issues with running legacy Minecraft.<br>
Expand All @@ -22,9 +23,8 @@ As of now:
- [ ] Joining servers with c0.0.15a
- [ ] Unnecessary duplicates of sound files and assets
- [ ] Offline saving in Classic versions
- [x] Forge for b1.7.3 - b1.8.1

### How can I use it?
TODO

### What programs use it?
- [BetaCraft Launcher V2](https://github.com/betacraftuk/betacraft-launcher/tree/v2)
- Used by default in the [BetaCraft v2 Launcher](https://github.com/betacraftuk/betacraft-launcher/tree/v2)
- Apply the javaagent in the launcher of your choice
22 changes: 11 additions & 11 deletions src/main/java/uk/betacraft/legacyfix/LFLogger.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package uk.betacraft.legacyfix;

import uk.betacraft.legacyfix.patch.Patch;

public class LFLogger {
public static void info(String msg) {
System.out.println("[INFO] LF: " + msg);
public static void info(String ...lines) {
log("INFO", lines);
}

public static void info(String ...lines) {
for (int i = 0; i < lines.length; i++) {
if (i == 0) {
System.out.println("[INFO] LF: " + lines[i]);
} else {
System.out.println(" " + lines[i]);
}
}
public static void error(Patch patch, Exception e) {
error(patch.getName(), e.toString());
}

public static void error(String ...lines) {
log("ERROR", lines);
}

public static void log(String prefix, String ...lines) {
for (int i = 0; i < lines.length; i++) {
if (i == 0) {
System.out.println("[ERROR] LF: " + lines[i]);
System.out.println("[LF] " + prefix + ": " + lines[i]);
} else {
System.out.println(" " + lines[i]);
}
Expand Down
32 changes: 18 additions & 14 deletions src/main/java/uk/betacraft/legacyfix/LegacyFixAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.instrument.Instrumentation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

public class LegacyFixAgent {
private static final Map<String, Object> SETTINGS = new HashMap<String, Object>();
private static final List<Patch> PATCHES = new ArrayList<Patch>();
private static int jvmVersion = -1;

public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final HashMap<String, String> RELEASE_INFO = GSON.fromJson(new BufferedReader(new InputStreamReader(LegacyFixAgent.class.getResourceAsStream("/releaseInfo.json"))), HashMap.class);
public static final String VERSION = RELEASE_INFO.containsKey("version") ? RELEASE_INFO.get("version") : "unknown";
private static final HashMap<?, ?> RELEASE_INFO = GSON.fromJson(new BufferedReader(new InputStreamReader(LegacyFixAgent.class.getResourceAsStream("/releaseInfo.json"))), HashMap.class);
public static final String VERSION = RELEASE_INFO.containsKey("version") ? (String) RELEASE_INFO.get("version") : "unknown";

public static void premain(String agentArgs, final Instrumentation inst) {
jvmVersion = getMajorJvmVersion();
Expand All @@ -34,17 +31,24 @@ public static void premain(String agentArgs, final Instrumentation inst) {
}
}

PATCHES.add(new DisableControllersPatch());
PATCHES.add(new ModloaderPatch());
PATCHES.add(new DeAwtPatch());
PATCHES.add(new TexturepackFolderPatch());
PATCHES.addAll(Arrays.asList(
new DisableControllersPatch(),
new TexturePackFolderPatch(),
new ModloaderPatch(),
new BetaForgePatch(),
new DeAwtPatch()
));

for (Patch patch : PATCHES) {
if (patch.shouldApply()) {
if (patch.apply(inst)) {
LFLogger.info("Applied " + patch.getName());
} else {
LFLogger.error("Failed to apply " + patch.getName() + "!");
try {
if (patch.apply(inst)) {
LFLogger.info("Applied " + patch.getName());
} else {
LFLogger.error("Failed to apply " + patch.getName());
}
} catch (Exception e) {
LFLogger.error(patch, e);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/uk/betacraft/legacyfix/patch/Patch.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ public boolean shouldApply() {
/**
* Applies the patch. Should only ever be called in the agent's premain.
* @return If the patch was correctly applied
* @throws Exception Exceptions related to class patching
*/
public boolean apply(final Instrumentation inst) {
public boolean apply(final Instrumentation inst) throws Exception {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/
@SuppressWarnings("unused")
public class URLClassLoaderBridge extends URLClassLoader {
private static ArrayList<URL> urls = new ArrayList<URL>();
private static final ArrayList<URL> urls = new ArrayList<URL>();

static {
String classpath = System.getProperty("java.class.path");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package uk.betacraft.legacyfix.patch.impl;

import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import uk.betacraft.legacyfix.patch.Patch;

import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;

/**
* Patches b1.7.3 - b1.8.1 Forge
*/
public class BetaForgePatch extends Patch {
public BetaForgePatch() {
super("betaforge", "Beta Forge");
}

@Override
public boolean apply(Instrumentation inst) throws Exception {
CtClass clazz = pool.getOrNull("forge.ForgeHooksClient");
if (clazz == null) return false;

clazz.instrument(new ExprEditor() {
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("toArray") && m.getSignature().equals("()[Ljava/lang/Object;")) {
m.replace("$_ = $0.toArray(new Integer[0]);");
}
}
});

inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,14 @@ public DisableControllersPatch() {
}

@Override
public boolean apply(Instrumentation inst) {
try {
CtClass clazz = pool.get("org.lwjgl.input.Controllers");
CtMethod method = clazz.getDeclaredMethod("create");
method.setBody(
"{ return; }"
);
public boolean apply(Instrumentation inst) throws Exception {
CtClass clazz = pool.get("org.lwjgl.input.Controllers");
CtMethod method = clazz.getDeclaredMethod("create");
method.setBody(
"{ return; }"
);

inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));
return true;
}
}
70 changes: 31 additions & 39 deletions src/main/java/uk/betacraft/legacyfix/patch/impl/ModloaderPatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public ModloaderPatch() {
}

@Override
public boolean apply(Instrumentation inst) {
public boolean apply(Instrumentation inst) throws Exception {
if (LegacyFixAgent.getJvmVersion() >= 11) {
String args = JvmUtils.getJvmArguments();
if (!(
Expand Down Expand Up @@ -48,49 +48,41 @@ public boolean apply(Instrumentation inst) {
}
}

try {
CtClass clazz;
CtMethod method;
CtClass string = pool.get("java.lang.String");
CtClass clazz = pool.get("java.lang.Class");
CtClass string = pool.get("java.lang.String");
CtMethod method = clazz.getDeclaredMethod("getDeclaredField", new CtClass[] {string});

clazz = pool.get("java.lang.Class");
method = clazz.getDeclaredMethod("getDeclaredField", new CtClass[] {string});
method.setBody(
"{" +
" java.lang.reflect.Field[] fieldz = getDeclaredFields0(false);" +
" for (int i = 0; i < fieldz.length; i++) {" +
" java.lang.reflect.Field one = fieldz[i];" +
" if ($1.equals(one.getName())) {" +
" return one;" +
" }" +
" }" +
" return null;" +
"}"
);
method.setBody(
"{" +
" java.lang.reflect.Field[] fieldz = getDeclaredFields0(false);" +
" for (int i = 0; i < fieldz.length; i++) {" +
" java.lang.reflect.Field one = fieldz[i];" +
" if ($1.equals(one.getName())) {" +
" return one;" +
" }" +
" }" +
" return null;" +
"}"
);

method = clazz.getDeclaredMethod("getDeclaredFields");
method.setBody(
"{" +
" return copyFields($0.getDeclaredFields0(false));" +
"}"
);
method = clazz.getDeclaredMethod("getDeclaredFields");
method.setBody(
"{" +
" return copyFields($0.getDeclaredFields0(false));" +
"}"
);

inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));
inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));

clazz = pool.get("java.lang.ClassLoader");
method = clazz.getDeclaredMethod("loadClass", new CtClass[] {string});
method.insertBefore(
"if ($1.startsWith(\"\\.mod_\")) {" +
" $1 = $1.substring(1);" +
"}"
);

inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));
} catch (Exception e) {
e.printStackTrace();
return false;
}
clazz = pool.get("java.lang.ClassLoader");
method = clazz.getDeclaredMethod("loadClass", new CtClass[] {string});
method.insertBefore(
"if ($1.startsWith(\"\\.mod_\")) {" +
" $1 = $1.substring(1);" +
"}"
);

inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));
return true;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package uk.betacraft.legacyfix.patch.impl;

import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;

import javassist.CtClass;
import javassist.CtMethod;
import uk.betacraft.legacyfix.LFLogger;
import uk.betacraft.legacyfix.patch.Patch;

/**
* Patch for unresponsive "Open texture pack folder" button in versions before 1.2-pre on Linux and macOS
*/
public class TexturePackFolderPatch extends Patch {
public TexturePackFolderPatch() {
super("texturePackButton", "Patch open texture pack folder button");
}

@Override
public boolean apply(final Instrumentation inst) throws Exception {
CtClass clazz;
CtMethod method;
CtClass string = pool.get("java.lang.String");

clazz = pool.getOrNull("org.lwjgl.Sys");
if (clazz == null) return false;

method = clazz.getDeclaredMethod("openURL", new CtClass[] {string});
method.insertBefore(
"if ($1 != null && $1.indexOf(\"file://\") == 0) {" +
" String txpfolder = $1.substring(7);" +
" try {" +
" Class desktopClass = Class.forName(\"java.awt.Desktop\");" +
" Object desktop = desktopClass.getMethod(\"getDesktop\").invoke((Object) null);" +
" desktopClass.getMethod(\"browse\", java.net.URI.class).invoke(desktop, (new java.io.File(txpfolder)).toURI());" +
" return true;" +
" } catch (Throwable t) {" +
" t.printStackTrace();" + // if failed, don't return and have a shot at the Sys.openURL method (vanilla behavior since 1.2-pre)
" }" +
"}"
);

inst.redefineClasses(new ClassDefinition(Class.forName(clazz.getName()), clazz.toBytecode()));
return true;
}

@Override
public boolean shouldApply() {
return true;
}
}
Loading

0 comments on commit c0c67b2

Please sign in to comment.