Skip to content

Commit

Permalink
Fix: c0.0.15a server join, improved Classic saving fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Moresteck committed Oct 8, 2024
1 parent 26f4b6f commit b7104b6
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 60 deletions.
4 changes: 2 additions & 2 deletions src/main/java/uk/betacraft/legacyfix/LegacyFixAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public static void premain(String agentArgs, final Instrumentation inst) {
new BetaForgePatch(),
new ModloaderPatch(),
new BitDepthPatch(),
new ClassicPatch(),
new GameDirPatch(),
new DeAwtPatch(),
new MousePatch(),
new VSyncPatch(),
new C15aPatch()
new VSyncPatch()
));

List<String> patchStates = new ArrayList<String>();
Expand Down
55 changes: 0 additions & 55 deletions src/main/java/uk/betacraft/legacyfix/patch/impl/C15aPatch.java

This file was deleted.

141 changes: 141 additions & 0 deletions src/main/java/uk/betacraft/legacyfix/patch/impl/ClassicPatch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package uk.betacraft.legacyfix.patch.impl;

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

import javassist.CtClass;
import javassist.CtMethod;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.CodeIterator;
import javassist.bytecode.ConstPool;
import javassist.bytecode.Opcode;
import uk.betacraft.legacyfix.LFLogger;
import uk.betacraft.legacyfix.LegacyFixLauncher;
import uk.betacraft.legacyfix.patch.Patch;
import uk.betacraft.legacyfix.patch.PatchHelper;

/**
* Fixes server joining for c0.0.15a and saving in early Classic
*/
public class ClassicPatch extends Patch {
public ClassicPatch() {
super("classicpatch", "Fixes server joining for c0.0.15a and saving in early Classic", true);
}

@Override
public void apply(Instrumentation inst) throws Exception {
CtClass minecraftAppletClass = PatchHelper.findMinecraftAppletClass(pool);
if (minecraftAppletClass.isFrozen())
minecraftAppletClass.defrost();

CtMethod initMethod = minecraftAppletClass.getDeclaredMethod("init");

ConstPool initConstPool = initMethod.getMethodInfo().getConstPool();

CodeAttribute codeAttribute = initMethod.getMethodInfo().getCodeAttribute();
CodeIterator codeIterator = codeAttribute.iterator();

while (codeIterator.hasNext()) {
int pos = codeIterator.next();

patch15aServerJoin(codeIterator, initConstPool, pos);
patchMinecraftUriPort(codeIterator, initConstPool, pos);
}

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

public static void patch15aServerJoin(CodeIterator codeIterator, ConstPool constPool, int pos) {
String server = System.getProperty("server", null);
int port = Integer.parseInt(System.getProperty("port", "25565"));

if (codeIterator.byteAt(pos) != Opcode.ALOAD_0 ||
codeIterator.byteAt(pos + 1) != Opcode.GETFIELD ||
codeIterator.byteAt(pos + 4) != Opcode.LDC ||
codeIterator.byteAt(pos + 6) != Opcode.SIPUSH ||
codeIterator.byteAt(pos + 9) != Opcode.INVOKEVIRTUAL) {
return;
}

int ldcPos = codeIterator.byteAt(pos + 5);
if (constPool.getTag(ldcPos) != ConstPool.CONST_String)
return;

String defaultString = constPool.getStringInfo(ldcPos);
int defaultPort = codeIterator.s16bitAt(pos + 7);

if (!"79.136.77.240".equals(defaultString))
return;

if (defaultPort != 5565)
return;

String refType = constPool.getMethodrefType(codeIterator.u16bitAt(pos + 10));
if (!"(Ljava/lang/String;I)V".equals(refType))
return;

if (server != null) {
// Inject the intended server
int serverRef = constPool.addStringInfo(server);

codeIterator.writeByte(serverRef, pos + 5);
codeIterator.write16bit(port, pos + 7);
} else {
// Erase the call
for (int i = 0; i < 12; i++) {
codeIterator.writeByte(Opcode.NOP, pos + i);
}
}
}

/**
* Patch for negative port number during saving
*/
public static void patchMinecraftUriPort(CodeIterator codeIterator, ConstPool constPool, int pos) {
if (codeIterator.byteAt(pos) != Opcode.INVOKESPECIAL ||
codeIterator.byteAt(pos + 3) != Opcode.ALOAD_0 ||
codeIterator.byteAt(pos + 4) != Opcode.INVOKEVIRTUAL ||
codeIterator.byteAt(pos + 7) != Opcode.INVOKEVIRTUAL ||
codeIterator.byteAt(pos + 10) != Opcode.INVOKEVIRTUAL ||
codeIterator.byteAt(pos + 13) != Opcode.LDC ||
codeIterator.byteAt(pos + 15) != Opcode.INVOKEVIRTUAL ||
codeIterator.byteAt(pos + 18) != Opcode.ALOAD_0 ||
codeIterator.byteAt(pos + 19) != Opcode.INVOKEVIRTUAL ||
codeIterator.byteAt(pos + 22) != Opcode.INVOKEVIRTUAL ||
codeIterator.byteAt(pos + 25) != Opcode.INVOKEVIRTUAL) {
return;
}

int ldcPos = codeIterator.byteAt(pos + 14);
if (constPool.getTag(ldcPos) != ConstPool.CONST_String)
return;

String separatorString = constPool.getStringInfo(ldcPos);
if (!":".equals(separatorString))
return;

String appendStringType = "(Ljava/lang/String;)Ljava/lang/StringBuilder;";
String appendIntType = "(I)Ljava/lang/StringBuilder;";

if (!appendStringType.equals(constPool.getMethodrefType(codeIterator.u16bitAt(pos + 11))) ||
!appendStringType.equals(constPool.getMethodrefType(codeIterator.u16bitAt(pos + 16))) ||
!appendIntType.equals(constPool.getMethodrefType(codeIterator.u16bitAt(pos + 26))))
return;

String getDocumentBaseType = "()Ljava/net/URL;";
if (!getDocumentBaseType.equals(constPool.getMethodrefType(codeIterator.u16bitAt(pos + 5))) ||
!"getDocumentBase".equals(constPool.getMethodrefName(codeIterator.u16bitAt(pos + 5))) ||
!"()Ljava/lang/String;".equals(constPool.getMethodrefType(codeIterator.u16bitAt(pos + 8))) ||
!"getHost".equals(constPool.getMethodrefName(codeIterator.u16bitAt(pos + 8))) ||
!getDocumentBaseType.equals(constPool.getMethodrefType(codeIterator.u16bitAt(pos + 20))) ||
!"getDocumentBase".equals(constPool.getMethodrefName(codeIterator.u16bitAt(pos + 20))) ||
!"()I".equals(constPool.getMethodrefType(codeIterator.u16bitAt(pos + 23))) ||
!"getPort".equals(constPool.getMethodrefName(codeIterator.u16bitAt(pos + 23))))
return;

// Erase the port
for (int i = 0; i < 15; i++) {
codeIterator.writeByte(Opcode.NOP, pos + 13 + i);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public void apply(final Instrumentation inst) throws Exception {
throw new PatchException("No applet class could be found");
}

if (minecraftAppletClass.isFrozen())
minecraftAppletClass.defrost();

CtField minecraftField = PatchHelper.findMinecraftField(pool);
CtClass minecraftClass = PatchHelper.findMinecraftClass(pool);
if (minecraftField == null || minecraftClass == null) {
Expand Down Expand Up @@ -117,11 +120,9 @@ public void edit(MethodCall mc) throws CannotCompileException {

CtMethod getDocumentBaseMethod = javaAppletClass.getDeclaredMethod("getDocumentBase");

// TODO: Investigate another way to patch early classic saving
final int documentPort = minecraftClass.getPackageName().startsWith("com") ? 80 : -1;
// @formatter:off
getDocumentBaseMethod.insertBefore(
"return new java.net.URL(\"http\", \"www.minecraft.net\", " + documentPort + ", \"\");"
"return new java.net.URL(\"http://www.minecraft.net/\");"
);
// @formatter:on

Expand Down

0 comments on commit b7104b6

Please sign in to comment.