Initial support update for Bukkit4fabric mod (Fabric)
This commit is contained in:
1 parent
fb0c2663f6
commit
23eaed2e49
3 files changed
+177
-9
No files matched your search
@@ -84,6 +84,7 @@ public class CommonBootstrap {
|
||||
// Always Spigot server
|
||||
CommonServer server = new SpigotServer();
|
||||
server.init();
|
||||
initServerResolvers(server);
|
||||
server.postInit();
|
||||
_commonServer = server;
|
||||
} else {
|
||||
@@ -93,6 +94,7 @@ public class CommonBootstrap {
|
||||
servers.add(new MagmaServer());
|
||||
servers.add(new ArclightServer());
|
||||
servers.add(new CatServerServer());
|
||||
servers.add(new Bukkit4FabricServer());
|
||||
servers.add(new PurpurServer());
|
||||
servers.add(new SpigotServer());
|
||||
servers.add(new SportBukkitServer());
|
||||
@@ -103,6 +105,7 @@ public class CommonBootstrap {
|
||||
for (CommonServer server : servers) {
|
||||
try {
|
||||
if (server.init()) {
|
||||
initServerResolvers(server);
|
||||
server.postInit();
|
||||
_commonServer = server;
|
||||
break;
|
||||
@@ -212,12 +215,11 @@ public class CommonBootstrap {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the type, field and method resolvers for a server, so that such information
|
||||
* can be obtained at runtime.
|
||||
* Registers any resolvers used by the current server handler
|
||||
*
|
||||
* @param server
|
||||
*/
|
||||
private static void initResolvers(CommonServer server) {
|
||||
private static void initServerResolvers(CommonServer server) {
|
||||
// Register server to handle field, method and class resolving
|
||||
if (server instanceof ClassPathResolver) {
|
||||
Resolver.registerClassResolver((ClassPathResolver) server);
|
||||
@@ -234,7 +236,15 @@ public class CommonBootstrap {
|
||||
if (server instanceof CompiledMethodNameResolver) {
|
||||
Resolver.registerCompiledMethodResolver((CompiledMethodNameResolver) server);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the type, field and method resolvers for a server, so that such information
|
||||
* can be obtained at runtime.
|
||||
*
|
||||
* @param server
|
||||
*/
|
||||
private static void initResolvers(CommonServer server) {
|
||||
// Enum Gamemode not available in package space on <= MC 1.9; we must proxy it
|
||||
if (Resolver.loadClass("net.minecraft.server.EnumGamemode", false) == null) {
|
||||
final String eg_path = Resolver.resolveClassPath("net.minecraft.server.EnumGamemode");
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.bergerkiller.bukkit.common.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import com.bergerkiller.mountiplex.reflection.declarations.Template;
|
||||
import com.bergerkiller.mountiplex.reflection.resolver.FieldNameResolver;
|
||||
import com.bergerkiller.mountiplex.reflection.resolver.MethodNameResolver;
|
||||
|
||||
/**
|
||||
* Fabric server support, that uses the Bukkit4Fabric mod for paper/spigot/bukkit support.<br>
|
||||
* <br>
|
||||
* https://github.com/BukkitFabric/bukkit4fabric/
|
||||
*/
|
||||
public class Bukkit4FabricServer extends SpigotServer implements FieldNameResolver, MethodNameResolver {
|
||||
private ReflectionRemapperClass reflectionRemapper = null;
|
||||
|
||||
@Override
|
||||
public boolean init() {
|
||||
if (!super.init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check Bukkit4fabric mod exists, we expect this Class to exist
|
||||
try {
|
||||
Class.forName("com.javazilla.bukkitfabric.BukkitFabricMod");
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure RemappingUtils exists, this initializes the RemappingUtilsHandle using the above initialized declaration
|
||||
reflectionRemapper = Template.Class.create(ReflectionRemapperClass.class);
|
||||
if (!reflectionRemapper.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Force initialization to avoid late catastrophic failing
|
||||
reflectionRemapper.forceInitialization();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerName() {
|
||||
return "Fabric (Bukkit4fabric)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getLoadableWorlds() {
|
||||
return ForgeSupport.getLoadableWorlds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadableWorld(String worldName) {
|
||||
return ForgeSupport.isLoadableWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWorldRegionFolder(String worldName) {
|
||||
return ForgeSupport.getWorldRegionFolder(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWorldFolder(String worldName) {
|
||||
return ForgeSupport.getWorldFolder(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveClassPath(String path) {
|
||||
// Replaces path with proper net.minecraft.server.v1_1_1 path
|
||||
path = super.resolveClassPath(path);
|
||||
|
||||
// Ask Magma what the actual class name is on Forge
|
||||
path = reflectionRemapper.mapClassName(path);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canLoadClassPath(String classPath) {
|
||||
// The .class data at this path contains obfuscated type information
|
||||
// These obfuscated names are deobufscated at runtime
|
||||
// This difference causes compiler errors at runtime, so instead of
|
||||
// loading the .class files, inspect the signatures using reflection.
|
||||
if (classPath.startsWith("org.bukkit.craftbukkit.")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveMethodName(Class<?> type, String methodName, Class<?>[] params) {
|
||||
try {
|
||||
//TODO: Params???
|
||||
Method method = reflectionRemapper.getDeclaredMethodByName(type, methodName);
|
||||
if (method != null) {
|
||||
return method.getName();
|
||||
}
|
||||
} catch (Throwable t) {}
|
||||
|
||||
return methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveFieldName(Class<?> type, String fieldName) {
|
||||
try {
|
||||
//TODO: Params???
|
||||
Field field = reflectionRemapper.getDeclaredFieldByName(type, fieldName);
|
||||
if (field != null) {
|
||||
return field.getName();
|
||||
}
|
||||
} catch (Throwable t) {}
|
||||
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVariables(Map<String, String> variables) {
|
||||
super.addVariables(variables);
|
||||
variables.put("fabric", "bukkit4fabric");
|
||||
variables.put("forge_nms_obfuscated", "true");
|
||||
}
|
||||
|
||||
@Template.Optional
|
||||
@Template.InstanceType("com.javazilla.bukkitfabric.nms.ReflectionRemapper")
|
||||
public static abstract class ReflectionRemapperClass extends Template.Class<Template.Handle> {
|
||||
|
||||
@Template.Generated("public static String mapClassName(String className)")
|
||||
public abstract String mapClassName(String className);
|
||||
|
||||
@Template.Generated("public static java.lang.reflect.Method getDeclaredMethodByName(Class<?> calling, String f)")
|
||||
public abstract Method getDeclaredMethodByName(Class<?> type, String name);
|
||||
|
||||
@Template.Generated("public static java.lang.reflect.Field getDeclaredFieldByName(Class<?> calling, String f)")
|
||||
public abstract Field getDeclaredFieldByName(Class<?> type, String fieldName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,11 @@ import com.bergerkiller.bukkit.common.Logging;
|
||||
import com.bergerkiller.bukkit.common.utils.StringUtil;
|
||||
import com.bergerkiller.mountiplex.reflection.ClassTemplate;
|
||||
import com.bergerkiller.mountiplex.reflection.resolver.ClassPathResolver;
|
||||
import com.bergerkiller.mountiplex.reflection.resolver.Resolver;
|
||||
import com.bergerkiller.mountiplex.reflection.util.asm.ASMUtil;
|
||||
import com.bergerkiller.mountiplex.reflection.util.asm.MPLType;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -73,18 +76,18 @@ public class CraftBukkitServer extends CommonServerBase implements ClassPathReso
|
||||
public void postInit() {
|
||||
try {
|
||||
// Find getVersion() method using reflection
|
||||
Class<?> minecraftServerType = Class.forName(NMS_ROOT_VERSIONED + ".MinecraftServer", false, this.getClass().getClassLoader());
|
||||
java.lang.reflect.Method getVersionMethod = minecraftServerType.getMethod("getVersion");
|
||||
Class<?> minecraftServerType = loadClass(NMS_ROOT_VERSIONED + ".MinecraftServer");
|
||||
java.lang.reflect.Method getVersionMethod = getDeclaredMethod(minecraftServerType, "getVersion");
|
||||
|
||||
// This is easy when the server is already initialized
|
||||
if (Bukkit.getServer() != null) {
|
||||
// Obtain MinecraftServer instance from server
|
||||
Class<?> server = Class.forName(CB_ROOT_VERSIONED + ".CraftServer");
|
||||
Class<?> server = loadClass(CB_ROOT_VERSIONED + ".CraftServer");
|
||||
|
||||
// Standard CraftServer::getServer()
|
||||
Object minecraftServerInstance;
|
||||
try {
|
||||
java.lang.reflect.Method getServerMethod = server.getDeclaredMethod("getServer");
|
||||
java.lang.reflect.Method getServerMethod = getDeclaredMethod(server, "getServer");
|
||||
minecraftServerInstance = getServerMethod.invoke(Bukkit.getServer());
|
||||
MC_VERSION = (String) getVersionMethod.invoke(minecraftServerInstance);
|
||||
return;
|
||||
@@ -99,10 +102,10 @@ public class CraftBukkitServer extends CommonServerBase implements ClassPathReso
|
||||
try {
|
||||
Object gameVersion;
|
||||
try {
|
||||
Class<?> minecraftVersionClass = Class.forName(NMS_ROOT_VERSIONED + ".MinecraftVersion");
|
||||
Class<?> minecraftVersionClass = loadClass(NMS_ROOT_VERSIONED + ".MinecraftVersion");
|
||||
gameVersion = minecraftVersionClass.getDeclaredMethod("a").invoke(null);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException ex) {
|
||||
Class<?> sharedConstantsClass = Class.forName(NMS_ROOT_VERSIONED + ".SharedConstants");
|
||||
Class<?> sharedConstantsClass = loadClass(NMS_ROOT_VERSIONED + ".SharedConstants");
|
||||
gameVersion = sharedConstantsClass.getDeclaredMethod("a").invoke(null);
|
||||
Logging.LOGGER.warning("Failed to find Minecraft Version using MinecraftVersion.class, used SharedConstants instead");
|
||||
}
|
||||
@@ -143,6 +146,19 @@ public class CraftBukkitServer extends CommonServerBase implements ClassPathReso
|
||||
return path;
|
||||
}
|
||||
|
||||
private Method getDeclaredMethod(Class<?> declaringClass, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
methodName = Resolver.resolveMethodName(declaringClass, methodName, parameterTypes);
|
||||
return MPLType.getDeclaredMethod(declaringClass, methodName, parameterTypes);
|
||||
}
|
||||
|
||||
private Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
Class<?> type = Resolver.loadClass(name, false);
|
||||
if (type == null) {
|
||||
throw new ClassNotFoundException("Failed to load class " + name);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinecraftVersion() {
|
||||
return MC_VERSION;
|
||||
|
||||
Reference in new issue
Block a user