You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
486 lines
27 KiB
486 lines
27 KiB
--- ../src-base/minecraft/org/bukkit/plugin/java/PluginClassLoader.java |
|
+++ ../src-work/minecraft/org/bukkit/plugin/java/PluginClassLoader.java |
|
@@ -1,5 +1,23 @@ |
|
package org.bukkit.plugin.java; |
|
|
|
+// Cauldron start |
|
+import net.md_5.specialsource.provider.ClassLoaderProvider; |
|
+import net.md_5.specialsource.transformer.MavenShade; |
|
+//import org.bouncycastle.util.io.Streams; |
|
+import net.md_5.specialsource.*; |
|
+import net.md_5.specialsource.repo.*; |
|
+import net.minecraft.server.MinecraftServer; |
|
+import net.minecraftforge.cauldron.configuration.CauldronConfig; |
|
+import net.minecraftforge.cauldron.CauldronUtils; |
|
+ |
|
+import org.bukkit.plugin.PluginDescriptionFile; |
|
+import java.io.*; |
|
+import java.net.JarURLConnection; |
|
+import java.security.CodeSigner; |
|
+import java.security.CodeSource; |
|
+import java.util.concurrent.*; |
|
+// Cauldron end |
|
+ |
|
import java.io.File; |
|
import java.net.MalformedURLException; |
|
import java.net.URL; |
|
@@ -15,16 +33,40 @@ |
|
/** |
|
* A ClassLoader for plugins, to allow shared classes across multiple plugins |
|
*/ |
|
-final class PluginClassLoader extends URLClassLoader { |
|
+public class PluginClassLoader extends URLClassLoader { |
|
private final JavaPluginLoader loader; |
|
- private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>(); |
|
+ private final ConcurrentMap<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>(); // Cauldron - Threadsafe classloading |
|
private final PluginDescriptionFile description; |
|
private final File dataFolder; |
|
private final File file; |
|
- final JavaPlugin plugin; |
|
+ JavaPlugin plugin; // Cauldron - remove final |
|
private JavaPlugin pluginInit; |
|
private IllegalStateException pluginState; |
|
+ // Cauldron start |
|
+ private JarRemapper remapper; // class remapper for this plugin, or null |
|
+ private RemapperProcessor remapperProcessor; // secondary; for inheritance & remapping reflection |
|
+ private boolean debug; // classloader debugging |
|
+ private int remapFlags = -1; |
|
|
|
+ private static ConcurrentMap<Integer,JarMapping> jarMappings = new ConcurrentHashMap<Integer, JarMapping>(); |
|
+ private static final int F_GLOBAL_INHERIT = 1 << 1; |
|
+ private static final int F_REMAP_OBCPRE = 1 << 2; |
|
+ private static final int F_REMAP_NMS152 = 1 << 3; |
|
+ private static final int F_REMAP_NMS164 = 1 << 4; |
|
+ private static final int F_REMAP_NMS172 = 1 << 5; |
|
+ private static final int F_REMAP_NMS179 = 1 << 6; |
|
+ private static final int F_REMAP_NMS1710 = 1 << 7; |
|
+ private static final int F_REMAP_OBC152 = 1 << 8; |
|
+ private static final int F_REMAP_OBC164 = 1 << 9; |
|
+ private static final int F_REMAP_OBC172 = 1 << 10; |
|
+ private static final int F_REMAP_OBC179 = 1 << 11; |
|
+ private static final int F_REMAP_OBC1710 = 1 << 12; |
|
+ private static final int F_REMAP_NMSPRE_MASK= 0xffff0000; // "unversioned" NMS plugin version |
|
+ |
|
+ // This trick bypasses Maven Shade's package rewriting when using String literals [same trick in jline] |
|
+ private static final String org_bukkit_craftbukkit = new String(new char[] {'o','r','g','/','b','u','k','k','i','t','/','c','r','a','f','t','b','u','k','k','i','t'}); |
|
+ // Cauldron end |
|
+ |
|
PluginClassLoader(final JavaPluginLoader loader, final ClassLoader parent, final PluginDescriptionFile description, final File dataFolder, final File file) throws InvalidPluginException, MalformedURLException { |
|
super(new URL[] {file.toURI().toURL()}, parent); |
|
Validate.notNull(loader, "Loader cannot be null"); |
|
@@ -34,6 +76,113 @@ |
|
this.dataFolder = dataFolder; |
|
this.file = file; |
|
|
|
+ // Cauldron start |
|
+ |
|
+ String pluginName = this.description.getName(); |
|
+ |
|
+ // configure default remapper settings |
|
+ boolean useCustomClassLoader = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.custom-class-loader", true); |
|
+ debug = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.debug", false); |
|
+ boolean remapNMS1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_7_R4", true); |
|
+ boolean remapNMS179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_7_R3", true); |
|
+ boolean remapNMS172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_7_R1", true); |
|
+ boolean remapNMS164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_6_R3", true); |
|
+ boolean remapNMS152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_5_R3", true); |
|
+ String remapNMSPre = MinecraftServer.getServer().cauldronConfig.getString("plugin-settings.default.remap-nms-pre", "false"); |
|
+ boolean remapOBC1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_7_R4", true); |
|
+ boolean remapOBC179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_7_R3", true); |
|
+ boolean remapOBC172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_7_R1", true); |
|
+ boolean remapOBC164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_6_R3", true); |
|
+ boolean remapOBC152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_5_R3", true); |
|
+ boolean remapOBCPre = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-pre", false); |
|
+ boolean globalInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.global-inheritance", true); |
|
+ boolean pluginInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.plugin-inheritance", true); |
|
+ boolean reflectFields = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-reflect-field", true); |
|
+ boolean reflectClass = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-reflect-class", true); |
|
+ boolean allowFuture = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-allow-future", false); |
|
+ |
|
+ // plugin-specific overrides |
|
+ useCustomClassLoader = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".custom-class-loader", useCustomClassLoader, false); |
|
+ debug = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".debug", debug, false); |
|
+ remapNMS1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_7_R4", remapNMS1710, false); |
|
+ remapNMS179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_7_R3", remapNMS179, false); |
|
+ remapNMS172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_7_R1", remapNMS172, false); |
|
+ remapNMS164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_6_R3", remapNMS164, false); |
|
+ remapNMS152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_5_R3", remapNMS152, false); |
|
+ remapNMSPre = MinecraftServer.getServer().cauldronConfig.getString("plugin-settings."+pluginName+".remap-nms-pre", remapNMSPre, false); |
|
+ remapOBC1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_7_R4", remapOBC1710, false); |
|
+ remapOBC179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_7_R3", remapOBC179, false); |
|
+ remapOBC172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_7_R1", remapOBC172, false); |
|
+ remapOBC164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_6_R3", remapOBC164, false); |
|
+ remapOBC152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_5_R3", remapOBC152, false); |
|
+ remapOBCPre = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-pre", remapOBCPre, false); |
|
+ globalInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".global-inheritance", globalInherit, false); |
|
+ pluginInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".plugin-inheritance", pluginInherit, false); |
|
+ reflectFields = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-reflect-field", reflectFields, false); |
|
+ reflectClass = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-reflect-class", reflectClass, false); |
|
+ allowFuture = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-allow-future", allowFuture, false); |
|
+ |
|
+ if (debug) { |
|
+ System.out.println("PluginClassLoader debugging enabled for "+pluginName); |
|
+ } |
|
+ |
|
+ if (!useCustomClassLoader) { |
|
+ remapper = null; |
|
+ return; |
|
+ } |
|
+ |
|
+ int flags = 0; |
|
+ if (remapNMS1710) flags |= F_REMAP_NMS1710; |
|
+ if (remapNMS179) flags |= F_REMAP_NMS179; |
|
+ if (remapNMS172) flags |= F_REMAP_NMS172; |
|
+ if (remapNMS164) flags |= F_REMAP_NMS164; |
|
+ if (remapNMS152) flags |= F_REMAP_NMS152; |
|
+ if (!remapNMSPre.equals("false")) { |
|
+ if (remapNMSPre.equals("1.7.10")) flags |= 0x17100000; |
|
+ else if (remapNMSPre.equals("1.7.9")) flags |= 0x01790000; |
|
+ else if (remapNMSPre.equals("1.7.2")) flags |= 0x01720000; |
|
+ else if (remapNMSPre.equals("1.6.4")) flags |= 0x01640000; |
|
+ else if (remapNMSPre.equals("1.5.2")) flags |= 0x01520000; |
|
+ else { |
|
+ System.out.println("Unsupported nms-remap-pre version '"+remapNMSPre+"', disabling"); |
|
+ } |
|
+ } |
|
+ if (remapOBC1710) flags |= F_REMAP_OBC1710; |
|
+ if (remapOBC179) flags |= F_REMAP_OBC179; |
|
+ if (remapOBC172) flags |= F_REMAP_OBC172; |
|
+ if (remapOBC164) flags |= F_REMAP_OBC164; |
|
+ if (remapOBC152) flags |= F_REMAP_OBC152; |
|
+ if (remapOBCPre) flags |= F_REMAP_OBCPRE; |
|
+ if (globalInherit) flags |= F_GLOBAL_INHERIT; |
|
+ |
|
+ remapFlags = flags; // used in findClass0 |
|
+ JarMapping jarMapping = getJarMapping(flags); |
|
+ |
|
+ // Load inheritance map |
|
+ if ((flags & F_GLOBAL_INHERIT) != 0) { |
|
+ if (debug) { |
|
+ System.out.println("Enabling global inheritance remapping"); |
|
+ //ClassLoaderProvider.verbose = debug; // TODO: changed in https://github.com/md-5/SpecialSource/commit/132584eda4f0860c9d14f4c142e684a027a128b8#L3L48 |
|
+ } |
|
+ jarMapping.setInheritanceMap(loader.getGlobalInheritanceMap()); |
|
+ jarMapping.setFallbackInheritanceProvider(new ClassLoaderProvider(this)); |
|
+ } |
|
+ |
|
+ remapper = new kcauldron.KCauldronRemapper(jarMapping); |
|
+ |
|
+ if (pluginInherit || reflectFields || reflectClass) { |
|
+ remapperProcessor = new RemapperProcessor( |
|
+ pluginInherit ? loader.getGlobalInheritanceMap() : null, |
|
+ (reflectFields || reflectClass) ? jarMapping : null); |
|
+ |
|
+ remapperProcessor.setRemapReflectField(reflectFields); |
|
+ remapperProcessor.setRemapReflectClass(reflectClass); |
|
+ remapperProcessor.debug = debug; |
|
+ } else { |
|
+ remapperProcessor = null; |
|
+ } |
|
+ // Cauldron end |
|
+ |
|
try { |
|
Class<?> jarClass; |
|
try { |
|
@@ -58,34 +207,290 @@ |
|
} |
|
|
|
@Override |
|
- protected Class<?> findClass(String name) throws ClassNotFoundException { |
|
+ public Class<?> findClass(String name) throws ClassNotFoundException { // Cauldron - public access for plugins to support CB NMS -> MCP class remap |
|
return findClass(name, true); |
|
} |
|
|
|
- Class<?> findClass(String name, boolean checkGlobal) throws ClassNotFoundException { |
|
- if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) { |
|
- throw new ClassNotFoundException(name); |
|
+ // Cauldron start |
|
+ /** |
|
+ * Get the "native" obfuscation version, from our Maven shading version. |
|
+ */ |
|
+ public static String getNativeVersion() { |
|
+ // see https://github.com/mbax/VanishNoPacket/blob/master/src/main/java/org/kitteh/vanish/compat/NMSManager.java |
|
+ if (CauldronUtils.deobfuscatedEnvironment()) return "v1_7_R4"; // support plugins in deobf environment |
|
+ final String packageName = org.bukkit.craftbukkit.CraftServer.class.getPackage().getName(); |
|
+ return packageName.substring(packageName.lastIndexOf('.') + 1); |
|
+ } |
|
+ |
|
+ /** |
|
+ * Load NMS mappings from CraftBukkit mc-dev to repackaged srgnames for FML runtime deobf |
|
+ * |
|
+ * @param jarMapping An existing JarMappings instance to load into |
|
+ * @param obfVersion CraftBukkit version with internal obfuscation counter identifier |
|
+ * >=1.4.7 this is the major version + R#. v1_4_R1=1.4.7, v1_5_R1=1.5, v1_5_R2=1.5.1.. |
|
+ * For older versions (including pre-safeguard) it is the full Minecraft version number |
|
+ * @throws IOException |
|
+ */ |
|
+ private void loadNmsMappings(JarMapping jarMapping, String obfVersion) throws IOException { |
|
+ Map<String, String> relocations = new HashMap<String, String>(); |
|
+ // mc-dev jar to CB, apply version shading (aka plugin safeguard) |
|
+ relocations.put("net.minecraft.server", "net.minecraft.server." + obfVersion); |
|
+ |
|
+ // support for running 1.7.10 plugins in Cauldron dev |
|
+ if (CauldronUtils.deobfuscatedEnvironment() && obfVersion.equals("v1_7_R4")) |
|
+ { |
|
+ jarMapping.loadMappings( |
|
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/cb2pkgmcp.srg"))), |
|
+ new MavenShade(relocations), |
|
+ null, false); |
|
+ |
|
+ jarMapping.loadMappings( |
|
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/obf2pkgmcp.srg"))), |
|
+ null, // no version relocation for obf |
|
+ null, false); |
|
+ // resolve naming conflict in FML/CB |
|
+ jarMapping.methods.put("net/minecraft/server/"+obfVersion+"/PlayerConnection/getPlayer ()Lorg/bukkit/craftbukkit/entity/CraftPlayer;", "getPlayerB"); |
|
} |
|
- Class<?> result = classes.get(name); |
|
+ else |
|
+ { |
|
+ jarMapping.loadMappings( |
|
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/cb2numpkg.srg"))), |
|
+ new MavenShade(relocations), |
|
+ null, false); |
|
|
|
- if (result == null) { |
|
- if (checkGlobal) { |
|
- result = loader.getClassByName(name); |
|
+ if (obfVersion.equals("v1_7_R4")) { |
|
+ jarMapping.loadMappings( |
|
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/obf2numpkg.srg"))), |
|
+ null, // no version relocation for obf |
|
+ null, false); |
|
} |
|
|
|
+ // resolve naming conflict in FML/CB |
|
+ jarMapping.methods.put("net/minecraft/server/"+obfVersion+"/PlayerConnection/getPlayer ()Lorg/bukkit/craftbukkit/"+getNativeVersion()+"/entity/CraftPlayer;", "getPlayerB"); |
|
+ } |
|
+ // remap bouncycastle to Forge's included copy, not the vanilla obfuscated copy (not in Cauldron), see #133 |
|
+ //jarMapping.packages.put("net/minecraft/"+obfVersion+"/org/bouncycastle", "org/bouncycastle"); No longer needed |
|
+ } |
|
+ |
|
+ private JarMapping getJarMapping(int flags) { |
|
+ JarMapping jarMapping = jarMappings.get(flags); |
|
+ |
|
+ if (jarMapping != null) { |
|
+ if (debug) { |
|
+ System.out.println("Mapping reused for "+Integer.toHexString(flags)); |
|
+ } |
|
+ return jarMapping; |
|
+ } |
|
+ |
|
+ jarMapping = new JarMapping(); |
|
+ try { |
|
+ |
|
+ // Guava 10 is part of the Bukkit API, so plugins can use it, but FML includes Guava 15 |
|
+ // To resolve this conflict, remap plugin usages to Guava 10 in a separate package |
|
+ // Most plugins should keep this enabled, unless they want a newer Guava |
|
+ jarMapping.packages.put("com/google/common", "guava10/com/google/common"); |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit + "/libs/com/google/gson", "com/google/gson"); // Handle Gson being in a "normal" place |
|
+ // Bukkit moves these packages to nms while we keep them in root so we must relocate them for plugins that rely on them |
|
+ jarMapping.packages.put("net/minecraft/util/io", "io"); |
|
+ jarMapping.packages.put("net/minecraft/util/com", "com"); |
|
+ jarMapping.packages.put("net/minecraft/util/gnu", "gnu"); |
|
+ jarMapping.packages.put("net/minecraft/util/org", "org"); |
|
+ |
|
+ if ((flags & F_REMAP_NMS1710) != 0) { |
|
+ loadNmsMappings(jarMapping, "v1_7_R4"); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_NMS179) != 0) { |
|
+ loadNmsMappings(jarMapping, "v1_7_R3"); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_NMS172) != 0) { |
|
+ loadNmsMappings(jarMapping, "v1_7_R1"); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_NMS164) != 0) { |
|
+ loadNmsMappings(jarMapping, "v1_6_R3"); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_NMS152) != 0) { |
|
+ loadNmsMappings(jarMapping, "v1_5_R3"); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_OBC1710) != 0) { |
|
+ if (CauldronUtils.deobfuscatedEnvironment()) |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R4", org_bukkit_craftbukkit); |
|
+ else jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R4", org_bukkit_craftbukkit+"/"+getNativeVersion()); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_OBC179) != 0) { |
|
+ if (CauldronUtils.deobfuscatedEnvironment()) |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R3", org_bukkit_craftbukkit); |
|
+ else jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R3", org_bukkit_craftbukkit+"/"+getNativeVersion()); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_OBC172) != 0) { |
|
+ if (CauldronUtils.deobfuscatedEnvironment()) |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R1", org_bukkit_craftbukkit+"/"+getNativeVersion()); |
|
+ else jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R1", org_bukkit_craftbukkit+"/"+getNativeVersion()); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_OBC164) != 0) { |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_6_R3", org_bukkit_craftbukkit+"/"+getNativeVersion()); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_OBC152) != 0) { |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_5_R3", org_bukkit_craftbukkit+"/"+getNativeVersion()); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_OBCPRE) != 0) { |
|
+ // enabling unversioned obc not currently compatible with versioned obc plugins (overmapped) - |
|
+ // admins should enable remap-obc-pre on a per-plugin basis, as needed |
|
+ // then map unversioned to current version |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/libs/org/objectweb/asm", "org/objectweb/asm"); // ? |
|
+ jarMapping.packages.put(org_bukkit_craftbukkit, org_bukkit_craftbukkit+"/"+getNativeVersion()); |
|
+ } |
|
+ |
|
+ if ((flags & F_REMAP_NMSPRE_MASK) != 0) { |
|
+ String obfVersion; |
|
+ switch (flags & F_REMAP_NMSPRE_MASK) |
|
+ { |
|
+ case 0x17100000: obfVersion = "v1_7_R4"; break; |
|
+ case 0x01790000: obfVersion = "v1_7_R3"; break; |
|
+ case 0x01720000: obfVersion = "v1_7_R1"; break; |
|
+ case 0x01640000: obfVersion = "v1_6_R3"; break; |
|
+ case 0x01510000: obfVersion = "v1_5_R2"; break; |
|
+ default: throw new IllegalArgumentException("Invalid unversioned mapping flags: "+Integer.toHexString(flags & F_REMAP_NMSPRE_MASK)+" in "+Integer.toHexString(flags)); |
|
+ } |
|
+ |
|
+ jarMapping.loadMappings( |
|
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/" + obfVersion + "/cb2numpkg.srg"))), |
|
+ null, // no version relocation! |
|
+ null, false); |
|
+ } |
|
+ |
|
+ System.out.println("Mapping loaded "+jarMapping.packages.size()+" packages, "+jarMapping.classes.size()+" classes, "+jarMapping.fields.size()+" fields, "+jarMapping.methods.size()+" methods, flags "+Integer.toHexString(flags)); |
|
+ |
|
+ JarMapping currentJarMapping = jarMappings.putIfAbsent(flags, jarMapping); |
|
+ return currentJarMapping == null ? jarMapping : currentJarMapping; |
|
+ } catch (IOException ex) { |
|
+ ex.printStackTrace(); |
|
+ throw new RuntimeException(ex); |
|
+ } |
|
+ } |
|
+ |
|
+ Class<?> findClass(String name, boolean checkGlobal) throws ClassNotFoundException { |
|
+ // Cauldron start - remap any calls for classes with packaged nms version |
|
+ if (name.startsWith("net.minecraft.")) |
|
+ { |
|
+ JarMapping jarMapping = this.getJarMapping(remapFlags); // grab from SpecialSource |
|
+ String remappedClass = jarMapping.classes.get(name.replaceAll("\\.", "\\/")); // get remapped pkgmcp class name |
|
+ Class<?> clazz = ((net.minecraft.launchwrapper.LaunchClassLoader)MinecraftServer.getServer().getClass().getClassLoader()).findClass(remappedClass); |
|
+ return clazz; |
|
+ } |
|
+ if (name.startsWith("org.bukkit.")) { |
|
+ if (debug) { |
|
+ System.out.println("Unexpected plugin findClass on OBC/NMS: name="+name+", checkGlobal="+checkGlobal+"; returning not found"); |
|
+ } |
|
+ throw new ClassNotFoundException(name); |
|
+ } |
|
+ // custom loader, if enabled, threadsafety |
|
+ synchronized (name.intern()) { |
|
+ Class<?> result = classes.get(name); |
|
+ |
|
if (result == null) { |
|
- result = super.findClass(name); |
|
+ if (checkGlobal) { |
|
+ result = loader.getClassByName(name); // Don't warn on deprecation, but maintain overridability |
|
+ } |
|
|
|
+ if (result == null) { |
|
+ if (remapper == null) { |
|
+ result = super.findClass(name); |
|
+ } else { |
|
+ result = remappedFindClass(name); |
|
+ } |
|
+ |
|
+ if (result != null) { |
|
+ loader.setClass(name, result); |
|
+ } |
|
+ } |
|
if (result != null) { |
|
- loader.setClass(name, result); |
|
+ Class<?> old = classes.putIfAbsent(name, result); |
|
+ if (old != null && old != result) { |
|
+ System.err.println("Defined class " + name + " twice as different classes, " + result + " and " + old); |
|
+ result = old; |
|
+ } |
|
} |
|
} |
|
|
|
- classes.put(name, result); |
|
+ return result; |
|
} |
|
+ // Cauldron end |
|
+ } |
|
+ private Class<?> remappedFindClass(String name) throws ClassNotFoundException { |
|
+ Class<?> result = null; |
|
|
|
+ try { |
|
+ // Load the resource to the name |
|
+ String path = name.replace('.', '/').concat(".class"); |
|
+ URL url = this.findResource(path); |
|
+ if (url != null) { |
|
+ InputStream stream = url.openStream(); |
|
+ if (stream != null) { |
|
+ byte[] bytecode = null; |
|
+ |
|
+ // Reflection remap and inheritance extract |
|
+ if (remapperProcessor != null) { |
|
+ // add to inheritance map |
|
+ bytecode = remapperProcessor.process(stream); |
|
+ if (bytecode == null) stream = url.openStream(); |
|
+ } |
|
+ |
|
+ /*if (bytecode == null) { |
|
+ bytecode = Streams.readAll(stream); |
|
+ }*/ |
|
+ |
|
+ // Remap the classes |
|
+ byte[] remappedBytecode = remapper.remapClassFile(bytecode, RuntimeRepo.getInstance()); |
|
+ |
|
+ if (debug) { |
|
+ File file = new File("remapped-plugin-classes/"+name+".class"); |
|
+ file.getParentFile().mkdirs(); |
|
+ try { |
|
+ FileOutputStream fileOutputStream = new FileOutputStream(file); |
|
+ fileOutputStream.write(remappedBytecode); |
|
+ fileOutputStream.close(); |
|
+ } catch (IOException ex) { |
|
+ ex.printStackTrace(); |
|
+ } |
|
+ } |
|
+ |
|
+ // Define (create) the class using the modified byte code |
|
+ // The top-child class loader is used for this to prevent access violations |
|
+ // Set the codesource to the jar, not within the jar, for compatibility with |
|
+ // plugins that do new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI())) |
|
+ // instead of using getResourceAsStream - see https://github.com/MinecraftPortCentral/Cauldron-Plus/issues/75 |
|
+ JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); // parses only |
|
+ URL jarURL = jarURLConnection.getJarFileURL(); |
|
+ CodeSource codeSource = new CodeSource(jarURL, new CodeSigner[0]); |
|
+ |
|
+ result = this.defineClass(name, remappedBytecode, 0, remappedBytecode.length, codeSource); |
|
+ if (result != null) { |
|
+ // Resolve it - sets the class loader of the class |
|
+ this.resolveClass(result); |
|
+ } |
|
+ } |
|
+ } |
|
+ } catch (Throwable t) { |
|
+ if (debug) { |
|
+ System.out.println("remappedFindClass("+name+") exception: "+t); |
|
+ t.printStackTrace(); |
|
+ } |
|
+ throw new ClassNotFoundException("Failed to remap class "+name, t); |
|
+ } |
|
+ |
|
return result; |
|
} |
|
+ // Cauldron end |
|
|
|
Set<String> getClasses() { |
|
return classes.keySet();
|
|
|