Skip to content

Commit

Permalink
Fix crash when starting 1.2.5 server (#866)
Browse files Browse the repository at this point in the history
  • Loading branch information
modmuss50 authored Dec 13, 2023
1 parent 9f8521e commit 9aa2b91
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.function.Consumer;
import java.util.function.Function;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
Expand All @@ -35,12 +34,12 @@

public final class BrandingPatch extends GamePatch {
@Override
public void process(FabricLauncher launcher, Function<String, ClassReader> classSource, Consumer<ClassNode> classEmitter) {
public void process(FabricLauncher launcher, Function<String, ClassNode> classSource, Consumer<ClassNode> classEmitter) {
for (String brandClassName : new String[] {
"net.minecraft.client.ClientBrandRetriever",
"net.minecraft.server.MinecraftServer"
}) {
ClassNode brandClass = readClass(classSource.apply(brandClassName));
ClassNode brandClass = classSource.apply(brandClassName);

if (brandClass != null) {
if (applyBrandingPatch(brandClass)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.function.Consumer;
import java.util.function.Function;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
Expand Down Expand Up @@ -62,7 +61,7 @@ private void finishEntrypoint(EnvType type, ListIterator<AbstractInsnNode> it) {
}

@Override
public void process(FabricLauncher launcher, Function<String, ClassReader> classSource, Consumer<ClassNode> classEmitter) {
public void process(FabricLauncher launcher, Function<String, ClassNode> classSource, Consumer<ClassNode> classEmitter) {
EnvType type = launcher.getEnvironmentType();
String entrypoint = launcher.getEntrypoint();
Version gameVersion = getGameVersion();
Expand All @@ -74,7 +73,7 @@ public void process(FabricLauncher launcher, Function<String, ClassReader> class
String gameEntrypoint = null;
boolean serverHasFile = true;
boolean isApplet = entrypoint.contains("Applet");
ClassNode mainClass = readClass(classSource.apply(entrypoint));
ClassNode mainClass = classSource.apply(entrypoint);

if (mainClass == null) {
throw new RuntimeException("Could not load main class " + entrypoint + "!");
Expand Down Expand Up @@ -189,7 +188,7 @@ public void process(FabricLauncher launcher, Function<String, ClassReader> class
if (gameEntrypoint.equals(entrypoint) || is20w22aServerOrHigher) {
gameClass = mainClass;
} else {
gameClass = readClass(classSource.apply(gameEntrypoint));
gameClass = classSource.apply(gameEntrypoint);
if (gameClass == null) throw new RuntimeException("Could not load game class " + gameEntrypoint + "!");
}

Expand Down Expand Up @@ -527,22 +526,22 @@ public void process(FabricLauncher launcher, Function<String, ClassReader> class
}
}

private boolean hasSuperClass(String cls, String superCls, Function<String, ClassReader> classSource) {
private boolean hasSuperClass(String cls, String superCls, Function<String, ClassNode> classSource) {
if (cls.contains("$") || (!cls.startsWith("net/minecraft") && cls.contains("/"))) {
return false;
}

ClassReader reader = classSource.apply(cls);
ClassNode classNode = classSource.apply(cls);

return reader != null && reader.getSuperName().equals(superCls);
return classNode != null && classNode.superName.equals(superCls);
}

private boolean hasStrInMethod(String cls, String methodName, String methodDesc, String str, Function<String, ClassReader> classSource) {
private boolean hasStrInMethod(String cls, String methodName, String methodDesc, String str, Function<String, ClassNode> classSource) {
if (cls.contains("$") || (!cls.startsWith("net/minecraft") && cls.contains("/"))) {
return false;
}

ClassNode node = readClass(classSource.apply(cls));
ClassNode node = classSource.apply(cls);
if (node == null) return false;

for (MethodNode method : node.methods) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class EntrypointPatchFML125 extends GamePatch {
private static final String TO_INTERNAL = "cpw/mods/fml/common/ModClassLoader";

@Override
public void process(FabricLauncher launcher, Function<String, ClassReader> classSource, Consumer<ClassNode> classEmitter) {
public void process(FabricLauncher launcher, Function<String, ClassNode> classSource, Consumer<ClassNode> classEmitter) {
if (classSource.apply(TO) != null
&& classSource.apply("cpw.mods.fml.relauncher.FMLRelauncher") == null) {
if (!(launcher instanceof Knot)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.function.Consumer;
import java.util.function.Function;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
Expand All @@ -47,7 +46,7 @@ public final class TinyFDPatch extends GamePatch {
private static final String DIALOG_TITLE = "Select settings file (.json)";

@Override
public void process(FabricLauncher launcher, Function<String, ClassReader> classSource, Consumer<ClassNode> classEmitter) {
public void process(FabricLauncher launcher, Function<String, ClassNode> classSource, Consumer<ClassNode> classEmitter) {
if (launcher.getEnvironmentType() != EnvType.CLIENT) {
// Fix should only be applied to clients.
return;
Expand All @@ -61,7 +60,7 @@ public void process(FabricLauncher launcher, Function<String, ClassReader> class
className = FabricLoader.getInstance().getMappingResolver().mapClassName("intermediary", MORE_OPTIONS_DIALOG_CLASS_NAME);
}

final ClassNode classNode = readClass(classSource.apply(className));
final ClassNode classNode = classSource.apply(className);

if (classNode == null) {
// Class is not present in this version, nothing to do.
Expand Down
11 changes: 1 addition & 10 deletions src/main/java/net/fabricmc/loader/impl/game/patch/GamePatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
Expand All @@ -33,14 +32,6 @@
import net.fabricmc.loader.impl.launch.FabricLauncher;

public abstract class GamePatch {
protected static ClassNode readClass(ClassReader reader) {
if (reader == null) return null;

ClassNode node = new ClassNode();
reader.accept(node, 0);
return node;
}

protected FieldNode findField(ClassNode node, Predicate<FieldNode> predicate) {
return node.fields.stream().filter(predicate).findAny().orElse(null);
}
Expand Down Expand Up @@ -128,5 +119,5 @@ protected boolean isPublicInstance(int access) {
return ((access & 0x0F) == (Opcodes.ACC_PUBLIC | 0 /* non-static */));
}

public abstract void process(FabricLauncher launcher, Function<String, ClassReader> classSource, Consumer<ClassNode> classEmitter);
public abstract void process(FabricLauncher launcher, Function<String, ClassNode> classSource, Consumer<ClassNode> classEmitter);
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,23 @@ public void locateEntrypoints(FabricLauncher launcher, List<Path> gameJars) {
patchedClasses = new HashMap<>();

try (SimpleClassPath cp = new SimpleClassPath(gameJars)) {
Function<String, ClassReader> classSource = name -> {
byte[] data = patchedClasses.get(name);
Map<String, ClassNode> patchedClassNodes = new HashMap<>();

if (data != null) {
return new ClassReader(data);
final Function<String, ClassNode> classSource = name -> {
// Reuse previously patched classes if available
if (patchedClassNodes.containsKey(name)) {
return patchedClassNodes.get(name);
}

try {
CpEntry entry = cp.getEntry(LoaderUtil.getClassFileName(name));
if (entry == null) return null;

try (InputStream is = entry.getInputStream()) {
return new ClassReader(is);
} catch (IOException | ZipError e) {
throw new RuntimeException(String.format("error reading %s in %s: %s", name, LoaderUtil.normalizePath(entry.getOrigin()), e), e);
}
} catch (IOException e) {
throw ExceptionUtil.wrap(e);
}
return readClassNode(cp, name);
};

for (GamePatch patch : patches) {
patch.process(launcher, classSource, this::addPatchedClass);
patch.process(launcher, classSource, classNode -> patchedClassNodes.put(classNode.name, classNode));
}

for (ClassNode patchedClassNode : patchedClassNodes.values()) {
addPatchedClass(patchedClassNode);
}
} catch (IOException e) {
throw ExceptionUtil.wrap(e);
Expand All @@ -99,6 +93,27 @@ public void locateEntrypoints(FabricLauncher launcher, List<Path> gameJars) {
entrypointsLocated = true;
}

private ClassNode readClassNode(SimpleClassPath classpath, String name) {
byte[] data = patchedClasses.get(name);

if (data != null) {
return readClass(new ClassReader(data));
}

try {
CpEntry entry = classpath.getEntry(LoaderUtil.getClassFileName(name));
if (entry == null) return null;

try (InputStream is = entry.getInputStream()) {
return readClass(new ClassReader(is));
} catch (IOException | ZipError e) {
throw new RuntimeException(String.format("error reading %s in %s: %s", name, LoaderUtil.normalizePath(entry.getOrigin()), e), e);
}
} catch (IOException e) {
throw ExceptionUtil.wrap(e);
}
}

/**
* This must run first, contractually!
* @param className The class name,
Expand All @@ -107,4 +122,12 @@ public void locateEntrypoints(FabricLauncher launcher, List<Path> gameJars) {
public byte[] transform(String className) {
return patchedClasses.get(className);
}

private static ClassNode readClass(ClassReader reader) {
if (reader == null) return null;

ClassNode node = new ClassNode();
reader.accept(node, 0);
return node;
}
}

0 comments on commit 9aa2b91

Please sign in to comment.