Skip to content

Commit

Permalink
feat: Обновлен Nukkit-Mot & переработан запуск серверного ядра
Browse files Browse the repository at this point in the history
  • Loading branch information
Reider745 committed Oct 23, 2024
1 parent b1018fa commit 5c5bd62
Show file tree
Hide file tree
Showing 17 changed files with 237 additions and 289 deletions.
Binary file modified iclibs/Nukkit-MOT-SNAPSHOT.jar
Binary file not shown.
25 changes: 25 additions & 0 deletions src/main/java/com/reider745/InstrumentHook.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.reider745;

import java.lang.instrument.Instrumentation;
import java.util.UUID;

public class InstrumentHook {
public static void premain(String agentArgs, Instrumentation inst) {
if (agentArgs != null) {
System.getProperties().put(AGENT_ARGS_KEY, agentArgs);
}
System.getProperties().put(INSTRUMENTATION_KEY, inst);
}

public static Instrumentation getInstrumentation() {
return (Instrumentation) System.getProperties().get(INSTRUMENTATION_KEY);
}

// Needn't be a UUID - can be a String or any other object that
// implements equals().
private static final Object AGENT_ARGS_KEY =
UUID.fromString("887b43f3-c742-4b87-978d-70d2db74e40e");

private static final Object INSTRUMENTATION_KEY =
UUID.fromString("214ac54a-60a5-417e-b3b8-772e80a16667");
}
136 changes: 91 additions & 45 deletions src/main/java/com/reider745/Main.java
Original file line number Diff line number Diff line change
@@ -1,70 +1,116 @@
package com.reider745;

import cn.nukkit.Server;
import cn.nukkit.network.Network;

import java.lang.instrument.Instrumentation;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

import com.reider745.api.hooks.JarEditor;
import com.reider745.event.DispenseBehaviorOverrides;
import com.reider745.hooks.*;
import com.reider745.hooks.bugfix.SaplingFix;
import com.reider745.network.CraftingTransactionPacket;
import com.reider745.network.InnerCorePacket;

public class Main {
public static InnerCoreServer innerCoreServer = new InnerCoreServer();
public static boolean block_not_vanilla = false;
import javassist.CannotCompileException;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.LineNumberAttribute;

public static class LoadingStages {
public static void preload(Server server) throws Exception {
innerCoreServer.preload(server);
}
public class Main {
public static final JarEditor loader = new JarEditor();

public static void afterload(Server server) {
innerCoreServer.afterload();
public static void add(String name) throws ClassNotFoundException, NotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
try {
loader.registerHooksInitializationForClass(name);
} catch (Exception e) {
System.out.print("registerHooksInitializationForClass(" + name + "): ");
e.printStackTrace();
}
}

public static void start(Server server) {
innerCoreServer.start();
/*
Не Загружать лишних классов, только патчи!
Иначе классы могут загрузится в не нужном ClassLoader, что может привести к не предсказуемым последствиям
*/
private static void printList(ClassLoader CL) {
Instrumentation inst = InstrumentHook.getInstrumentation();
for (Class<?> clazz: inst.getAllLoadedClasses()) {
System.err.println(clazz.getName());
}
}

public static void main(String[] args) throws Throwable {
// Отключает блокировку входа с ванильного майнкрафта, полезно при разработки фич не связанные с inner core
// Внимание ломает вход с inner core!
block_not_vanilla = Arrays.stream(args).anyMatch("--vanilla_not_block"::equals);
JarEditor loader = new JarEditor();

if(!block_not_vanilla) {
loader.registerHooksInitializationForClass(GlobalBlockPalette.class);
loader.registerHooksInitializationForClass(NetworkHooks.class);
loader.registerHooksInitializationForClass(PlayerHooks.class);
if (Arrays.stream(args).anyMatch("--snowfall-everywhere"::equals)) {
add("com.reider745.hooks.SnowfallEverywhere");
}

loader.registerHooksInitializationForClass(ServerHooks.class);
loader.registerHooksInitializationForClass(CraftingTransactionPacket.class);
loader.registerHooksInitializationForClass(RhinoOverrides.class);
//items and blocks
add("com.reider745.hooks.GlobalBlockPalette");
add("com.reider745.hooks.ItemUtils");
add("com.reider745.hooks.RuntimeItemsHooks");
add("com.reider745.hooks.BlocksHooks");
loader.addRebuildField("com.reider745.hooks.BlocksHooks", (ctClass, field) -> {
String name = field.getName();
if (name.equals("MAX_BLOCK_ID") || name.equals("usesFakeWater"))
field.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
});
add("com.reider745.event.DispenseBehaviorOverrides");
loader.addInit("com.reider745.event.DispenseBehaviorOverrides", ctClass -> {
try {

loader.registerHooksInitializationForClass(RuntimeItemsHooks.class);
loader.registerHooksInitializationForClass(BlocksHooks.class);
loader.registerHooksInitializationForClass(LevelHooks.class);
loader.registerHooksInitializationForClass(ItemUtils.class);
loader.registerHooksInitializationForClass(EntityOverrides.class);
loader.registerHooksInitializationForClass(DispenseBehaviorOverrides.class);
loader.registerHooksInitializationForClass(AndroidHooks.class);
CtMethod dispenseMethod = ctClass.getDeclaredMethod("dispense");
dispenseMethod.insertAt(dispenseMethod.getMethodInfo().getLineNumber(310),
"com.reider745.event.DispenseBehaviorOverrides.dispenseSlot = slot;");
} catch (NotFoundException | CannotCompileException e) {
e.printStackTrace();
System.out.println("Nukkit-MOT has been updated and overrides for `BlockDispenser.dispense` method are no longer available.");
}
});
add("com.reider745.network.CraftingTransactionPacket");

if (Arrays.stream(args).anyMatch("--snowfall-everywhere"::equals)) {
loader.registerHooksInitializationForClass(SnowfallEverywhere.class);
}
//entity
add("com.reider745.hooks.EntityOverrides");
add("com.reider745.hooks.PlayerHooks");

//Js engine
//add("com.reider745.jsengine.graalvm.hooks.ArgumentsPatch");
add("com.reider745.hooks.RhinoOverrides");
loader.addInit("com.reider745.jsengine.rhino.hooks.RhinoOverrides", ctClass -> {
try {
CtMethod reflectMethod = ctClass.getDeclaredMethod("reflect");
reflectMethod.insertAt(reflectMethod.getMethodInfo().getLineNumber(76),
"method = org.mozilla.javascript.MembersPatch.override(cl, method);");
} catch (NotFoundException | CannotCompileException e) {
e.printStackTrace();
System.out.println("Rhino has been updated and overrides for `JavaMembers.reflect` method are no longer available.");
}
});

//loader.registerHooksInitializationForClass(BiomesHooks.class);
loader.registerHooksInitializationForClass(GlobalBanList.class);
//technical
add("com.reider745.hooks.AndroidHooks");
add("com.reider745.hooks.GlobalBanList");
add("com.reider745.hooks.NetworkHooks");
add("com.reider745.hooks.LevelHooks");
loader.addRebuildField("com.reider745.hooks.LevelHooks", (ctClass, field) -> {
if (field.getName().equals("randomTickBlocks"))
field.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
});
add("com.reider745.hooks.ServerHooks");
/*loader.addInit("com.reider745.hooks.ServerHooks", server -> {
try {
var ctClass = loader.get("org.graalvm.polyglot.AbstractValue");
ctClass.getDeclaredField("context")
.setModifiers(Modifier.PUBLIC);
ctClass = loader.get("com.oracle.truffle.polyglot.PolyglotMap");
ctClass.getDeclaredField("languageContext")
.setModifiers(Modifier.PUBLIC);
} catch (Exception e) {
throw new RuntimeException(e);
}
});*/

// bug fix
loader.registerHooksInitializationForClass(SaplingFix.class);
//add("com.reider745.hooks.bugfix.DimensionsFix");


loader.init(Arrays.stream(args).anyMatch("--debug-hooks"::equals));
loader.run("cn.nukkit.Nukkit", args);
}
}
}
10 changes: 2 additions & 8 deletions src/main/java/com/reider745/api/hooks/HookClass.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package com.reider745.api.hooks;

import javassist.CtClass;
import javassist.CtField;

public interface HookClass {
default void rebuildField(CtClass ctClass, CtField field) {
}

default void init(CtClass ctClass) {
default void init() {
}
}
}
65 changes: 24 additions & 41 deletions src/main/java/com/reider745/api/hooks/HookClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ public class HookClassLoader extends ClassLoader {
private ProtectionDomain domain;
public boolean doDelegation;

public HookClassLoader() {
this((ClassPool) null);
}

public HookClassLoader(ClassPool classPool) {
this.doDelegation = true;
this.init(classPool);
}

public HookClassLoader(ClassLoader parent, ClassPool classPool) {
super(parent);
this.doDelegation = true;
Expand Down Expand Up @@ -71,32 +62,34 @@ public void addTranslator(ClassPool classPool, Translator translator) throws Exc
translator.start(classPool);
}

public void run(String[] args) throws Throwable {
if (args.length >= 1) {
this.run(args[0], (String[]) Arrays.copyOfRange(args, 1, args.length));
}
}

public void run(String className, String[] args) throws Throwable {
Class<?> c = this.loadClass(className);

try {
c.getDeclaredMethod("main", String[].class).invoke((Object) null, new Object[] { args });
} catch (InvocationTargetException var5) {
throw var5.getTargetException();
}
}

private static ArrayList<String> DENIED_FIND_CLASSES = new ArrayList<>();

static {
DENIED_FIND_CLASSES.add("jdk.internal.reflect.ConstructorAccessorImpl");
DENIED_FIND_CLASSES.add("jdk.internal.reflect.MethodAccessorImpl");

/*DENIED_FIND_CLASSES.add("com.reider745.api.hooks.HookClass");
DENIED_FIND_CLASSES.add("com.reider745.api.hooks.annotation.Hooks");
DENIED_FIND_CLASSES.add("com.reider745.api.hooks.annotation.Inject");
DENIED_FIND_CLASSES.add("com.reider745.api.hooks.HookController");
DENIED_FIND_CLASSES.add("com.reider745.api.hooks.TypeHook");
DENIED_FIND_CLASSES.add("javassist.CtClass");
DENIED_FIND_CLASSES.add("javassist.CtField");
DENIED_FIND_CLASSES.add("javassist.NotFoundException");
DENIED_FIND_CLASSES.add("javassist.CannotCompileException");
DENIED_FIND_CLASSES.add("javassist.CtMethod");
DENIED_FIND_CLASSES.add("javassist.bytecode.MethodInfo");
DENIED_FIND_CLASSES.add("javassist.bytecode.MethodInfo");
DENIED_FIND_CLASSES.add("com.reider745.api.hooks.JarEditor");*/
}

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
name = name.intern();
synchronized (name) {
if(name.startsWith("com.reider745.api.hooks") || name.startsWith("javassist.") || name.startsWith("jdk.") || name.startsWith("java.")) {
return getParent().loadClass(name);
}

Class<?> c = this.findLoadedClass(name);
if (c == null) {
c = this.loadClassByDelegation(name);
Expand All @@ -114,7 +107,12 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
}
}

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if(name.startsWith("com.reider745.api.hooks") || name.startsWith("javassist.") || name.startsWith("jdk.") || name.startsWith("java.")) {
return getParent().loadClass(name);
}

byte[] bytecode;

try {
Expand Down Expand Up @@ -206,19 +204,4 @@ protected Class<?> delegateToParent(String classname) throws ClassNotFoundExcept
ClassLoader cl = this.getParent();
return cl != null ? cl.loadClass(classname) : this.findSystemClass(classname);
}

public static String PATH_TO_ASSETS = null;

@Nullable
@Override
public URL getResource(String name) {
if (PATH_TO_ASSETS != null) {
try {
return new URL("file:///" + PATH_TO_ASSETS + "/" + name);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
return super.getResource(name);
}
}
}
Loading

0 comments on commit 5c5bd62

Please sign in to comment.