Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void process(FabricLauncher launcher, Function<String, ClassNode> classSo
// Main -> Game entrypoint search
//
// -- CLIENT --
// pre-classic: find init() invocation before "Failed to start RubyDung" log message
// pre-1.6 (seems to hold to 0.0.11!): find the only non-static non-java-packaged Object field
// 1.6.1+: [client].start() [INVOKEVIRTUAL]
// 19w04a: [client].<init> [INVOKESPECIAL] -> Thread.start()
Expand Down Expand Up @@ -209,6 +210,62 @@ public void process(FabricLauncher launcher, Function<String, ClassNode> classSo
}
}

if (type == EnvType.CLIENT && !isApplet && gmCandidate.name.equals("run")) {
// For pre-classic, try to find the "Failed to start RubyDung" log message
// that is shown if the init() method throws an exception, then patch said
// init() method.

MethodInsnNode potentialInitInsn = null;
boolean hasFailedToStartLog = false;

for (AbstractInsnNode insn : gmCandidate.instructions) {
if (insn instanceof MethodInsnNode && potentialInitInsn == null) {
MethodInsnNode methodInsn = (MethodInsnNode) insn;

if (methodInsn.getOpcode() == Opcodes.INVOKEVIRTUAL && methodInsn.owner.equals(gameClass.name)) {
potentialInitInsn = methodInsn;
} else {
// first method insn is not init(), this is not pre-classic!
break;
}
}

if (insn instanceof LdcInsnNode && !hasFailedToStartLog) {
if (potentialInitInsn == null) {
// found LDC before init() invocation, this is not pre-classic!
break;
}

Object cst = ((LdcInsnNode) insn).cst;

if (cst instanceof String) {
String s = (String) cst;

if (s.equals("Failed to start RubyDung")) {
hasFailedToStartLog = true;
}
}

if (!hasFailedToStartLog) {
// first LDC insn is not the expected log message, this is not pre-classic!
break;
}
}

if (potentialInitInsn != null && hasFailedToStartLog) {
// found log message and init() invocation, now get the init() method node
for (MethodNode gm : gameClass.methods) {
if (gm.name.equals(potentialInitInsn.name) && gm.desc.equals(potentialInitInsn.desc)) {
gameMethod = gm;
gameMethodQuality = 2;

break;
}
}
}
}
}

if (type == EnvType.CLIENT && !isApplet && gameMethodQuality < 2) {
// Try to find a method with an LDC string "LWJGL Version: ".
// This is the "init()" method, or as of 19w38a is the constructor, or called somewhere in that vicinity,
Expand Down Expand Up @@ -510,6 +567,17 @@ public void process(FabricLauncher launcher, Function<String, ClassNode> classSo
break;
}
}

// TODO: better handling of run directory for pre-classic
if (!patched && gameMethod != gameConstructor) {
ListIterator<AbstractInsnNode> it = gameMethod.instructions.iterator();

it.add(new InsnNode(Opcodes.ACONST_NULL));
it.add(new VarInsnNode(Opcodes.ALOAD, 0));
finishEntrypoint(type, it);

patched = true;
}
}

if (!patched) {
Expand Down