From b6c6639dc6fdc62cd04cd5ad31aba4c014e84dfd Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Mon, 25 Dec 2023 16:35:18 -0300 Subject: [PATCH 1/9] Added /crucible findChunks command --- .../io/github/crucible/CrucibleCommand.java | 97 +++++++++++++------ 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/src/main/java/io/github/crucible/CrucibleCommand.java b/src/main/java/io/github/crucible/CrucibleCommand.java index 5e70e152..6329e8fd 100644 --- a/src/main/java/io/github/crucible/CrucibleCommand.java +++ b/src/main/java/io/github/crucible/CrucibleCommand.java @@ -1,15 +1,19 @@ package io.github.crucible; +import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.ModContainer; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldProvider; +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.cauldron.CauldronHooks; import net.minecraftforge.common.DimensionManager; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.spigotmc.RestartCommand; @@ -17,8 +21,7 @@ import java.lang.ref.WeakReference; import java.text.DecimalFormat; import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; +import java.util.*; public class CrucibleCommand extends Command { @@ -30,24 +33,25 @@ protected CrucibleCommand(MinecraftServer server) { serveReference = new WeakReference<>(server); String usage = "&7&m-------------------&7[&bCrucible&7]&m-------------------\n" + - "&b >&e crucible tps &7-&a Show tps statistics.\n" + - "&b >&e crucible restart &7-&a Restart the server.\n" + - "&b >&e crucible info &7-&a Print some information about the server.\n" + - "&b >&e crucible chunks &7-&a Print some information about loaded chunks.\n" + - "&b >&e crucible heap &7-&a Dump the server heap.\n" + - "&b >&e crucible plugins &7-&a Shows all your loaded plugins and mod plugins.\n" + - "&b >&e crucible mods &7-&a Shows all your loaded mods.\n"; + "&b >&e crucible tps &7-&a Show tps statistics.\n" + + "&b >&e crucible restart &7-&a Restart the server.\n" + + "&b >&e crucible info &7-&a Print some information about the server.\n" + + "&b >&e crucible chunks &7-&a Print some information about loaded chunks.\n" + + "&b >&e crucible heap &7-&a Dump the server heap.\n" + + "&b >&e crucible plugins &7-&a Shows all your loaded plugins and mod plugins.\n" + + "&b >&e crucible mods &7-&a Shows all your loaded mods.\n" + + "&b >&e crucible findChunks &7-&a Find and filter *loaded* chunks by their content."; setUsage(ChatColor.translateAlternateColorCodes('&', usage)); setPermission("crucible"); } public static String generateInfo() { String info = "This server is running &3Crucible&r [" + CrucibleModContainer.instance.getVersion() + "] (Thermos fork by CrucibleMC Team).\n" + - "&9https://github.com/CrucibleMC/Crucible\n&r" + - "Bukkit API implemented: 1.7.9-R0.3-SNAPSHOT\n" + - "Plugins: " + Bukkit.getPluginManager().getPlugins().length + "\n&r" + - "Mods: " + Loader.instance().getActiveModList().size() + - " &r| Loaded: " + Loader.instance().getModList().size() + "\n&r"; + "&9https://github.com/CrucibleMC/Crucible\n&r" + + "Bukkit API implemented: 1.7.9-R0.3-SNAPSHOT\n" + + "Plugins: " + Bukkit.getPluginManager().getPlugins().length + "\n&r" + + "Mods: " + Loader.instance().getActiveModList().size() + + " &r| Loaded: " + Loader.instance().getModList().size() + "\n&r"; return ChatColor.translateAlternateColorCodes('&', info); } @@ -111,13 +115,13 @@ private static String getTps() { name = worldProvider.worldObj.getSaveHandler().getWorldDirectoryName(); } tps.append("&8(&2&l") - .append(dimId) - .append(" &r&7&o\u279c &r&b") - .append(name).append("&r&8) &7Time: &l") - .append(timeFormat.format(worldTickTime)) - .append("&r&7ms TPS: ") - .append(parseTps(worldTPS)) - .append("&r\n"); + .append(dimId) + .append(" &r&7&o\u279c &r&b") + .append(name).append("&r&8) &7Time: &l") + .append(timeFormat.format(worldTickTime)) + .append("&r&7ms TPS: ") + .append(parseTps(worldTPS)) + .append("&r\n"); } return ChatColor.translateAlternateColorCodes('&', tps.toString()); @@ -192,6 +196,10 @@ public boolean execute(CommandSender sender, String commandLabel, String[] args) if (!testPermission(sender, "crucible.plugins")) return true; sender.sendMessage("Plugins " + getPluginList()); + } else if (args[0].equalsIgnoreCase("findChunks")) { + if (!testPermission(sender, "crucible.findChunks")) + return true; + findChunks(sender, args); } else if (args[0].equalsIgnoreCase("")) { if (!testPermission(sender, "crucible.")) return true; @@ -202,6 +210,37 @@ public boolean execute(CommandSender sender, String commandLabel, String[] args) return true; } + private void findChunks(CommandSender sender, String[] args) { + WorldServer world; + if (args.length >= 2) { + int id; + try { + id = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + sender.sendMessage(ChatColor.BLUE + "[Crucible] " + ChatColor.DARK_RED + "World ID is not a valid number!"); + return; + } + + world = DimensionManager.getWorld(id); + if (world == null) { + sender.sendMessage(ChatColor.BLUE + "[Crucible] " + ChatColor.DARK_RED + "World not found!"); + return; + } + } else if (sender instanceof Player) { + world = ((Player) sender).getWorld().getWorldServer(); + } else { + world = FMLCommonHandler.instance().getMinecraftServerInstance().worldServers[0]; + } + + List chunks = new ArrayList<>(world.theChunkProviderServer.loadedChunkHashMap_KC.rawVanilla().values()); + chunks.sort(Collections.reverseOrder(Comparator.comparingInt(c -> c.chunkTileEntityMap.size()))); + for (int i = 0; i < Math.min(chunks.size(), 20); i++) { + Chunk chunk = chunks.get(i); + sender.sendMessage(String.format(ChatColor.translateAlternateColorCodes('&', "&7[&e%s&7, &e%s&7] &r Tile Entities:%s"), + chunk.xPosition << 4, chunk.zPosition << 4, chunk.chunkTileEntityMap.size())); + } + } + public boolean testPermission(CommandSender target, String permission) { if (testPermissionSilent(target, permission)) { return true; @@ -231,15 +270,15 @@ private void processChunks(CommandSender sender, String[] args) { sender.sendMessage(ChatColor.GOLD + "Dimension stats: "); for (net.minecraft.world.WorldServer world : MinecraftServer.getServer().worlds) { sender.sendMessage(ChatColor.GOLD + "Dimension: " + ChatColor.GRAY + world.provider.dimensionId + - ChatColor.GOLD + " Loaded Chunks: " + ChatColor.GRAY + world.theChunkProviderServer.loadedChunkHashMap_KC.size() + - ChatColor.GOLD + " Active Chunks: " + ChatColor.GRAY + world.activeChunkSet.size() + - ChatColor.GOLD + " Entities: " + ChatColor.GRAY + world.loadedEntityList.size() + - ChatColor.GOLD + " Tile Entities: " + ChatColor.GRAY + world.loadedTileEntityList.size() + ChatColor.GOLD + " Loaded Chunks: " + ChatColor.GRAY + world.theChunkProviderServer.loadedChunkHashMap_KC.size() + + ChatColor.GOLD + " Active Chunks: " + ChatColor.GRAY + world.activeChunkSet.size() + + ChatColor.GOLD + " Entities: " + ChatColor.GRAY + world.loadedEntityList.size() + + ChatColor.GOLD + " Tile Entities: " + ChatColor.GRAY + world.loadedTileEntityList.size() ); sender.sendMessage(ChatColor.GOLD + " Entities Last Tick: " + ChatColor.GRAY + world.entitiesTicked + - ChatColor.GOLD + " Tiles Last Tick: " + ChatColor.GRAY + world.tilesTicked + - ChatColor.GOLD + " Removed Entities: " + ChatColor.GRAY + world.unloadedEntityList.size() + - ChatColor.GOLD + " Removed Tile Entities: " + ChatColor.GRAY + world.field_147483_b.size() + ChatColor.GOLD + " Tiles Last Tick: " + ChatColor.GRAY + world.tilesTicked + + ChatColor.GOLD + " Removed Entities: " + ChatColor.GRAY + world.unloadedEntityList.size() + + ChatColor.GOLD + " Removed Tile Entities: " + ChatColor.GRAY + world.field_147483_b.size() ); } @@ -254,4 +293,4 @@ private void processChunks(CommandSender sender, String[] args) { sender.sendMessage("Chunk info complete"); } -} +} \ No newline at end of file From 50b5646dc41ef15a59978caf97f3806b68011e48 Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Thu, 28 Dec 2023 10:43:03 -0300 Subject: [PATCH 2/9] Experimental Java 9+ support with lwjgl3ify --- build.gradle | 20 +- .../EventSubscriptionTransformer.java.patch | 20 + .../TerminalTransformer.java.patch | 17 +- .../common/discovery/JarDiscoverer.java.patch | 2 +- .../asm/ModAnnotationVisitor.java.patch | 11 + .../discovery/asm/ModClassVisitor.java.patch | 11 + .../discovery/asm/ModFieldVisitor.java.patch | 11 + .../discovery/asm/ModMethodVisitor.java.patch | 11 + .../launcher/FMLServerTweaker.java.patch | 10 - .../patcher/ClassPatchManager.java.patch | 58 ++ .../registry/ItemStackHolderRef.java.patch | 114 ++++ .../registry/ObjectHolderRef.java.patch | 143 +++++ .../registry/ObjectHolderRegistry.java.patch | 22 + .../fml/relauncher/CoreModManager.java.patch | 197 +++++- .../minecraft/crash/CrashReport.java.patch | 2 +- .../common/ForgeVersion.java.patch | 2 +- .../common/util/EnumHelper.java.patch | 585 +++++++++++++----- .../io/github/crucible/CrucibleCommand.java | 3 +- .../io/github/crucible/CrucibleConfigs.java | 36 +- .../github/crucible/CrucibleModContainer.java | 36 +- .../{ => bootstrap}/CrucibleMetadata.java | 3 +- .../bootstrap/CrucibleServerMainHook.java | 48 +- .../crucible/bootstrap/Lwjgl3ifyGlue.java | 111 ++++ .../crucible/util/config}/BaseConfig.java | 5 +- .../util/config}/BaseConfigMapper.java | 2 +- .../github/crucible/util/config}/Comment.java | 2 +- .../crucible/util/config}/Comments.java | 2 +- .../github/crucible/util/config}/Config.java | 2 +- .../crucible/util/config}/ConfigBasic.java | 2 +- .../crucible/util/config}/ConfigMapper.java | 4 +- .../crucible/util/config}/ConfigMode.java | 2 +- .../crucible/util/config}/ConfigSection.java | 2 +- .../github/crucible/util/config}/IConfig.java | 2 +- .../util/config}/InternalConverter.java | 20 +- .../InvalidConfigurationException.java | 2 +- .../config}/InvalidConverterException.java | 2 +- .../util/config}/MapConfigMapper.java | 2 +- .../github/crucible/util/config}/Path.java | 2 +- .../crucible/util/config}/PreserveStatic.java | 2 +- .../util/config}/SerializeOptions.java | 2 +- .../crucible/util/config}/YamlConfig.java | 2 +- .../util/config}/YamlConfigMapper.java | 2 +- .../util/config/converter}/Array.java | 4 +- .../util/config/converter}/Config.java | 8 +- .../util/config/converter}/Converter.java | 2 +- .../crucible/util/config/converter}/List.java | 4 +- .../crucible/util/config/converter}/Map.java | 6 +- .../util/config/converter}/Primitive.java | 4 +- .../crucible/util/config/converter}/Set.java | 4 +- .../eigenraven/lwjgl3ify/IExtensibleEnum.java | 31 + .../me/eigenraven/lwjgl3ify/UnsafeHacks.java | 99 +++ .../lwjgl3ify/WasFinalObjectHolder.java | 10 + .../eigenraven/lwjgl3ify/api/ConfigUtils.java | 34 + .../eigenraven/lwjgl3ify/api/Lwjgl3Aware.java | 13 + .../lwjgl3ify/api/MakeEnumExtensible.java | 13 + .../core/ExtensibleEnumTransformerHelper.java | 277 +++++++++ ...xConstantPoolInterfaceMethodRefHelper.java | 93 +++ .../core/LwjglRedirectTransformer.java | 86 +++ .../UnfinalizeObjectHoldersTransformer.java | 127 ++++ .../craftbukkit/v1_7_R4/CraftServer.java | 2 +- .../v1_7_R4/boss/CraftBossBar.java | 2 +- .../v1_7_R4/entity/CraftPlayer.java | 2 +- 62 files changed, 2081 insertions(+), 274 deletions(-) create mode 100644 patches/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java.patch create mode 100644 patches/cpw/mods/fml/common/discovery/asm/ModAnnotationVisitor.java.patch create mode 100644 patches/cpw/mods/fml/common/discovery/asm/ModClassVisitor.java.patch create mode 100644 patches/cpw/mods/fml/common/discovery/asm/ModFieldVisitor.java.patch create mode 100644 patches/cpw/mods/fml/common/discovery/asm/ModMethodVisitor.java.patch delete mode 100644 patches/cpw/mods/fml/common/launcher/FMLServerTweaker.java.patch create mode 100644 patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch create mode 100644 patches/cpw/mods/fml/common/registry/ItemStackHolderRef.java.patch create mode 100644 patches/cpw/mods/fml/common/registry/ObjectHolderRef.java.patch create mode 100644 patches/cpw/mods/fml/common/registry/ObjectHolderRegistry.java.patch rename src/main/java/io/github/crucible/{ => bootstrap}/CrucibleMetadata.java (96%) create mode 100644 src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/BaseConfig.java (94%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/BaseConfigMapper.java (99%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/Comment.java (89%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/Comments.java (89%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/Config.java (58%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/ConfigBasic.java (60%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/ConfigMapper.java (96%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/ConfigMode.java (78%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/ConfigSection.java (99%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/IConfig.java (93%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/InternalConverter.java (91%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/InvalidConfigurationException.java (91%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/InvalidConverterException.java (91%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/MapConfigMapper.java (63%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/Path.java (89%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/PreserveStatic.java (88%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/SerializeOptions.java (91%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/YamlConfig.java (99%) rename src/main/java/{net/cubespace/Yamler/Config => io/github/crucible/util/config}/YamlConfigMapper.java (64%) rename src/main/java/{net/cubespace/Yamler/Config/Converter => io/github/crucible/util/config/converter}/Array.java (94%) rename src/main/java/{net/cubespace/Yamler/Config/Converter => io/github/crucible/util/config/converter}/Config.java (88%) rename src/main/java/{net/cubespace/Yamler/Config/Converter => io/github/crucible/util/config/converter}/Converter.java (97%) rename src/main/java/{net/cubespace/Yamler/Config/Converter => io/github/crucible/util/config/converter}/List.java (94%) rename src/main/java/{net/cubespace/Yamler/Config/Converter => io/github/crucible/util/config/converter}/Map.java (96%) rename src/main/java/{net/cubespace/Yamler/Config/Converter => io/github/crucible/util/config/converter}/Primitive.java (94%) rename src/main/java/{net/cubespace/Yamler/Config/Converter => io/github/crucible/util/config/converter}/Set.java (95%) create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/IExtensibleEnum.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/UnsafeHacks.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/WasFinalObjectHolder.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/api/ConfigUtils.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/api/Lwjgl3Aware.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/api/MakeEnumExtensible.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/core/LwjglRedirectTransformer.java create mode 100644 src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java diff --git a/build.gradle b/build.gradle index 763f916a..0567961f 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { } dependencies { classpath 'com.anatawa12.forge:ForgeGradle:1.2-1.1.0' - classpath 'io.github.cruciblemc:CrucibleGradle:1.1-SNAPSHOT' + classpath 'io.github.cruciblemc:CrucibleGradle:1.2-SNAPSHOT' } } @@ -81,6 +81,21 @@ configurations { } dependencies { + // New java stuff + libraries 'org.apache.commons:commons-lang3:3.12.0' + libraries 'org.apache.commons:commons-compress:1.21' + libraries 'org.ow2.asm:asm:9.5' + libraries 'org.ow2.asm:asm-commons:9.5' + libraries 'org.ow2.asm:asm-tree:9.5' + libraries 'org.ow2.asm:asm-analysis:9.5' + libraries 'org.ow2.asm:asm-util:9.5' + libraries 'org.ow2.asm:asm-deprecated:7.1' + libraries 'jakarta.xml.bind:jakarta.xml.bind-api:3.0.1' + libraries 'jakarta.servlet:jakarta.servlet-api:6.0.0' + libraries 'com.sun.xml.bind:jaxb-impl:3.0.2' + libraries 'org.mozilla:rhino-engine:1.7.14' + + // Other libs libraries 'pw.prok:Damask:0.1.2@jar' libraries 'commons-cli:commons-cli:1.3@jar' libraries 'org.slf4j:slf4j-simple:1.6.2@jar' @@ -89,7 +104,6 @@ dependencies { libraries 'net.sf.opencsv:opencsv:2.0@jar' libraries 'com.beust:jcommander:1.30@jar' libraries 'io.github.cruciblemc:launchwrapper:1.13@jar' - libraries 'org.ow2.asm:asm-all:5.0.3' libraries 'com.typesafe.akka:akka-actor_2.11:2.3.3' libraries 'com.typesafe:config:1.2.1' libraries 'org.scala-lang:scala-actors-migration_2.11:1.1.0' @@ -113,7 +127,6 @@ dependencies { libraries 'org.xerial:sqlite-jdbc:3.7.2' libraries 'mysql:mysql-connector-java:5.1.14' libraries 'javax.persistence:persistence-api:1.0.2' - libraries 'net.minecraft:server:1.7.10' libraries 'pw.prok:KImagine:0.2.0@jar' libraries 'org.apache.httpcomponents:httpclient:4.4.1' libraries 'net.openhft:affinity:3.0.1' @@ -121,6 +134,7 @@ dependencies { libraries 'com.koloboke:koloboke-impl-jdk8:1.0.0' libraries 'java3d:vecmath:1.3.1' libraries 'it.unimi.dsi:fastutil:8.2.2' + libraries 'net.minecraft:server:1.7.10' } packageApi { diff --git a/patches/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java.patch b/patches/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java.patch new file mode 100644 index 00000000..fd4d3fa4 --- /dev/null +++ b/patches/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java.patch @@ -0,0 +1,20 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java ++++ ../src-work/minecraft/cpw/mods/fml/common/asm/transformers/EventSubscriptionTransformer.java +@@ -123,7 +123,7 @@ + { + for (AnnotationNode node : classNode.visibleAnnotations) + { +- if (!hasResult && node.desc.equals("Lcpw/mods/fml/common/eventhandler/Event$HasResult;")) ++ if (!hasResult && node.desc.replace('$', '/').equals("Lcpw/mods/fml/common/eventhandler/Event/HasResult;")) + { + /* Add: + * public boolean hasResult() +@@ -162,7 +162,7 @@ + return edited; + } + +- Type tSuper = Type.getType(classNode.superName); ++ Type tSuper = Type.getObjectType(classNode.superName); + + //Add private static ListenerList LISTENER_LIST + classNode.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, "LISTENER_LIST", listDesc, null, null)); diff --git a/patches/cpw/mods/fml/common/asm/transformers/TerminalTransformer.java.patch b/patches/cpw/mods/fml/common/asm/transformers/TerminalTransformer.java.patch index ff6c3318..1fe32aa7 100644 --- a/patches/cpw/mods/fml/common/asm/transformers/TerminalTransformer.java.patch +++ b/patches/cpw/mods/fml/common/asm/transformers/TerminalTransformer.java.patch @@ -1,6 +1,15 @@ --- ../src-base/minecraft/cpw/mods/fml/common/asm/transformers/TerminalTransformer.java +++ ../src-work/minecraft/cpw/mods/fml/common/asm/transformers/TerminalTransformer.java -@@ -46,7 +46,8 @@ +@@ -29,7 +29,7 @@ + + private ExitVisitor(ClassVisitor cv) + { +- super(Opcodes.ASM5, cv); ++ super(Opcodes.ASM9, cv); + } + + @Override +@@ -46,10 +46,11 @@ clsName.equals("net/minecraft/server/dedicated/DedicatedServer") || clsName.equals("cpw/mods/fml/common/FMLCommonHandler") || clsName.startsWith("com/jcraft/jogg/") || @@ -9,4 +18,8 @@ + clsName.startsWith("net/md_5/specialsource") ); - return new MethodVisitor(Opcodes.ASM5, super.visitMethod(mAccess, mName, mDesc, mSignature, mExceptions)) +- return new MethodVisitor(Opcodes.ASM5, super.visitMethod(mAccess, mName, mDesc, mSignature, mExceptions)) ++ return new MethodVisitor(Opcodes.ASM9, super.visitMethod(mAccess, mName, mDesc, mSignature, mExceptions)) + { + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isIntf) diff --git a/patches/cpw/mods/fml/common/discovery/JarDiscoverer.java.patch b/patches/cpw/mods/fml/common/discovery/JarDiscoverer.java.patch index e88fdd63..cf0ba2ae 100644 --- a/patches/cpw/mods/fml/common/discovery/JarDiscoverer.java.patch +++ b/patches/cpw/mods/fml/common/discovery/JarDiscoverer.java.patch @@ -5,7 +5,7 @@ for (ZipEntry ze : Collections.list(jar.entries())) { - if (ze.getName()!=null && ze.getName().startsWith("__MACOSX")) -+ if (ze.getName()!=null && (ze.getName().startsWith("__MACOSX") || ze.getName().startsWith("META-INF/versions"))) ++ if (ze.getName().startsWith("__MACOSX") || ze.getName().startsWith("META-INF/versions") || ze.getName().contains("org/openjdk/nashorn") || ze.getName().contains("jakarta/servlet/")) { continue; } diff --git a/patches/cpw/mods/fml/common/discovery/asm/ModAnnotationVisitor.java.patch b/patches/cpw/mods/fml/common/discovery/asm/ModAnnotationVisitor.java.patch new file mode 100644 index 00000000..82b0b86d --- /dev/null +++ b/patches/cpw/mods/fml/common/discovery/asm/ModAnnotationVisitor.java.patch @@ -0,0 +1,11 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/discovery/asm/ModAnnotationVisitor.java ++++ ../src-work/minecraft/cpw/mods/fml/common/discovery/asm/ModAnnotationVisitor.java +@@ -25,7 +25,7 @@ + + public ModAnnotationVisitor(ASMModParser discoverer) + { +- super(Opcodes.ASM5); ++ super(Opcodes.ASM9); + this.discoverer = discoverer; + } + diff --git a/patches/cpw/mods/fml/common/discovery/asm/ModClassVisitor.java.patch b/patches/cpw/mods/fml/common/discovery/asm/ModClassVisitor.java.patch new file mode 100644 index 00000000..f0e8e3e1 --- /dev/null +++ b/patches/cpw/mods/fml/common/discovery/asm/ModClassVisitor.java.patch @@ -0,0 +1,11 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/discovery/asm/ModClassVisitor.java ++++ ../src-work/minecraft/cpw/mods/fml/common/discovery/asm/ModClassVisitor.java +@@ -24,7 +24,7 @@ + + public ModClassVisitor(ASMModParser discoverer) + { +- super(Opcodes.ASM5); ++ super(Opcodes.ASM9); + this.discoverer = discoverer; + } + diff --git a/patches/cpw/mods/fml/common/discovery/asm/ModFieldVisitor.java.patch b/patches/cpw/mods/fml/common/discovery/asm/ModFieldVisitor.java.patch new file mode 100644 index 00000000..425920f5 --- /dev/null +++ b/patches/cpw/mods/fml/common/discovery/asm/ModFieldVisitor.java.patch @@ -0,0 +1,11 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/discovery/asm/ModFieldVisitor.java ++++ ../src-work/minecraft/cpw/mods/fml/common/discovery/asm/ModFieldVisitor.java +@@ -24,7 +24,7 @@ + + public ModFieldVisitor(String name, ASMModParser discoverer) + { +- super(Opcodes.ASM5); ++ super(Opcodes.ASM9); + this.fieldName = name; + this.discoverer = discoverer; + } diff --git a/patches/cpw/mods/fml/common/discovery/asm/ModMethodVisitor.java.patch b/patches/cpw/mods/fml/common/discovery/asm/ModMethodVisitor.java.patch new file mode 100644 index 00000000..8b77fca5 --- /dev/null +++ b/patches/cpw/mods/fml/common/discovery/asm/ModMethodVisitor.java.patch @@ -0,0 +1,11 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/discovery/asm/ModMethodVisitor.java ++++ ../src-work/minecraft/cpw/mods/fml/common/discovery/asm/ModMethodVisitor.java +@@ -12,7 +12,7 @@ + + public ModMethodVisitor(String name, String desc, ASMModParser discoverer) + { +- super(Opcodes.ASM5); ++ super(Opcodes.ASM9); + this.methodName = name; + this.methodDescriptor = desc; + this.discoverer = discoverer; diff --git a/patches/cpw/mods/fml/common/launcher/FMLServerTweaker.java.patch b/patches/cpw/mods/fml/common/launcher/FMLServerTweaker.java.patch deleted file mode 100644 index 56333988..00000000 --- a/patches/cpw/mods/fml/common/launcher/FMLServerTweaker.java.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- ../src-base/minecraft/cpw/mods/fml/common/launcher/FMLServerTweaker.java -+++ ../src-work/minecraft/cpw/mods/fml/common/launcher/FMLServerTweaker.java -@@ -19,6 +19,7 @@ - classLoader.addTransformerExclusion("cpw.mods.fml.repackage."); - classLoader.addTransformerExclusion("cpw.mods.fml.relauncher."); - classLoader.addTransformerExclusion("cpw.mods.fml.common.asm.transformers."); -+ classLoader.addTransformerExclusion("io.github.crucible.bootstrap."); // Crucible - make our bootstrap stuff visible for both obfuscated and not obfuscated sides - classLoader.addClassLoaderExclusion("LZMA."); - FMLLaunchHandler.configureForServerLaunch(classLoader, this); - FMLLaunchHandler.appendCoreMods(); diff --git a/patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch b/patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch new file mode 100644 index 00000000..5a4f9abf --- /dev/null +++ b/patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch @@ -0,0 +1,58 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/patcher/ClassPatchManager.java ++++ ../src-work/minecraft/cpw/mods/fml/common/patcher/ClassPatchManager.java +@@ -14,11 +14,13 @@ + import java.util.jar.Pack200; + import java.util.regex.Pattern; + ++import org.apache.commons.compress.harmony.unpack200.Archive; + import org.apache.logging.log4j.Level; + + import net.minecraft.launchwrapper.LaunchClassLoader; + +-import LZMA.LzmaInputStream; ++import org.apache.commons.compress.harmony.unpack200.Pack200UnpackerAdapter; ++import org.apache.logging.log4j.Level; + + import com.google.common.base.Joiner; + import com.google.common.base.Throwables; +@@ -30,11 +32,13 @@ + import com.google.common.io.ByteStreams; + import com.google.common.io.Files; + ++import LZMA.LzmaInputStream; + import cpw.mods.fml.relauncher.FMLRelaunchLog; + import cpw.mods.fml.relauncher.Side; + import cpw.mods.fml.repackage.com.nothome.delta.GDiffPatcher; + + public class ClassPatchManager { ++ + public static final ClassPatchManager INSTANCE = new ClassPatchManager(); + + public static final boolean dumpPatched = Boolean.parseBoolean(System.getProperty("fml.dumpPatchedClasses", "false")); +@@ -155,10 +159,24 @@ + FMLRelaunchLog.log(Level.ERROR, "The binary patch set is missing. Either you are in a development environment, or things are not going to work!"); + return; + } +- LzmaInputStream binpatchesDecompressed = new LzmaInputStream(binpatchesCompressed); ++ // Crucible start - apply lwjgl3ify patch ++ // LzmaInputStream binpatchesDecompressed = new LzmaInputStream(binpatchesCompressed); ++ LzmaInputStream binpatchesDecompressedLzma = new LzmaInputStream(binpatchesCompressed); ++ // The Apache pack200 stream chokes on a lzmainputstream for some reason ++ byte[] decompressed = ByteStreams.toByteArray(binpatchesDecompressedLzma); ++ binpatchesDecompressedLzma.close(); ++ ByteArrayInputStream binpatchesDecompressed = new ByteArrayInputStream(decompressed); + ByteArrayOutputStream jarBytes = new ByteArrayOutputStream(); + JarOutputStream jos = new JarOutputStream(jarBytes); +- Pack200.newUnpacker().unpack(binpatchesDecompressed, jos); ++ ++ //Pack200.newUnpacker().unpack(binpatchesDecompressed, jos); ++ Archive archive = new Archive(binpatchesDecompressed, jos); ++ archive.setQuiet(true); ++ // Crucible note: YES, this *IS* needed, Thermos logging is so broken beyond repair that not setting a log file will break *EVERYTHING* - juanmuscaria ++ archive.setLogFile("logs/.ignoreMe"); ++ archive.unpack(); ++ // Crucible end ++ + jis = new JarInputStream(new ByteArrayInputStream(jarBytes.toByteArray())); + } + catch (Exception e) diff --git a/patches/cpw/mods/fml/common/registry/ItemStackHolderRef.java.patch b/patches/cpw/mods/fml/common/registry/ItemStackHolderRef.java.patch new file mode 100644 index 00000000..124fc6f8 --- /dev/null +++ b/patches/cpw/mods/fml/common/registry/ItemStackHolderRef.java.patch @@ -0,0 +1,114 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/registry/ItemStackHolderRef.java ++++ ../src-work/minecraft/cpw/mods/fml/common/registry/ItemStackHolderRef.java +@@ -1,5 +1,7 @@ + package cpw.mods.fml.common.registry; + ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; + import java.lang.reflect.Field; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; +@@ -40,20 +42,26 @@ + private static Object reflectionFactory; + private static Method newFieldAccessor; + private static Method fieldAccessorSet; ++ private static MethodHandle fieldSetter; // Crucible - lwjgl3ify field + private static void makeWritable(Field f) + { + try + { +- if (modifiersField == null) +- { +- Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); +- reflectionFactory = getReflectionFactory.invoke(null); +- newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); +- fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); +- modifiersField = Field.class.getDeclaredField("modifiers"); +- modifiersField.setAccessible(true); +- } +- modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); ++ // Crucible start - implement lwjgl3ify patch directly ++// if (modifiersField == null) ++// { ++// Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); ++// reflectionFactory = getReflectionFactory.invoke(null); ++// newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); ++// fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); ++// modifiersField = Field.class.getDeclaredField("modifiers"); ++// modifiersField.setAccessible(true); ++// } ++// modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); ++ f.setAccessible(true); ++ fieldSetter = MethodHandles.lookup() ++ .unreflectSetter(f); ++ // Crucible end + } catch (Exception e) + { + throw Throwables.propagate(e); +@@ -62,23 +70,53 @@ + + public void apply() + { ++ // Crucible start - implement lwjgl3ify patch directly ++// ItemStack is; ++// try ++// { ++// is = GameRegistry.makeItemStack(itemName, meta, 1, serializednbt); ++// } catch (RuntimeException e) ++// { ++// FMLLog.getLogger().log(Level.ERROR, "Caught exception processing itemstack {},{},{} in annotation at {}.{}", itemName, meta, serializednbt,field.getClass().getName(),field.getName()); ++// throw e; ++// } ++// try ++// { ++// Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); ++// fieldAccessorSet.invoke(fieldAccessor, null, is); ++// } ++// catch (Exception e) ++// { ++// FMLLog.getLogger().log(Level.WARN, "Unable to set {} with value {},{},{}", this.field, this.itemName, this.meta, this.serializednbt); ++// } + ItemStack is; +- try +- { ++ try { + is = GameRegistry.makeItemStack(itemName, meta, 1, serializednbt); +- } catch (RuntimeException e) +- { +- FMLLog.getLogger().log(Level.ERROR, "Caught exception processing itemstack {},{},{} in annotation at {}.{}", itemName, meta, serializednbt,field.getClass().getName(),field.getName()); ++ } catch (RuntimeException e) { ++ FMLLog.getLogger() ++ .log( ++ Level.ERROR, ++ "Caught exception processing itemstack {},{},{} in annotation at {}.{}", ++ itemName, ++ meta, ++ serializednbt, ++ field.getClass() ++ .getName(), ++ field.getName()); + throw e; + } +- try +- { +- Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); +- fieldAccessorSet.invoke(fieldAccessor, null, is); ++ try { ++ fieldSetter.invoke(is); ++ } catch (Throwable e) { ++ FMLLog.getLogger() ++ .log( ++ Level.WARN, ++ "Unable to set {} with value {},{},{}", ++ this.field, ++ this.itemName, ++ this.meta, ++ this.serializednbt); + } +- catch (Exception e) +- { +- FMLLog.getLogger().log(Level.WARN, "Unable to set {} with value {},{},{}", this.field, this.itemName, this.meta, this.serializednbt); +- } ++ // Crucible end + } + } diff --git a/patches/cpw/mods/fml/common/registry/ObjectHolderRef.java.patch b/patches/cpw/mods/fml/common/registry/ObjectHolderRef.java.patch new file mode 100644 index 00000000..9f8c09f3 --- /dev/null +++ b/patches/cpw/mods/fml/common/registry/ObjectHolderRef.java.patch @@ -0,0 +1,143 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/registry/ObjectHolderRef.java ++++ ../src-work/minecraft/cpw/mods/fml/common/registry/ObjectHolderRef.java +@@ -1,5 +1,7 @@ + package cpw.mods.fml.common.registry; + ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; + import java.lang.reflect.Field; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; +@@ -74,16 +76,19 @@ + { + try + { +- if (modifiersField == null) +- { +- Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); +- reflectionFactory = getReflectionFactory.invoke(null); +- newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); +- fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); +- modifiersField = Field.class.getDeclaredField("modifiers"); +- modifiersField.setAccessible(true); +- } +- modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); ++ // Crucible start - implement lwjgl3ify patch directly ++// if (modifiersField == null) ++// { ++// Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); ++// reflectionFactory = getReflectionFactory.invoke(null); ++// newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); ++// fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); ++// modifiersField = Field.class.getDeclaredField("modifiers"); ++// modifiersField.setAccessible(true); ++// } ++// modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); ++ f.setAccessible(true); ++ // Crucible end + } catch (Exception e) + { + throw Throwables.propagate(e); +@@ -94,39 +99,80 @@ + { + return isBlock || isItem; + } ++ ++ private MethodHandle fieldSetter = null; // Crucible - needed by lwjgl3ify + public void apply() + { ++ // Crucible start - implement lwjgl3ify patch directly ++// Object thing; ++// if (isBlock) ++// { ++// thing = GameData.getBlockRegistry().getObject(injectedObject); ++// if (thing == Blocks.air) ++// { ++// thing = null; ++// } ++// } ++// else if (isItem) ++// { ++// thing = GameData.getItemRegistry().getObject(injectedObject); ++// } ++// else ++// { ++// thing = null; ++// } ++// ++// if (thing == null) ++// { ++// FMLLog.getLogger().log(Level.DEBUG, "Unable to lookup {} for {}. This means the object wasn't registered. It's likely just mod options.", injectedObject, field); ++// return; ++// } ++// try ++// { ++// Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); ++// fieldAccessorSet.invoke(fieldAccessor, null, thing); ++// } ++// catch (Exception e) ++// { ++// FMLLog.log(Level.WARN, e, "Unable to set %s with value %s (%s)", this.field, thing, this.injectedObject); ++// } ++ if (fieldSetter == null) { ++ try { ++ fieldSetter = MethodHandles.lookup() ++ .unreflectSetter(this.field); ++ } catch (IllegalAccessException e) { ++ throw new RuntimeException(e); ++ } ++ } + Object thing; +- if (isBlock) +- { +- thing = GameData.getBlockRegistry().getObject(injectedObject); +- if (thing == Blocks.air) +- { ++ if (isBlock) { ++ thing = GameData.getBlockRegistry() ++ .getObject(injectedObject); ++ if (thing == Blocks.air) { + thing = null; + } +- } +- else if (isItem) +- { +- thing = GameData.getItemRegistry().getObject(injectedObject); +- } +- else +- { ++ } else if (isItem) { ++ thing = GameData.getItemRegistry() ++ .getObject(injectedObject); ++ } else { + thing = null; + } + +- if (thing == null) +- { +- FMLLog.getLogger().log(Level.DEBUG, "Unable to lookup {} for {}. This means the object wasn't registered. It's likely just mod options.", injectedObject, field); ++ if (thing == null) { ++ FMLLog.getLogger() ++ .log( ++ Level.DEBUG, ++ "Unable to lookup {} for {}. This means the object wasn't registered. It's likely just mod options.", ++ injectedObject, ++ field); + return; + } +- try +- { +- Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); +- fieldAccessorSet.invoke(fieldAccessor, null, thing); +- } +- catch (Exception e) +- { ++ try { ++ fieldSetter.invoke(thing); ++ FMLLog.finer("Set field " + field.toString() + " to " + thing); ++ } catch (Throwable e) { + FMLLog.log(Level.WARN, e, "Unable to set %s with value %s (%s)", this.field, thing, this.injectedObject); + } ++ // Crucible end + } + } diff --git a/patches/cpw/mods/fml/common/registry/ObjectHolderRegistry.java.patch b/patches/cpw/mods/fml/common/registry/ObjectHolderRegistry.java.patch new file mode 100644 index 00000000..23de36ff --- /dev/null +++ b/patches/cpw/mods/fml/common/registry/ObjectHolderRegistry.java.patch @@ -0,0 +1,22 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/registry/ObjectHolderRegistry.java ++++ ../src-work/minecraft/cpw/mods/fml/common/registry/ObjectHolderRegistry.java +@@ -12,6 +12,7 @@ + import cpw.mods.fml.common.discovery.ASMDataTable; + import cpw.mods.fml.common.discovery.ASMDataTable.ASMData; + import cpw.mods.fml.common.registry.GameRegistry.ObjectHolder; ++import me.eigenraven.lwjgl3ify.WasFinalObjectHolder; + + /** + * Internal registry for tracking {@link ObjectHolder} references +@@ -111,6 +112,11 @@ + for (Field f : clazz.getFields()) + { + int mods = f.getModifiers(); ++ // Crucible start - lwjgl3ify patch ++ if (f.isAnnotationPresent(WasFinalObjectHolder.class)) { ++ mods |= Modifier.FINAL; ++ } ++ // Crucible end + boolean isMatch = Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods); + if (!isMatch || f.isAnnotationPresent(ObjectHolder.class)) + { diff --git a/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch b/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch index 9a9b8e00..fe562294 100644 --- a/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch +++ b/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch @@ -1,6 +1,38 @@ --- ../src-base/minecraft/cpw/mods/fml/relauncher/CoreModManager.java +++ ../src-work/minecraft/cpw/mods/fml/relauncher/CoreModManager.java -@@ -60,7 +60,7 @@ +@@ -7,7 +7,8 @@ + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * + * Contributors: +- * cpw - implementation ++ * cpw - implementation ++ * eigenraven - java 9 compatibility + */ + + package cpw.mods.fml.relauncher; +@@ -16,7 +17,7 @@ + import java.io.FileFilter; + import java.io.FilenameFilter; + import java.io.IOException; +-import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Field; + import java.lang.reflect.Method; + import java.net.MalformedURLException; + import java.net.URL; +@@ -31,6 +32,8 @@ + import java.util.jar.Attributes; + import java.util.jar.JarFile; + ++import io.github.crucible.CrucibleModContainer; ++import io.github.crucible.bootstrap.CrucibleServerMainHook; + import net.minecraft.launchwrapper.ITweaker; + import net.minecraft.launchwrapper.Launch; + import net.minecraft.launchwrapper.LaunchClassLoader; +@@ -57,10 +60,11 @@ + import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; + + public class CoreModManager { ++ private static final Attributes.Name COREMODCONTAINSFMLMOD = new Attributes.Name("FMLCorePluginContainsFMLMod"); private static final Attributes.Name MODTYPE = new Attributes.Name("ModType"); private static final Attributes.Name MODSIDE = new Attributes.Name("ModSide"); @@ -9,15 +41,41 @@ private static List loadedCoremods = Lists.newArrayList(); private static List loadPlugins; private static boolean deobfuscatedEnvironment; -@@ -101,6 +101,7 @@ +@@ -70,6 +74,7 @@ + private static List accessTransformers = Lists.newArrayList(); + + private static class FMLPluginWrapper implements ITweaker { ++ + public final String name; + public final IFMLLoadingPlugin coreModInstance; + public final List predepends; +@@ -99,14 +104,17 @@ + } + @Override - public void injectIntoClassLoader(LaunchClassLoader classLoader) - { -+ // Cauldron end - FMLRelaunchLog.fine("Injecting coremod %s {%s} class transformers", name, coreModInstance.getClass().getName()); - if (coreModInstance.getASMTransformerClass() != null) for (String transformer : coreModInstance.getASMTransformerClass()) - { -@@ -160,6 +161,9 @@ +- public void injectIntoClassLoader(LaunchClassLoader classLoader) +- { +- FMLRelaunchLog.fine("Injecting coremod %s {%s} class transformers", name, coreModInstance.getClass().getName()); +- if (coreModInstance.getASMTransformerClass() != null) for (String transformer : coreModInstance.getASMTransformerClass()) +- { +- FMLRelaunchLog.finer("Registering transformer %s", transformer); +- classLoader.registerTransformer(transformer); +- } ++ public void injectIntoClassLoader(LaunchClassLoader classLoader) { ++ FMLRelaunchLog.info( ++ "Injecting coremod %s {%s} class transformers", ++ name, ++ coreModInstance.getClass() ++ .getName()); ++ if (coreModInstance.getASMTransformerClass() != null) ++ for (String transformer : coreModInstance.getASMTransformerClass()) { ++ FMLRelaunchLog.finer("Registering transformer %s", transformer); ++ classLoader.registerTransformer(transformer); ++ } + FMLRelaunchLog.fine("Injection complete"); + + FMLRelaunchLog.fine("Running coremod plugin for %s {%s}", name, coreModInstance.getClass().getName()); +@@ -160,6 +168,9 @@ } @@ -27,7 +85,7 @@ public static void handleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { CoreModManager.mcDir = mcDir; -@@ -219,6 +223,19 @@ +@@ -219,7 +230,23 @@ loadCoreMod(classLoader, coreModClassName, null); } discoverCoreMods(mcDir, classLoader); @@ -35,7 +93,7 @@ + if (!noVersionAnnotationCoreMods.isEmpty()) + { + FMLRelaunchLog -+ .warning("The following coremods do not have a @MCVersion annotation. They may cause problems if this is not the correct version of Minecraft for them."); ++ .warning("The following coremods do not have a @MCVersion annotation. They may cause problems if this is not the correct version of Minecraft for them."); + StringBuilder sb = new StringBuilder("Missing @MCVersion: "); + for (String className : noVersionAnnotationCoreMods) + { @@ -45,9 +103,13 @@ + } + // Cauldron end ++ // Crucible start - too lazy for creating a coremod ++ CrucibleServerMainHook.coremodHandleLaunch(mcDir, classLoader, tweaker); ++ // Crucible end } -@@ -336,6 +353,10 @@ + private static void discoverCoreMods(File mcDir, LaunchClassLoader classLoader) +@@ -336,6 +363,10 @@ String cascadedTweaker = mfAttributes.getValue("TweakClass"); if (cascadedTweaker != null) { @@ -58,7 +120,7 @@ FMLRelaunchLog.info("Loading tweaker %s from %s", cascadedTweaker, coreMod.getName()); Integer sortOrder = Ints.tryParse(Strings.nullToEmpty(mfAttributes.getValue("TweakOrder"))); sortOrder = (sortOrder == null ? Integer.valueOf(0) : sortOrder); -@@ -365,6 +386,10 @@ +@@ -365,6 +396,10 @@ FMLRelaunchLog.fine("Not found coremod data in %s", coreMod.getName()); continue; } @@ -69,7 +131,101 @@ // Support things that are mod jars, but not FML mod jars try { -@@ -467,8 +492,11 @@ +@@ -377,40 +412,76 @@ + else + { + FMLRelaunchLog.finer("Found FMLCorePluginContainsFMLMod marker in %s, it will be examined later for regular @Mod instances", +- coreMod.getName()); ++ coreMod.getName()); + reparsedCoremods.add(coreMod.getName()); + } + } + catch (MalformedURLException e) + { + FMLRelaunchLog.log(Level.ERROR, e, "Unable to convert file into a URL. weird"); ++ + continue; + } + loadCoreMod(classLoader, fmlCorePlugin, coreMod); + } + } + ++ // Lwjgl3ify start - support code + private static Method ADDURL; ++ private static void addUrlToClassloader(ClassLoader loader, URL coreModUrl) { ++ try { ++ if (loader instanceof URLClassLoader) { ++ if (ADDURL == null) { ++ ADDURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); ++ ADDURL.setAccessible(true); ++ } ++ ADDURL.invoke(loader, coreModUrl); ++ } else { ++ Field ucpField; ++ try { ++ // Java 8-11 ++ ucpField = loader.getClass() ++ .getDeclaredField("ucp"); ++ } catch (NoSuchFieldException e) { ++ // Java 17 ++ ucpField = loader.getClass() ++ .getSuperclass() ++ .getDeclaredField("ucp"); ++ } ++ ucpField.setAccessible(true); ++ final Object ucp = ucpField.get(loader); ++ final Method urlAdder = ucp.getClass() ++ .getDeclaredMethod("addURL", URL.class); ++ urlAdder.invoke(ucp, coreModUrl); ++ } ++ } catch (ReflectiveOperationException e) { ++ throw new RuntimeException("Couldn't add url to classpath in loader " + loader.getClass(), e); ++ } ++ } ++ // Lwjgl3ify end + +- private static void handleCascadingTweak(File coreMod, JarFile jar, String cascadedTweaker, LaunchClassLoader classLoader, Integer sortingOrder) +- { +- try +- { ++ private static void handleCascadingTweak(File coreMod, JarFile jar, String cascadedTweaker, ++ LaunchClassLoader classLoader, Integer sortingOrder) { ++ try { + // Have to manually stuff the tweaker into the parent classloader +- if (ADDURL == null) +- { +- ADDURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); +- ADDURL.setAccessible(true); +- } +- ADDURL.invoke(classLoader.getClass().getClassLoader(), coreMod.toURI().toURL()); +- classLoader.addURL(coreMod.toURI().toURL()); ++ // Lwjgl3ify start ++ URL coreModUrl = coreMod.toURI() ++ .toURL(); ++ ClassLoader myLoader = classLoader.getClass() ++ .getClassLoader(); ++ addUrlToClassloader(myLoader, coreModUrl); ++ classLoader.addURL(coreModUrl); ++ // Lwjgl3ify end + CoreModManager.tweaker.injectCascadingTweak(cascadedTweaker); +- tweakSorting.put(cascadedTweaker,sortingOrder); ++ tweakSorting.put(cascadedTweaker, sortingOrder); ++ } catch (Exception e) { ++ FMLRelaunchLog.log( ++ Level.INFO, ++ e, ++ "There was a problem trying to load the mod dir tweaker %s", ++ coreMod.getAbsolutePath()); ++ e.printStackTrace(); + } +- catch (Exception e) +- { +- FMLRelaunchLog.log(Level.INFO, e, "There was a problem trying to load the mod dir tweaker %s", coreMod.getAbsolutePath()); +- } + } + + /** +@@ -467,19 +538,22 @@ MCVersion requiredMCVersion = coreModClazz.getAnnotation(IFMLLoadingPlugin.MCVersion.class); if (!Arrays.asList(rootPlugins).contains(coreModClass) && (requiredMCVersion == null || Strings.isNullOrEmpty(requiredMCVersion.value()))) { @@ -83,3 +239,16 @@ } else if (requiredMCVersion != null && !FMLInjectionData.mccversion.equals(requiredMCVersion.value())) { + FMLRelaunchLog.log(Level.ERROR, "The coremod %s is requesting minecraft version %s and minecraft is %s. It will be ignored.", coreModClass, +- requiredMCVersion.value(), FMLInjectionData.mccversion); ++ requiredMCVersion.value(), FMLInjectionData.mccversion); + return null; + } + else if (requiredMCVersion != null) + { + FMLRelaunchLog.log(Level.DEBUG, "The coremod %s requested minecraft version %s and minecraft is %s. It will be loaded.", coreModClass, +- requiredMCVersion.value(), FMLInjectionData.mccversion); ++ requiredMCVersion.value(), FMLInjectionData.mccversion); + } + TransformerExclusions trExclusions = coreModClazz.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class); + if (trExclusions != null) diff --git a/patches/net/minecraft/crash/CrashReport.java.patch b/patches/net/minecraft/crash/CrashReport.java.patch index 262a1d4b..3e886ff4 100644 --- a/patches/net/minecraft/crash/CrashReport.java.patch +++ b/patches/net/minecraft/crash/CrashReport.java.patch @@ -5,7 +5,7 @@ import java.util.List; import java.util.concurrent.Callable; + -+import io.github.crucible.CrucibleMetadata; ++import io.github.crucible.bootstrap.CrucibleMetadata; import net.minecraft.util.ReportedException; import net.minecraft.world.gen.layer.IntCache; + diff --git a/patches/net/minecraftforge/common/ForgeVersion.java.patch b/patches/net/minecraftforge/common/ForgeVersion.java.patch index a74448b4..37ef8374 100644 --- a/patches/net/minecraftforge/common/ForgeVersion.java.patch +++ b/patches/net/minecraftforge/common/ForgeVersion.java.patch @@ -7,7 +7,7 @@ -import java.io.InputStream; -import java.net.URL; -import java.util.Map; -+import io.github.crucible.CrucibleMetadata; ++import io.github.crucible.bootstrap.CrucibleMetadata; -import com.google.common.io.ByteStreams; -import com.google.gson.Gson; diff --git a/patches/net/minecraftforge/common/util/EnumHelper.java.patch b/patches/net/minecraftforge/common/util/EnumHelper.java.patch index b92eef86..6d6f15f8 100644 --- a/patches/net/minecraftforge/common/util/EnumHelper.java.patch +++ b/patches/net/minecraftforge/common/util/EnumHelper.java.patch @@ -1,6 +1,18 @@ --- ../src-base/minecraft/net/minecraftforge/common/util/EnumHelper.java +++ ../src-work/minecraft/net/minecraftforge/common/util/EnumHelper.java -@@ -21,7 +21,22 @@ +@@ -1,8 +1,11 @@ + package net.minecraftforge.common.util; + ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; + import java.lang.reflect.*; + import java.util.*; + ++import com.google.common.base.Throwables; + import cpw.mods.fml.common.FMLLog; + import net.minecraft.block.BlockPressurePlate.Sensitivity; + import net.minecraft.block.material.Material; +@@ -21,270 +24,291 @@ import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door; import net.minecraftforge.classloading.FMLForgePlugin; @@ -10,6 +22,10 @@ +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +-public class EnumHelper +-{ +- private static Object reflectionFactory = null; ++import org.apache.commons.lang3.ArrayUtils; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; @@ -20,186 +36,467 @@ +import org.bukkit.event.inventory.InventoryType; +// Cauldron end + - public class EnumHelper - { - private static Object reflectionFactory = null; -@@ -30,6 +45,7 @@ - private static Method newFieldAccessor = null; - private static Method fieldAccessorSet = null; - private static boolean isSetup = false; ++public class EnumHelper { ++ private static Object reflectionFactory = null; + private static Method newConstructorAccessor = null; +- private static Method newInstance = null; +- private static Method newFieldAccessor = null; +- private static Method fieldAccessorSet = null; +- private static boolean isSetup = false; ++ private static Method newInstance = null; ++ private static Method newFieldAccessor = null; ++ private static Method fieldAccessorSet = null; ++ private static boolean isSetup = false; + private static final Logger logger = LogManager.getLogger(); - //Some enums are decompiled with extra arguments, so lets check for that +- //Some enums are decompiled with extra arguments, so lets check for that ++ // Some enums are decompiled with extra arguments, so lets check for that @SuppressWarnings("rawtypes") -@@ -51,6 +67,73 @@ - {EnumRarity.class, EnumChatFormatting.class, String.class} - }; +- private static Class[][] commonTypes = +- { +- {EnumAction.class}, +- {ArmorMaterial.class, int.class, int[].class, int.class}, +- {EnumArt.class, String.class, int.class, int.class, int.class, int.class}, +- {EnumCreatureAttribute.class}, +- {EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class}, +- {Door.class}, +- {EnumEnchantmentType.class}, +- {EnumEntitySize.class}, +- {Sensitivity.class}, +- {MovingObjectType.class}, +- {EnumSkyBlock.class, int.class}, +- {EnumStatus.class}, +- {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, +- {EnumRarity.class, EnumChatFormatting.class, String.class} +- }; ++ private static Class[][] commonTypes = {{EnumAction.class}, ++ {ArmorMaterial.class, int.class, int[].class, int.class}, ++ {EnumArt.class, String.class, int.class, int.class, int.class, int.class}, {EnumCreatureAttribute.class}, ++ {EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class}, ++ {Door.class}, {EnumEnchantmentType.class}, {EnumEntitySize.class}, {Sensitivity.class}, ++ {MovingObjectType.class}, {EnumSkyBlock.class, int.class}, {EnumStatus.class}, ++ {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, ++ {EnumRarity.class, EnumChatFormatting.class, String.class}}; -+ // Cauldron start -+ public static Biome addBukkitBiome(String name) -+ { -+ return (Biome)addEnum(Biome.class, name, new Class[0], new Object[0]); -+ } +- public static EnumAction addAction(String name) +- { ++ public static EnumAction addAction(String name) { + return addEnum(EnumAction.class, name); + } +- public static ArmorMaterial addArmorMaterial(String name, int durability, int[] reductionAmounts, int enchantability) +- { + -+ public static World.Environment addBukkitEnvironment(int id, String name) -+ { -+ if (!isSetup) -+ { -+ setup(); -+ } ++ public static ArmorMaterial addArmorMaterial(String name, int durability, int[] reductionAmounts, int enchantability) { + return addEnum(ArmorMaterial.class, name, durability, reductionAmounts, enchantability); + } +- public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY) +- { + -+ return (World.Environment)addEnum(World.Environment.class, name, new Class[] { Integer.TYPE }, new Object[] { Integer.valueOf(id) }); ++ public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY) { + return addEnum(EnumArt.class, name, tile, sizeX, sizeY, offsetX, offsetY); + } +- public static EnumCreatureAttribute addCreatureAttribute(String name) +- { ++ ++ public static EnumCreatureAttribute addCreatureAttribute(String name) { + return addEnum(EnumCreatureAttribute.class, name); + } ++ + @SuppressWarnings("rawtypes") +- public static EnumCreatureType addCreatureType(String name, Class typeClass, int maxNumber, Material material, boolean peaceful, boolean animal) +- { ++ public static EnumCreatureType addCreatureType(String name, Class typeClass, int maxNumber, Material material, boolean peaceful, boolean animal) { + return addEnum(EnumCreatureType.class, name, typeClass, maxNumber, material, peaceful, animal); + } +- public static Door addDoor(String name) +- { ++ ++ public static Door addDoor(String name) { + return addEnum(Door.class, name); + } +- public static EnumEnchantmentType addEnchantmentType(String name) +- { ++ ++ public static EnumEnchantmentType addEnchantmentType(String name) { + return addEnum(EnumEnchantmentType.class, name); + } +- public static EnumEntitySize addEntitySize(String name) +- { ++ ++ public static EnumEntitySize addEntitySize(String name) { + return addEnum(EnumEntitySize.class, name); + } +- public static Sensitivity addSensitivity(String name) +- { ++ ++ public static Sensitivity addSensitivity(String name) { + return addEnum(Sensitivity.class, name); + } +- public static MovingObjectType addMovingObjectType(String name) +- { ++ ++ public static MovingObjectType addMovingObjectType(String name) { + return addEnum(MovingObjectType.class, name); + } +- public static EnumSkyBlock addSkyBlock(String name, int lightValue) +- { ++ ++ public static EnumSkyBlock addSkyBlock(String name, int lightValue) { + return addEnum(EnumSkyBlock.class, name, lightValue); + } +- public static EnumStatus addStatus(String name) +- { ++ ++ public static EnumStatus addStatus(String name) { + return addEnum(EnumStatus.class, name); + } +- public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability) +- { ++ ++ public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability) { + return addEnum(ToolMaterial.class, name, harvestLevel, maxUses, efficiency, damage, enchantability); + } +- public static EnumRarity addRarity(String name, EnumChatFormatting color, String displayName) +- { ++ ++ public static EnumRarity addRarity(String name, EnumChatFormatting color, String displayName) { + return addEnum(EnumRarity.class, name, color, displayName); + } + +- private static void setup() +- { +- if (isSetup) +- { +- return; ++ public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception { ++ try { ++ setFieldHandle.invokeExact(field, target, value); ++ } catch (Throwable e) { ++ Throwables.propagate(e); + } ++ } + +- try +- { +- Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); +- reflectionFactory = getReflectionFactory.invoke(null); +- newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class); +- newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class); +- newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); +- fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); ++ public static > T addEnum(Class enumType, String enumName, Object... paramValues) { ++ return addEnum(commonTypes, enumType, enumName, paramValues); + } + -+ public static WorldType addBukkitWorldType(String name) -+ { -+ if (!isSetup) -+ { -+ setup(); -+ } ++ @SuppressWarnings("rawtypes") ++ public static > T addEnum(Class[][] map, Class enumType, String enumName, ++ Object... paramValues) { ++ for (Class[] lookup : map) { ++ if (lookup[0] == enumType) { ++ Class[] paramTypes = new Class[lookup.length - 1]; ++ if (paramTypes.length > 0) { ++ System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length); ++ } ++ return addEnum(enumType, enumName, paramTypes, paramValues); ++ } + } +- catch (Exception e) +- { +- e.printStackTrace(); ++ return null; ++ } + ++ @SuppressWarnings("unchecked") ++ public static > T addEnum(Class enumType, String enumName, Class[] paramTypes, ++ Object[] paramValues) { ++ if (!extensibleEnumIface.isAssignableFrom(enumType)) { ++ throw new RuntimeException( ++ "Enum " + enumType.getName() + " was not made extensible, add it to Crucible configs."); + } + +- isSetup = true; +- } ++ try { ++ paramTypes = ArrayUtils.add(paramTypes, 0, String.class); ++ paramValues = ArrayUtils.add(paramValues, 0, enumName); + +- /* +- * Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+ +- * Also modified for use in decompiled code. +- * Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically +- */ +- private static Object getConstructorAccessor(Class enumClass, Class[] additionalParameterTypes) throws Exception +- { +- Class[] parameterTypes = new Class[additionalParameterTypes.length + 2]; +- parameterTypes[0] = String.class; +- parameterTypes[1] = int.class; +- System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length); +- return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes)); +- } ++ final Method creatorHandle = enumType.getMethod("dynamicCreate", paramTypes); ++ T newValue = (T) creatorHandle.invoke(null, paramValues); + +- private static < T extends Enum> T makeEnum(Class enumClass, String value, int ordinal, Class[] additionalTypes, Object[] additionalValues) throws Exception +- { +- Object[] parms = new Object[additionalValues.length + 2]; +- parms[0] = value; +- parms[1] = Integer.valueOf(ordinal); +- System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length); +- return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {parms})); ++ return newValue; ++ } catch (Exception e) { ++ e.printStackTrace(); ++ throw new RuntimeException(e.getMessage(), e); ++ } + } + +- public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception +- { +- field.setAccessible(true); +- Field modifiersField = Field.class.getDeclaredField("modifiers"); +- modifiersField.setAccessible(true); +- modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); +- Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); +- fieldAccessorSet.invoke(fieldAccessor, target, value); +- } ++ private static final Class extensibleEnumIface; ++ private static final MethodHandle setFieldHandle; + +- private static void blankField(Class enumClass, String fieldName) throws Exception +- { +- for (Field field : Class.class.getDeclaredFields()) +- { +- if (field.getName().contains(fieldName)) +- { +- field.setAccessible(true); +- setFailsafeFieldValue(field, enumClass, null); +- break; +- } ++ static { ++ try { ++ extensibleEnumIface = Class.forName("me.eigenraven.lwjgl3ify.IExtensibleEnum"); ++ Class unsafeHacks = Class.forName("me.eigenraven.lwjgl3ify.UnsafeHacks"); ++ Method setFieldM = unsafeHacks.getMethod("setField", Field.class, Object.class, Object.class); ++ setFieldHandle = MethodHandles.publicLookup() ++ .unreflect(setFieldM); ++ } catch (ReflectiveOperationException e) { ++ throw new RuntimeException(e); + } + } + +- private static void cleanEnumCache(Class enumClass) throws Exception ++ // Cauldron start ++ public static Biome addBukkitBiome(String name) + { +- blankField(enumClass, "enumConstantDirectory"); +- blankField(enumClass, "enumConstants"); ++ return (Biome)addEnum(Biome.class, name, new Class[0], new Object[0]); + } + +- public static > T addEnum(Class enumType, String enumName, Object... paramValues) ++ public static World.Environment addBukkitEnvironment(int id, String name) + { +- setup(); +- return addEnum(commonTypes, enumType, enumName, paramValues); ++ return (World.Environment)addEnum(World.Environment.class, name, new Class[] { Integer.TYPE }, new Object[] { Integer.valueOf(id) }); + } + +- @SuppressWarnings("rawtypes") +- public static > T addEnum(Class[][] map, Class enumType, String enumName, Object... paramValues) ++ public static WorldType addBukkitWorldType(String name) + { +- for (Class[] lookup : map) +- { +- if (lookup[0] == enumType) +- { +- Class[] paramTypes = new Class[lookup.length - 1]; +- if (paramTypes.length > 0) +- { +- System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length); +- } +- return addEnum(enumType, enumName, paramTypes, paramValues); +- } +- } +- return null; + WorldType worldType = addEnum(WorldType.class, name, new Class [] { String.class }, new Object[] { name }); + Map BY_NAME = ReflectionHelper.getPrivateValue(WorldType.class, null, "BY_NAME"); + BY_NAME.put(name.toUpperCase(), worldType); + + return worldType; -+ } -+ + } + +- @SuppressWarnings("unchecked") +- public static > T addEnum(Class enumType, String enumName, Class[] paramTypes, Object[] paramValues) +- { +- if (!isSetup) +- { +- setup(); +- } + public static EntityType addBukkitEntityType(String name, Class clazz, int typeId, boolean independent) { + String entityType = name.replace("-", "_").toUpperCase(); + EntityType bukkitType = addEnum(EntityType.class, entityType, new Class[] { String.class, Class.class, Integer.TYPE, Boolean.TYPE }, new Object[] { name, clazz, typeId, independent }); -+ + +- Field valuesField = null; +- Field[] fields = enumType.getDeclaredFields(); + Map NAME_MAP = ReflectionHelper.getPrivateValue(EntityType.class, null, "NAME_MAP"); + Map ID_MAP = ReflectionHelper.getPrivateValue(EntityType.class, null, "ID_MAP"); -+ + +- for (Field field : fields) +- { +- String name = field.getName(); +- if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards +- { +- valuesField = field; +- break; +- } +- } + NAME_MAP.put(name.toLowerCase(), bukkitType); + ID_MAP.put((short)typeId, bukkitType); -+ -+ + +- int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/; +- if (valuesField == null) +- { +- String valueType = String.format("[L%s;", enumType.getName().replace('.', '/')); + +- for (Field field : fields) +- { +- if ((field.getModifiers() & flags) == flags && +- field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't.. +- { +- valuesField = field; +- break; +- } +- } +- } + return bukkitType; + } -+ + +- if (valuesField == null) +- { +- FMLLog.severe("Could not find $VALUES field for enum: %s", enumType.getName()); +- FMLLog.severe("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF); +- FMLLog.severe("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')); +- FMLLog.severe("Fields:"); +- for (Field field : fields) +- { +- String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0'); +- FMLLog.severe(" %s %s: %s", mods, field.getName(), field.getType().getName()); +- } +- return null; +- } + public static InventoryType addInventoryType(TileEntity tileentity) + { + if (!IInventory.class.isAssignableFrom(tileentity.getClass())) return null; + String id = (String)TileEntity.classToNameMap.get(tileentity.getClass()); -+ -+ try -+ { + +- valuesField.setAccessible(true); +- + try + { +- T[] previousValues = (T[])valuesField.get(enumType); +- List values = new ArrayList(Arrays.asList(previousValues)); +- T newValue = (T)makeEnum(enumType, enumName, values.size(), paramTypes, paramValues); +- values.add(newValue); +- setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0))); +- cleanEnumCache(enumType); +- +- return newValue; + IInventory teInv = (IInventory)tileentity; + int size = teInv.getSizeInventory(); + return addEnum(org.bukkit.event.inventory.InventoryType.class, id, new Class[]{Integer.TYPE, String.class}, new Object[]{size, id}); -+ } -+ catch (Throwable e) -+ { + } +- catch (Exception e) ++ catch (Throwable e) + { +- e.printStackTrace(); +- throw new RuntimeException(e.getMessage(), e); + if (MinecraftServer.getServer().tileEntityConfig.enableTEInventoryWarning.getValue()) + { + logger.log(Level.WARN, "Could not create inventory type " + tileentity.getClass().getName() + " Exception: " + e.toString()); + logger.log(Level.WARN, "Could not determine default inventory size for type " + tileentity.getClass().getName() + " using size of 9"); + } + return addEnum(org.bukkit.event.inventory.InventoryType.class, id, new Class[]{Integer.TYPE, String.class}, new Object[]{9, id}); -+ } -+ } -+ // Cauldron end -+ - public static EnumAction addAction(String name) - { - return addEnum(EnumAction.class, name); -@@ -181,6 +264,10 @@ - - private static void cleanEnumCache(Class enumClass) throws Exception - { -+ // Cauldron start -+ // OpenJ9 moved the below fields -+ blankField(enumClass, "enumVars"); -+ // Cauldron end - blankField(enumClass, "enumConstantDirectory"); - blankField(enumClass, "enumConstants"); - } -@@ -280,6 +367,86 @@ } } -+ // Cauldron start -+ @SuppressWarnings("unchecked") -+ public static > T replaceEnum(Class enumType, String enumName, int ordinal, Class[] paramTypes, Object[] paramValues) -+ { -+ if (!isSetup) -+ { -+ setup(); -+ } -+ -+ Field valuesField = null; -+ Field[] fields = enumType.getDeclaredFields(); -+ -+ for (Field field : fields) -+ { -+ String name = field.getName(); -+ if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards -+ { -+ valuesField = field; -+ break; -+ } -+ } -+ -+ int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/; -+ if (valuesField == null) -+ { -+ String valueType = String.format("[L%s;", enumType.getName().replace('.', '/')); -+ -+ for (Field field : fields) -+ { -+ if ((field.getModifiers() & flags) == flags && -+ field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't.. -+ { -+ valuesField = field; -+ break; -+ } -+ } -+ } -+ -+ if (valuesField == null) -+ { -+ FMLLog.severe("Could not find $VALUES field for enum: %s", enumType.getName()); -+ FMLLog.severe("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF); -+ FMLLog.severe("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')); -+ FMLLog.severe("Fields:"); -+ for (Field field : fields) -+ { -+ String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0'); -+ FMLLog.severe(" %s %s: %s", mods, field.getName(), field.getType().getName()); -+ } -+ return null; -+ } -+ -+ valuesField.setAccessible(true); -+ try -+ { -+ Enum[] previousValues = (Enum[])(Enum[])valuesField.get(enumType); -+ Enum[] newValues = new Enum[previousValues.length]; -+ Enum newValue = null; -+ for (Enum enumValue : previousValues) -+ { -+ if (enumValue.ordinal() == ordinal) -+ { -+ newValue = makeEnum(enumType, enumName, ordinal, paramTypes, paramValues); -+ newValues[enumValue.ordinal()] = newValue; -+ } -+ else newValues[enumValue.ordinal()] = enumValue; -+ } -+ List values = new ArrayList(Arrays.asList(newValues)); -+ setFailsafeFieldValue(valuesField, null, values.toArray((Enum[])(Enum[])Array.newInstance(enumType, 0))); -+ cleanEnumCache(enumType); -+ return (T) newValue; -+ } -+ catch (Exception e) -+ { -+ e.printStackTrace(); -+ throw new RuntimeException(e.getMessage(), e); -+ } -+ } +- static +- { +- if (!isSetup) +- { +- setup(); +- } +- } ++// @SuppressWarnings("unchecked") ++// public static > T replaceEnum(Class enumType, String enumName, int ordinal, Class[] paramTypes, Object[] paramValues) ++// { ++// ++// Field valuesField = null; ++// Field[] fields = enumType.getDeclaredFields(); ++// ++// for (Field field : fields) ++// { ++// String name = field.getName(); ++// if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards ++// { ++// valuesField = field; ++// break; ++// } ++// } ++// ++// int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/; ++// if (valuesField == null) ++// { ++// String valueType = String.format("[L%s;", enumType.getName().replace('.', '/')); ++// ++// for (Field field : fields) ++// { ++// if ((field.getModifiers() & flags) == flags && ++// field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't.. ++// { ++// valuesField = field; ++// break; ++// } ++// } ++// } ++// ++// if (valuesField == null) ++// { ++// FMLLog.severe("Could not find $VALUES field for enum: %s", enumType.getName()); ++// FMLLog.severe("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF); ++// FMLLog.severe("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')); ++// FMLLog.severe("Fields:"); ++// for (Field field : fields) ++// { ++// String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0'); ++// FMLLog.severe(" %s %s: %s", mods, field.getName(), field.getType().getName()); ++// } ++// return null; ++// } ++// ++// valuesField.setAccessible(true); ++// try ++// { ++// Enum[] previousValues = (Enum[])(Enum[])valuesField.get(enumType); ++// Enum[] newValues = new Enum[previousValues.length]; ++// Enum newValue = null; ++// for (Enum enumValue : previousValues) ++// { ++// if (enumValue.ordinal() == ordinal) ++// { ++// newValue = makeEnum(enumType, enumName, ordinal, paramTypes, paramValues); ++// newValues[enumValue.ordinal()] = newValue; ++// } ++// else newValues[enumValue.ordinal()] = enumValue; ++// } ++// List values = new ArrayList(Arrays.asList(newValues)); ++// setFailsafeFieldValue(valuesField, null, values.toArray((Enum[])(Enum[])Array.newInstance(enumType, 0))); ++// return (T) newValue; ++// } ++// catch (Exception e) ++// { ++// e.printStackTrace(); ++// throw new RuntimeException(e.getMessage(), e); ++// } ++// } + // Cauldron end -+ - static - { - if (!isSetup) + } diff --git a/src/main/java/io/github/crucible/CrucibleCommand.java b/src/main/java/io/github/crucible/CrucibleCommand.java index 6329e8fd..25028c44 100644 --- a/src/main/java/io/github/crucible/CrucibleCommand.java +++ b/src/main/java/io/github/crucible/CrucibleCommand.java @@ -51,7 +51,8 @@ public static String generateInfo() { "Bukkit API implemented: 1.7.9-R0.3-SNAPSHOT\n" + "Plugins: " + Bukkit.getPluginManager().getPlugins().length + "\n&r" + "Mods: " + Loader.instance().getActiveModList().size() + - " &r| Loaded: " + Loader.instance().getModList().size() + "\n&r"; + " &r| Loaded: " + Loader.instance().getModList().size() + "\n&r" + + String.format("Java is %s, version %s, running on %s:%s:%s, installed at %s", System.getProperty("java.vm.name"), System.getProperty("java.version"), System.getProperty("os.name"), System.getProperty("os.arch"), System.getProperty("os.version"), System.getProperty("java.home")); return ChatColor.translateAlternateColorCodes('&', info); } diff --git a/src/main/java/io/github/crucible/CrucibleConfigs.java b/src/main/java/io/github/crucible/CrucibleConfigs.java index 989d013c..709a6682 100644 --- a/src/main/java/io/github/crucible/CrucibleConfigs.java +++ b/src/main/java/io/github/crucible/CrucibleConfigs.java @@ -1,14 +1,10 @@ package io.github.crucible; -import co.aikar.timings.Timings; -import co.aikar.timings.TimingsManager; -import net.cubespace.Yamler.Config.*; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.WorldServer; +import io.github.crucible.bootstrap.Lwjgl3ifyGlue; +import io.github.crucible.util.config.*; import java.io.File; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadMXBean; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -208,6 +204,9 @@ public class CrucibleConfigs extends YamlConfig { public String timings_serverName = "Crucible Server"; + @Comment("Enums to make extensible at runtime") + public List lwjgl3ify_extensibleEnums = new ArrayList<>(Arrays.asList(Lwjgl3ifyGlue.DEFAULT_EXTENSIBLE_ENUMS)); + private CrucibleConfigs() { CONFIG_FILE = new File("Crucible.yml"); CONFIG_MODE = ConfigMode.PATH_BY_UNDERSCORE; @@ -218,7 +217,6 @@ private CrucibleConfigs() { } catch (InvalidConfigurationException e) { e.printStackTrace(); } - configureTimings(); } public void save() { @@ -233,15 +231,6 @@ public int getTickTime() { return crucible_tickHandler_serverTickTime / crucible_tickHandler_serverTickRate; } - private void configureTimings() { - TimingsManager.privacy = timings_serverNamePrivacy; - TimingsManager.hiddenConfigs = timings_hiddenConfigEntries; - Timings.setVerboseTimingsEnabled(timings_verbose); - Timings.setHistoryInterval(timings_historyInterval * 20); - Timings.setHistoryLength(timings_historyLength * 20); - Timings.setTimingsEnabled(timings_enabledSinceServerStartup); - } - @Override public void reload() { try { @@ -250,17 +239,4 @@ public void reload() { e.printStackTrace(); } } - - //Mimics cauldron toggle behavior setting all fields fields that are not updated with the configs with the new values. - public void reapplyConfigs() { - for (WorldServer world : MinecraftServer.getServer().worlds) { - world.theChunkProviderServer.loadChunkOnProvideRequest = cauldron_settings_loadChunkOnRequest; - } - - ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); - if (mbean.isThreadContentionMonitoringSupported()) - mbean.setThreadContentionMonitoringEnabled(cauldron_debug_enableThreadContentionMonitoring); - else - CrucibleModContainer.logger.warn("Thread monitoring is not supported!"); - } } diff --git a/src/main/java/io/github/crucible/CrucibleModContainer.java b/src/main/java/io/github/crucible/CrucibleModContainer.java index 0d6b1133..b9b19c0c 100644 --- a/src/main/java/io/github/crucible/CrucibleModContainer.java +++ b/src/main/java/io/github/crucible/CrucibleModContainer.java @@ -1,18 +1,19 @@ package io.github.crucible; +import co.aikar.timings.Timings; +import co.aikar.timings.TimingsManager; import com.avaje.ebean.EbeanServer; import com.google.common.collect.ImmutableList; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; -import cpw.mods.fml.common.DummyModContainer; -import cpw.mods.fml.common.LoadController; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.ModMetadata; +import cpw.mods.fml.common.*; import cpw.mods.fml.common.event.*; import cpw.mods.fml.common.network.NetworkRegistry; import io.github.crucible.api.CrucibleAPI; +import io.github.crucible.bootstrap.CrucibleMetadata; import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; @@ -27,12 +28,14 @@ import java.io.File; import java.io.InputStream; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; import java.util.*; import java.util.regex.Pattern; @SuppressWarnings("UnstableApiUsage") public class CrucibleModContainer extends DummyModContainer implements Plugin { - public static Logger logger = LogManager.getLogger("Crucible"); //Crucible - note: use it only after forge configured the logger! + public static final Logger logger = LogManager.getLogger("Crucible"); public static CrucibleModContainer instance; public static Metrics metrics; private PluginLoader dummyPluginLoader; @@ -63,6 +66,7 @@ public boolean registerBus(EventBus bus, LoadController controller) { public void modConstruction(FMLConstructionEvent evt) { NetworkRegistry.INSTANCE.register(this, this.getClass(), "*", evt.getASMHarvestedData()); logger.info("Crucible DummyMod injected successfully!"); + configureTimings(); } @Subscribe @@ -255,4 +259,26 @@ public static boolean isModPlugin(Plugin plugin) { return plugin.getClass().getClassLoader().equals(Loader.instance().getModClassLoader()) || plugin.getClass().getClassLoader().equals(CrucibleModContainer.class.getClassLoader()); } + + public static void configureTimings() { + TimingsManager.privacy = CrucibleConfigs.configs.timings_serverNamePrivacy; + TimingsManager.hiddenConfigs = CrucibleConfigs.configs.timings_hiddenConfigEntries; + Timings.setVerboseTimingsEnabled(CrucibleConfigs.configs.timings_verbose); + Timings.setHistoryInterval(CrucibleConfigs.configs.timings_historyInterval * 20); + Timings.setHistoryLength(CrucibleConfigs.configs.timings_historyLength * 20); + Timings.setTimingsEnabled(CrucibleConfigs.configs.timings_enabledSinceServerStartup); + } + + //Mimics cauldron toggle behavior setting all fields that are not updated with the configs with the new values. + public static void reapplyConfigs() { + for (WorldServer world : MinecraftServer.getServer().worlds) { + world.theChunkProviderServer.loadChunkOnProvideRequest = CrucibleConfigs.configs.cauldron_settings_loadChunkOnRequest; + } + + ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); + if (mbean.isThreadContentionMonitoringSupported()) + mbean.setThreadContentionMonitoringEnabled(CrucibleConfigs.configs.cauldron_debug_enableThreadContentionMonitoring); + else + logger.warn("Thread monitoring is not supported!"); + } } diff --git a/src/main/java/io/github/crucible/CrucibleMetadata.java b/src/main/java/io/github/crucible/bootstrap/CrucibleMetadata.java similarity index 96% rename from src/main/java/io/github/crucible/CrucibleMetadata.java rename to src/main/java/io/github/crucible/bootstrap/CrucibleMetadata.java index 27a982e1..9848cec5 100644 --- a/src/main/java/io/github/crucible/CrucibleMetadata.java +++ b/src/main/java/io/github/crucible/bootstrap/CrucibleMetadata.java @@ -1,6 +1,7 @@ -package io.github.crucible; +package io.github.crucible.bootstrap; import cpw.mods.fml.common.FMLLog; +import net.minecraft.launchwrapper.LaunchClassLoader; import java.net.URL; import java.util.Enumeration; diff --git a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java index 01b03777..5388b6c0 100644 --- a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java +++ b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java @@ -1,6 +1,7 @@ package io.github.crucible.bootstrap; -import io.github.crucible.CrucibleMetadata; +import cpw.mods.fml.common.launcher.FMLTweaker; +import net.minecraft.launchwrapper.LaunchClassLoader; import java.io.File; import java.io.FileReader; @@ -10,17 +11,17 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; -import java.util.Properties; -import java.util.stream.Stream; +import java.util.*; // DO NOT TRY TO LOAD ANY MINECRAFT CLASS FROM HERE, THIS CLASS IS LOADED BEFORE EVERYTHING ON THE SERVER ENTRYPOINT +// Also avoid using streams here public class CrucibleServerMainHook { private static final String[] REPOS = new String[]{ - "https://github.com/juanmuscaria/maven/raw/master/", - "https://github.com/juanmuscaria/maven/raw/master/ThermosLibs/", - "https://maven.minecraftforge.net/", - "https://libraries.minecraft.net/", - "https://repo.maven.apache.org/maven2/" + "https://github.com/juanmuscaria/maven/raw/master/", + "https://github.com/juanmuscaria/maven/raw/master/ThermosLibs/", + "https://maven.minecraftforge.net/", + "https://libraries.minecraft.net/", + "https://repo.maven.apache.org/maven2/" }; private static final Path LIBRARY_ROOT = Paths.get("libraries").toAbsolutePath(); public static final PrintStream originalOut = System.out; @@ -35,7 +36,7 @@ public static void relaunchMain(String[] args) throws Exception { try { internalProperties.load(CrucibleServerMainHook.class.getClassLoader().getResourceAsStream("inject.properties")); internalProperties.store(Files.newOutputStream(injectFile.toPath()), - "All properties in this file will be injected into System Properties before the server starts. Useful for shared hostings"); + "All properties in this file will be injected into System Properties before the server starts. Useful for shared hostings"); } catch (IOException e) { throw new RuntimeException(e); } @@ -46,10 +47,19 @@ public static void relaunchMain(String[] args) throws Exception { } catch (IOException e) { throw new RuntimeException(e); } - propertiesToInject.forEach((key, value) -> System.setProperty((String) key, (String) value)); + + for (Map.Entry entry : propertiesToInject.entrySet()) { + System.setProperty((String) entry.getKey(), (String) entry.getValue()); + } + + System.out.println("[Crucible] This Crucible version has embedded a heavily modified version of lwjgl3ify (https://github.com/GTNewHorizons/lwjgl3ify/)."); + System.out.println("[Crucible] Do not, I repeat DO NOT report any issues to upstream, any issue you encounter is mostly likely because of a hybrid environment. Do open a Crucible issue instead."); + Lwjgl3ifyGlue.checkJava(); if (!verifyLibraries()) { setupLibraries(); + System.out.println("[Crucible] Crucible installed! You need to start the server again."); + System.exit(0); } else { System.out.println("[Crucible] Everything in check, booting the server"); } @@ -77,14 +87,28 @@ private static void setupLibraries() throws InterruptedException { if (Files.exists(LIBRARY_ROOT) && !Files.isDirectory(LIBRARY_ROOT)) { throw new IllegalStateException(String.format("Library root '%s' is a file, aborting startup!", LIBRARY_ROOT.toAbsolutePath())); } + String[] userDefinedRepos = System.getProperty("crucible.libraryRepos", "").split(" "); - LibraryManager.downloadMavenLibraries(LIBRARY_ROOT, Stream.of(REPOS, userDefinedRepos).flatMap(Stream::of) - .filter(s -> !s.isEmpty()).toArray(String[]::new), CrucibleMetadata.NEEDED_LIBRARIES); + List list = new ArrayList<>(); + for (String[] strings : Arrays.asList(REPOS, userDefinedRepos)) { + for (String s : strings) { + if (!s.isEmpty()) { + list.add(s); + } + } + } + LibraryManager.downloadMavenLibraries(LIBRARY_ROOT, list.toArray(new String[0]), CrucibleMetadata.NEEDED_LIBRARIES); } public static void restoreStreams() { System.setOut(originalOut); System.setErr(originalErr); } + + // Too lazy for a coremod + public static void coremodHandleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { + Lwjgl3ifyGlue.doCoremodWork(classLoader); + classLoader.addClassLoaderExclusion("io.github.crucible.bootstrap."); + } } \ No newline at end of file diff --git a/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java new file mode 100644 index 00000000..96b57db9 --- /dev/null +++ b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java @@ -0,0 +1,111 @@ +package io.github.crucible.bootstrap; + +import net.minecraft.launchwrapper.LaunchClassLoader; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class Lwjgl3ifyGlue { + public static final String[] DEFAULT_EXTENSIBLE_ENUMS = new String[] { + // From EnumHelper + "net.minecraft.item.EnumAction", "net.minecraft.item.ItemArmor$ArmorMaterial", + "net.minecraft.entity.item.EntityPainting$EnumArt", "net.minecraft.entity.EnumCreatureAttribute", + "net.minecraft.entity.EnumCreatureType", + "net.minecraft.world.gen.structure.StructureStrongholdPieces$Stronghold$Door", + "net.minecraft.enchantment.EnumEnchantmentType", "net.minecraft.entity.Entity$EnumEntitySize", + "net.minecraft.block.BlockPressurePlate$Sensitivity", + "net.minecraft.util.MovingObjectPosition$MovingObjectType", "net.minecraft.world.EnumSkyBlock", + "net.minecraft.entity.player.EntityPlayer$EnumStatus", "net.minecraft.item.Item$ToolMaterial", + "net.minecraft.item.EnumRarity", + // + "net.minecraftforge.event.terraingen.PopulateChunkEvent$Populate$EventType", + "net.minecraftforge.event.terraingen.InitMapGenEvent$EventType", + "net.minecraftforge.event.terraingen.OreGenEvent$GenerateMinable$EventType", + "net.minecraftforge.event.terraingen.DecorateBiomeEvent$Decorate$EventType", + // From GTNH crashes + "vswe.stevesfactory.Localization", "vswe.stevesfactory.blocks.ClusterMethodRegistration", + "vswe.stevesfactory.blocks.ConnectionBlockType", "vswe.stevesfactory.components.ComponentType", + "vswe.stevesfactory.components.ConnectionSet", "vswe.stevesfactory.components.ConnectionOption", + "ic2.core.init.InternalName", "gregtech.api.enums.Element", "gregtech.api.enums.OrePrefixes", + "net.minecraft.client.audio.MusicTicker$MusicType", "org.bukkit.Material", + "buildcraft.api.transport.IPipeTile.PipeType", "thaumcraft.common.entities.golems.EnumGolemType", + // Non-GTNH Mods Compat + // The Lord of the Rings Mod: Legacy + "net.minecraft.event.HoverEvent$Action", + // Reika's mods + "net.minecraft.client.audio.SoundCategory", + "Reika.RotaryCraft.TileEntities.Processing.TileEntityFuelConverter$Conversions", + "Reika.DragonAPI.ModInteract.Bees.BeeAlleleRegistry$Fertility", + "Reika.DragonAPI.ModInteract.Bees.BeeAlleleRegistry$Speeds", + "Reika.DragonAPI.ModInteract.Bees.BeeAlleleRegistry$Flowering", + "Reika.DragonAPI.ModInteract.Bees.BeeAlleleRegistry$Territory", + "Reika.DragonAPI.ModInteract.Bees.BeeAlleleRegistry$Life", + "Reika.DragonAPI.ModInteract.Bees.ButterflyAlleleRegistry$Fertility", + "Reika.DragonAPI.ModInteract.Bees.ButterflyAlleleRegistry$Life", + // Et Futurum Requiem + "net.minecraft.world.WorldSettings$GameType", + // Bukkit Enums + "org.bukkit.Material", + "org.bukkit.block.Biome", + "org.bukkit.World$Environment", + "org.bukkit.WorldType", + "org.bukkit.entity.EntityType", + "org.bukkit.event.inventory.InventoryType", + }; + + public static void checkJava() { + if (!Boolean.getBoolean("lwjgl3ify.skipjavacheck")) { + final String specVer = System.getProperty("java.specification.version"); + if (specVer.equals("17")) { + try { + final Class cRuntime = Class.forName("java.lang.Runtime"); + final Class cRuntimeVersion = Class.forName("java.lang.Runtime$Version"); + final MethodHandles.Lookup lookup = MethodHandles.publicLookup(); + final MethodHandle mRuntimeVersion = lookup + .findStatic(cRuntime, "version", MethodType.methodType(cRuntimeVersion)); + final MethodHandle mVersionParse = lookup + .findStatic(cRuntimeVersion, "parse", MethodType.methodType(cRuntimeVersion, String.class)); + final MethodHandle mVersionCompareTo = lookup.findVirtual( + cRuntimeVersion, + "compareToIgnoreOptional", + MethodType.methodType(int.class, cRuntimeVersion)); + final Object runtimeVersion = mRuntimeVersion.invoke(); + final Object ver17_0_6 = mVersionParse.invoke("17.0.6"); + final int cmpResult = (int) mVersionCompareTo.invoke(runtimeVersion, ver17_0_6); + if (cmpResult < 0) { + System.err.println("================================================================="); + System.err.println("Upgrade your Java 17 install to Java 17.0.6 for lwjgl3ify to work"); + System.err.println("Your Java version is: " + runtimeVersion); + System.err.println("================================================================="); + System.exit(1); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + } + } + + public static void doCoremodWork(LaunchClassLoader launchLoader) { + launchLoader.addClassLoaderExclusion("com.sun"); + launchLoader.addClassLoaderExclusion("com.oracle"); + launchLoader.addClassLoaderExclusion("javax"); + launchLoader.addClassLoaderExclusion("jdk"); + launchLoader.addClassLoaderExclusion("org.ietf.jgss"); + launchLoader.addClassLoaderExclusion("org.jcp.xml.dsig.internal"); + launchLoader.addClassLoaderExclusion("org.omg"); + launchLoader.addClassLoaderExclusion("org.w3c.dom"); + launchLoader.addClassLoaderExclusion("org.xml.sax"); + launchLoader.addClassLoaderExclusion("org.hotswap.agent"); + launchLoader.addClassLoaderExclusion("org.lwjglx.debug"); + try { + Class.forName("javax.script.ScriptEngineManager"); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + launchLoader.registerTransformer("me.eigenraven.lwjgl3ify.core.LwjglRedirectTransformer"); + launchLoader.registerTransformer("me.eigenraven.lwjgl3ify.core.UnfinalizeObjectHoldersTransformer"); + } +} diff --git a/src/main/java/net/cubespace/Yamler/Config/BaseConfig.java b/src/main/java/io/github/crucible/util/config/BaseConfig.java similarity index 94% rename from src/main/java/net/cubespace/Yamler/Config/BaseConfig.java rename to src/main/java/io/github/crucible/util/config/BaseConfig.java index 0530a9ab..26d844e9 100644 --- a/src/main/java/net/cubespace/Yamler/Config/BaseConfig.java +++ b/src/main/java/io/github/crucible/util/config/BaseConfig.java @@ -1,11 +1,8 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; /** * @author geNAZt (fabian.fassbender42@googlemail.com) diff --git a/src/main/java/net/cubespace/Yamler/Config/BaseConfigMapper.java b/src/main/java/io/github/crucible/util/config/BaseConfigMapper.java similarity index 99% rename from src/main/java/net/cubespace/Yamler/Config/BaseConfigMapper.java rename to src/main/java/io/github/crucible/util/config/BaseConfigMapper.java index f68d50d8..c1ef3783 100644 --- a/src/main/java/net/cubespace/Yamler/Config/BaseConfigMapper.java +++ b/src/main/java/io/github/crucible/util/config/BaseConfigMapper.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; diff --git a/src/main/java/net/cubespace/Yamler/Config/Comment.java b/src/main/java/io/github/crucible/util/config/Comment.java similarity index 89% rename from src/main/java/net/cubespace/Yamler/Config/Comment.java rename to src/main/java/io/github/crucible/util/config/Comment.java index 2e8b03b4..abf412c3 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Comment.java +++ b/src/main/java/io/github/crucible/util/config/Comment.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/net/cubespace/Yamler/Config/Comments.java b/src/main/java/io/github/crucible/util/config/Comments.java similarity index 89% rename from src/main/java/net/cubespace/Yamler/Config/Comments.java rename to src/main/java/io/github/crucible/util/config/Comments.java index 55da9288..2114bd09 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Comments.java +++ b/src/main/java/io/github/crucible/util/config/Comments.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/net/cubespace/Yamler/Config/Config.java b/src/main/java/io/github/crucible/util/config/Config.java similarity index 58% rename from src/main/java/net/cubespace/Yamler/Config/Config.java rename to src/main/java/io/github/crucible/util/config/Config.java index 125849ae..bc2745bb 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Config.java +++ b/src/main/java/io/github/crucible/util/config/Config.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; @Deprecated public class Config extends YamlConfig { diff --git a/src/main/java/net/cubespace/Yamler/Config/ConfigBasic.java b/src/main/java/io/github/crucible/util/config/ConfigBasic.java similarity index 60% rename from src/main/java/net/cubespace/Yamler/Config/ConfigBasic.java rename to src/main/java/io/github/crucible/util/config/ConfigBasic.java index bba09419..51c78dde 100644 --- a/src/main/java/net/cubespace/Yamler/Config/ConfigBasic.java +++ b/src/main/java/io/github/crucible/util/config/ConfigBasic.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; @Deprecated public class ConfigBasic extends BaseConfig { diff --git a/src/main/java/net/cubespace/Yamler/Config/ConfigMapper.java b/src/main/java/io/github/crucible/util/config/ConfigMapper.java similarity index 96% rename from src/main/java/net/cubespace/Yamler/Config/ConfigMapper.java rename to src/main/java/io/github/crucible/util/config/ConfigMapper.java index 26721e78..f06fc577 100644 --- a/src/main/java/net/cubespace/Yamler/Config/ConfigMapper.java +++ b/src/main/java/io/github/crucible/util/config/ConfigMapper.java @@ -1,6 +1,6 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; -import net.cubespace.Yamler.Config.Converter.Converter; +import io.github.crucible.util.config.converter.Converter; import java.lang.reflect.Field; import java.lang.reflect.Modifier; diff --git a/src/main/java/net/cubespace/Yamler/Config/ConfigMode.java b/src/main/java/io/github/crucible/util/config/ConfigMode.java similarity index 78% rename from src/main/java/net/cubespace/Yamler/Config/ConfigMode.java rename to src/main/java/io/github/crucible/util/config/ConfigMode.java index 26dbb7dd..c5cac22c 100644 --- a/src/main/java/net/cubespace/Yamler/Config/ConfigMode.java +++ b/src/main/java/io/github/crucible/util/config/ConfigMode.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; /** * @author geNAZt (fabian.fassbender42@googlemail.com) diff --git a/src/main/java/net/cubespace/Yamler/Config/ConfigSection.java b/src/main/java/io/github/crucible/util/config/ConfigSection.java similarity index 99% rename from src/main/java/net/cubespace/Yamler/Config/ConfigSection.java rename to src/main/java/io/github/crucible/util/config/ConfigSection.java index dcefbefd..66f7f73f 100644 --- a/src/main/java/net/cubespace/Yamler/Config/ConfigSection.java +++ b/src/main/java/io/github/crucible/util/config/ConfigSection.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.util.LinkedHashMap; import java.util.Map; diff --git a/src/main/java/net/cubespace/Yamler/Config/IConfig.java b/src/main/java/io/github/crucible/util/config/IConfig.java similarity index 93% rename from src/main/java/net/cubespace/Yamler/Config/IConfig.java rename to src/main/java/io/github/crucible/util/config/IConfig.java index 7e5853f6..0e9ef837 100644 --- a/src/main/java/net/cubespace/Yamler/Config/IConfig.java +++ b/src/main/java/io/github/crucible/util/config/IConfig.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.io.File; diff --git a/src/main/java/net/cubespace/Yamler/Config/InternalConverter.java b/src/main/java/io/github/crucible/util/config/InternalConverter.java similarity index 91% rename from src/main/java/net/cubespace/Yamler/Config/InternalConverter.java rename to src/main/java/io/github/crucible/util/config/InternalConverter.java index 914596be..37daeb72 100644 --- a/src/main/java/net/cubespace/Yamler/Config/InternalConverter.java +++ b/src/main/java/io/github/crucible/util/config/InternalConverter.java @@ -1,7 +1,11 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; -import net.cubespace.Yamler.Config.Converter.Converter; -import net.cubespace.Yamler.Config.Converter.Primitive; +import io.github.crucible.util.config.converter.Array; +import io.github.crucible.util.config.converter.Config; +import io.github.crucible.util.config.converter.Map; +import io.github.crucible.util.config.converter.Set; +import io.github.crucible.util.config.converter.Converter; +import io.github.crucible.util.config.converter.Primitive; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -21,11 +25,11 @@ public class InternalConverter { public InternalConverter() { try { addConverter(Primitive.class); - addConverter(net.cubespace.Yamler.Config.Converter.Config.class); - addConverter(net.cubespace.Yamler.Config.Converter.List.class); - addConverter(net.cubespace.Yamler.Config.Converter.Map.class); - addConverter(net.cubespace.Yamler.Config.Converter.Array.class); - addConverter(net.cubespace.Yamler.Config.Converter.Set.class); + addConverter(Config.class); + addConverter(io.github.crucible.util.config.converter.List.class); + addConverter(Map.class); + addConverter(Array.class); + addConverter(Set.class); } catch (InvalidConverterException e) { throw new IllegalStateException(e); } diff --git a/src/main/java/net/cubespace/Yamler/Config/InvalidConfigurationException.java b/src/main/java/io/github/crucible/util/config/InvalidConfigurationException.java similarity index 91% rename from src/main/java/net/cubespace/Yamler/Config/InvalidConfigurationException.java rename to src/main/java/io/github/crucible/util/config/InvalidConfigurationException.java index 67b0d4fa..e803974f 100644 --- a/src/main/java/net/cubespace/Yamler/Config/InvalidConfigurationException.java +++ b/src/main/java/io/github/crucible/util/config/InvalidConfigurationException.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; /** * @author geNAZt (fabian.fassbender42@googlemail.com) diff --git a/src/main/java/net/cubespace/Yamler/Config/InvalidConverterException.java b/src/main/java/io/github/crucible/util/config/InvalidConverterException.java similarity index 91% rename from src/main/java/net/cubespace/Yamler/Config/InvalidConverterException.java rename to src/main/java/io/github/crucible/util/config/InvalidConverterException.java index 2b95e072..6431cbdf 100644 --- a/src/main/java/net/cubespace/Yamler/Config/InvalidConverterException.java +++ b/src/main/java/io/github/crucible/util/config/InvalidConverterException.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; /** * @author geNAZt (fabian.fassbender42@googlemail.com) diff --git a/src/main/java/net/cubespace/Yamler/Config/MapConfigMapper.java b/src/main/java/io/github/crucible/util/config/MapConfigMapper.java similarity index 63% rename from src/main/java/net/cubespace/Yamler/Config/MapConfigMapper.java rename to src/main/java/io/github/crucible/util/config/MapConfigMapper.java index b2a92e82..770fa733 100644 --- a/src/main/java/net/cubespace/Yamler/Config/MapConfigMapper.java +++ b/src/main/java/io/github/crucible/util/config/MapConfigMapper.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; @Deprecated public class MapConfigMapper extends YamlConfigMapper { diff --git a/src/main/java/net/cubespace/Yamler/Config/Path.java b/src/main/java/io/github/crucible/util/config/Path.java similarity index 89% rename from src/main/java/net/cubespace/Yamler/Config/Path.java rename to src/main/java/io/github/crucible/util/config/Path.java index 89bb01f0..c59f8301 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Path.java +++ b/src/main/java/io/github/crucible/util/config/Path.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/net/cubespace/Yamler/Config/PreserveStatic.java b/src/main/java/io/github/crucible/util/config/PreserveStatic.java similarity index 88% rename from src/main/java/net/cubespace/Yamler/Config/PreserveStatic.java rename to src/main/java/io/github/crucible/util/config/PreserveStatic.java index 0005b09f..b675feb4 100644 --- a/src/main/java/net/cubespace/Yamler/Config/PreserveStatic.java +++ b/src/main/java/io/github/crucible/util/config/PreserveStatic.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/net/cubespace/Yamler/Config/SerializeOptions.java b/src/main/java/io/github/crucible/util/config/SerializeOptions.java similarity index 91% rename from src/main/java/net/cubespace/Yamler/Config/SerializeOptions.java rename to src/main/java/io/github/crucible/util/config/SerializeOptions.java index 9a769cb6..099cebc6 100644 --- a/src/main/java/net/cubespace/Yamler/Config/SerializeOptions.java +++ b/src/main/java/io/github/crucible/util/config/SerializeOptions.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/net/cubespace/Yamler/Config/YamlConfig.java b/src/main/java/io/github/crucible/util/config/YamlConfig.java similarity index 99% rename from src/main/java/net/cubespace/Yamler/Config/YamlConfig.java rename to src/main/java/io/github/crucible/util/config/YamlConfig.java index 6b699401..a8402c19 100644 --- a/src/main/java/net/cubespace/Yamler/Config/YamlConfig.java +++ b/src/main/java/io/github/crucible/util/config/YamlConfig.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; import java.io.File; import java.io.IOException; diff --git a/src/main/java/net/cubespace/Yamler/Config/YamlConfigMapper.java b/src/main/java/io/github/crucible/util/config/YamlConfigMapper.java similarity index 64% rename from src/main/java/net/cubespace/Yamler/Config/YamlConfigMapper.java rename to src/main/java/io/github/crucible/util/config/YamlConfigMapper.java index 73677827..7b0d3cd3 100644 --- a/src/main/java/net/cubespace/Yamler/Config/YamlConfigMapper.java +++ b/src/main/java/io/github/crucible/util/config/YamlConfigMapper.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config; +package io.github.crucible.util.config; @Deprecated public class YamlConfigMapper extends BaseConfigMapper { diff --git a/src/main/java/net/cubespace/Yamler/Config/Converter/Array.java b/src/main/java/io/github/crucible/util/config/converter/Array.java similarity index 94% rename from src/main/java/net/cubespace/Yamler/Config/Converter/Array.java rename to src/main/java/io/github/crucible/util/config/converter/Array.java index db279a46..969f9072 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Converter/Array.java +++ b/src/main/java/io/github/crucible/util/config/converter/Array.java @@ -1,6 +1,6 @@ -package net.cubespace.Yamler.Config.Converter; +package io.github.crucible.util.config.converter; -import net.cubespace.Yamler.Config.InternalConverter; +import io.github.crucible.util.config.InternalConverter; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; diff --git a/src/main/java/net/cubespace/Yamler/Config/Converter/Config.java b/src/main/java/io/github/crucible/util/config/converter/Config.java similarity index 88% rename from src/main/java/net/cubespace/Yamler/Config/Converter/Config.java rename to src/main/java/io/github/crucible/util/config/converter/Config.java index 0db9386c..1c34527c 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Converter/Config.java +++ b/src/main/java/io/github/crucible/util/config/converter/Config.java @@ -1,8 +1,8 @@ -package net.cubespace.Yamler.Config.Converter; +package io.github.crucible.util.config.converter; -import net.cubespace.Yamler.Config.ConfigSection; -import net.cubespace.Yamler.Config.InternalConverter; -import net.cubespace.Yamler.Config.YamlConfig; +import io.github.crucible.util.config.InternalConverter; +import io.github.crucible.util.config.ConfigSection; +import io.github.crucible.util.config.YamlConfig; import java.lang.reflect.ParameterizedType; import java.util.Map; diff --git a/src/main/java/net/cubespace/Yamler/Config/Converter/Converter.java b/src/main/java/io/github/crucible/util/config/converter/Converter.java similarity index 97% rename from src/main/java/net/cubespace/Yamler/Config/Converter/Converter.java rename to src/main/java/io/github/crucible/util/config/converter/Converter.java index e72fd5a6..39b2ffc8 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Converter/Converter.java +++ b/src/main/java/io/github/crucible/util/config/converter/Converter.java @@ -1,4 +1,4 @@ -package net.cubespace.Yamler.Config.Converter; +package io.github.crucible.util.config.converter; import java.lang.reflect.ParameterizedType; diff --git a/src/main/java/net/cubespace/Yamler/Config/Converter/List.java b/src/main/java/io/github/crucible/util/config/converter/List.java similarity index 94% rename from src/main/java/net/cubespace/Yamler/Config/Converter/List.java rename to src/main/java/io/github/crucible/util/config/converter/List.java index a98bbbb6..b7fd9e6b 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Converter/List.java +++ b/src/main/java/io/github/crucible/util/config/converter/List.java @@ -1,6 +1,6 @@ -package net.cubespace.Yamler.Config.Converter; +package io.github.crucible.util.config.converter; -import net.cubespace.Yamler.Config.*; +import io.github.crucible.util.config.InternalConverter; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; diff --git a/src/main/java/net/cubespace/Yamler/Config/Converter/Map.java b/src/main/java/io/github/crucible/util/config/converter/Map.java similarity index 96% rename from src/main/java/net/cubespace/Yamler/Config/Converter/Map.java rename to src/main/java/io/github/crucible/util/config/converter/Map.java index d35fe545..c7e17d19 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Converter/Map.java +++ b/src/main/java/io/github/crucible/util/config/converter/Map.java @@ -1,7 +1,7 @@ -package net.cubespace.Yamler.Config.Converter; +package io.github.crucible.util.config.converter; -import net.cubespace.Yamler.Config.ConfigSection; -import net.cubespace.Yamler.Config.InternalConverter; +import io.github.crucible.util.config.ConfigSection; +import io.github.crucible.util.config.InternalConverter; import java.lang.reflect.ParameterizedType; import java.util.HashMap; diff --git a/src/main/java/net/cubespace/Yamler/Config/Converter/Primitive.java b/src/main/java/io/github/crucible/util/config/converter/Primitive.java similarity index 94% rename from src/main/java/net/cubespace/Yamler/Config/Converter/Primitive.java rename to src/main/java/io/github/crucible/util/config/converter/Primitive.java index 28598c3a..08757b54 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Converter/Primitive.java +++ b/src/main/java/io/github/crucible/util/config/converter/Primitive.java @@ -1,6 +1,6 @@ -package net.cubespace.Yamler.Config.Converter; +package io.github.crucible.util.config.converter; -import net.cubespace.Yamler.Config.InternalConverter; +import io.github.crucible.util.config.InternalConverter; import java.lang.reflect.ParameterizedType; import java.util.HashSet; diff --git a/src/main/java/net/cubespace/Yamler/Config/Converter/Set.java b/src/main/java/io/github/crucible/util/config/converter/Set.java similarity index 95% rename from src/main/java/net/cubespace/Yamler/Config/Converter/Set.java rename to src/main/java/io/github/crucible/util/config/converter/Set.java index 30ebfad7..f688b7b4 100644 --- a/src/main/java/net/cubespace/Yamler/Config/Converter/Set.java +++ b/src/main/java/io/github/crucible/util/config/converter/Set.java @@ -1,6 +1,6 @@ -package net.cubespace.Yamler.Config.Converter; +package io.github.crucible.util.config.converter; -import net.cubespace.Yamler.Config.*; +import io.github.crucible.util.config.InternalConverter; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; diff --git a/src/main/java/me/eigenraven/lwjgl3ify/IExtensibleEnum.java b/src/main/java/me/eigenraven/lwjgl3ify/IExtensibleEnum.java new file mode 100644 index 00000000..e1a55261 --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/IExtensibleEnum.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) Forge Development LLC and contributors SPDX-License-Identifier: LGPL-2.1-only + */ +package me.eigenraven.lwjgl3ify; + +/** + * To be implemented on vanilla enums that should be enhanced with ASM to be extensible. If this is implemented on a + * class, the class must define a static method called "create" which takes a String (enum name), and the rest of the + * parameters matching a constructor. + *

+ * For example, an enum with the constructor {@code MyEnum(Object foo)} would require the method: + * + *

+ *
+ * public static MyEnum create(String name, Object foo) {
+ *     throw new IllegalStateException("Enum not extended");
+ * }
+ * 
+ * + * The method contents will be replaced with ASM at runtime. Multiple {@code create} methods can be + * defined as long as each matches a constructor. + */ +public interface IExtensibleEnum { + + /** + * Called by generated factory code to do any post-constructor setup required by the enum. Should not be called + * manually. + */ + @Deprecated + default void init() {} +} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/UnsafeHacks.java b/src/main/java/me/eigenraven/lwjgl3ify/UnsafeHacks.java new file mode 100644 index 00000000..ac8a6711 --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/UnsafeHacks.java @@ -0,0 +1,99 @@ +/* + * Minecraft Forge Copyright (c) 2016-2019. This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the Free Software Foundation version 2.1 of + * the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. You should have received a copy of the GNU Lesser General Public License along with this + * library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +package me.eigenraven.lwjgl3ify; + +import java.lang.reflect.Field; +import java.util.Optional; + +@SuppressWarnings({ "restriction", "sunapi" }) +public class UnsafeHacks { + + private static final sun.misc.Unsafe UNSAFE; + + static { + try { + final Field theUnsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + UNSAFE = (sun.misc.Unsafe) theUnsafe.get(null); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException("BARF!", e); + } + } + + @SuppressWarnings("unchecked") + public static T newInstance(Class clazz) { + try { + return (T) UNSAFE.allocateInstance(clazz); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } + } + + @SuppressWarnings("unchecked") + public static T getField(Field field, Object object) { + if (object == null) { + long offset = UNSAFE.staticFieldOffset(field); + Object base = UNSAFE.staticFieldBase(field); + return (T) UNSAFE.getObject(base, offset); + } else { + long offset = UNSAFE.objectFieldOffset(field); + return (T) UNSAFE.getObject(object, offset); + } + } + + public static void setField(Field data, Object object, Object value) { + if (object == null) { + long offset = UNSAFE.staticFieldOffset(data); + Object base = UNSAFE.staticFieldBase(data); + UNSAFE.putObject(base, offset, value); + } else { + long offset = UNSAFE.objectFieldOffset(data); + UNSAFE.putObject(object, offset, value); + } + } + + public static int getIntField(Field field, Object object) { + if (object == null) { + long offset = UNSAFE.staticFieldOffset(field); + Object base = UNSAFE.staticFieldBase(field); + return UNSAFE.getInt(base, offset); + } else { + long offset = UNSAFE.objectFieldOffset(field); + return UNSAFE.getInt(object, offset); + } + } + + public static void setIntField(Field data, Object object, int value) { + if (object == null) { + long offset = UNSAFE.staticFieldOffset(data); + Object base = UNSAFE.staticFieldBase(data); + UNSAFE.putInt(base, offset, value); + } else { + long offset = UNSAFE.objectFieldOffset(data); + UNSAFE.putInt(object, offset, value); + } + } + + // Make sure we don't crash if any future versions change field names + private static Optional findField(Class clazz, String name) { + for (Field f : clazz.getDeclaredFields()) { + if (f.getName() + .equals(name)) { + return Optional.of(f); + } + } + return Optional.empty(); + } + + public static void cleanEnumCache(Class> enumClass) throws Exception { + findField(Class.class, "enumConstantDirectory").ifPresent(f -> setField(f, enumClass, null)); + findField(Class.class, "enumConstants").ifPresent(f -> setField(f, enumClass, null)); + } +} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/WasFinalObjectHolder.java b/src/main/java/me/eigenraven/lwjgl3ify/WasFinalObjectHolder.java new file mode 100644 index 00000000..f91c600c --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/WasFinalObjectHolder.java @@ -0,0 +1,10 @@ +package me.eigenraven.lwjgl3ify; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface WasFinalObjectHolder {} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/api/ConfigUtils.java b/src/main/java/me/eigenraven/lwjgl3ify/api/ConfigUtils.java new file mode 100644 index 00000000..228854a7 --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/api/ConfigUtils.java @@ -0,0 +1,34 @@ +package me.eigenraven.lwjgl3ify.api; + +import io.github.crucible.CrucibleConfigs; +import org.apache.logging.log4j.Logger; + +import java.util.HashSet; +import java.util.Set; + +/** + * Proxy everything to Crucible + * TODO: perhaps we need to ensure this class is loaded by us? + */ +public class ConfigUtils { + + public ConfigUtils(Logger logger) { + // NO-OP + } + + public boolean isLwjgl3ifyLoaded() { + return true; + } + + public Set getExtensibleEnums() { + return new HashSet<>(CrucibleConfigs.configs.lwjgl3ify_extensibleEnums); + } + + public void addExtensibleEnum(String className) { + CrucibleConfigs.configs.lwjgl3ify_extensibleEnums.add(className); + } + + public boolean isConfigLoaded() { + return true; + } +} diff --git a/src/main/java/me/eigenraven/lwjgl3ify/api/Lwjgl3Aware.java b/src/main/java/me/eigenraven/lwjgl3ify/api/Lwjgl3Aware.java new file mode 100644 index 00000000..28760fbf --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/api/Lwjgl3Aware.java @@ -0,0 +1,13 @@ +package me.eigenraven.lwjgl3ify.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Mark a class to not be transformed for lwjgl3 compatibility + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Lwjgl3Aware {} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/api/MakeEnumExtensible.java b/src/main/java/me/eigenraven/lwjgl3ify/api/MakeEnumExtensible.java new file mode 100644 index 00000000..bc1346b0 --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/api/MakeEnumExtensible.java @@ -0,0 +1,13 @@ +package me.eigenraven.lwjgl3ify.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Mark an enum for an automatic IExtensibleEnum implementation. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MakeEnumExtensible {} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java b/src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java new file mode 100644 index 00000000..647ed3ea --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) Forge Development LLC and contributors SPDX-License-Identifier: LGPL-2.1-only + */ +package me.eigenraven.lwjgl3ify.core; + +import java.util.List; +import java.util.stream.Collectors; + +import io.github.crucible.CrucibleModContainer; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.MethodNode; + +import me.eigenraven.lwjgl3ify.IExtensibleEnum; +import me.eigenraven.lwjgl3ify.api.MakeEnumExtensible; + +public class ExtensibleEnumTransformerHelper { + + private final Logger LOGGER = CrucibleModContainer.logger; + private final Type STRING = Type.getType(String.class); + private final Type ENUM = Type.getType(Enum.class); + public final Type MARKER_IFACE = Type.getType(IExtensibleEnum.class); + public final Type MARKER_ANNOTATION = Type.getType(MakeEnumExtensible.class); + private final Type ARRAY_UTILS = Type.getType("Lorg/apache/commons/lang3/ArrayUtils;"); // Don't directly reference + // this to prevent class + // loading. + private final String ADD_DESC = Type + .getMethodDescriptor(Type.getType(Object[].class), Type.getType(Object[].class), Type.getType(Object.class)); + private final Type UNSAFE_HACKS = Type.getType("Lme/eigenraven/lwjgl3ify/UnsafeHacks;"); // Again, not direct + // reference to prevent + // class loading. + private final String CLEAN_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Class.class)); + private final String NAME_DESC = Type.getMethodDescriptor(STRING); + private final String EQUALS_DESC = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, STRING); + public static final String CREATE_METHOD_NAME = "dynamicCreate"; + + /** + * @return Were changes made? + */ + public boolean processClassWithFlags(final ClassNode classNode, final Type classType) { + if ((classNode.access & Opcodes.ACC_ENUM) == 0) return false; + + Type array = Type.getType("[" + classType.getDescriptor()); + final int flags = Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC; + + FieldNode values = classNode.fields.stream() + .filter(f -> f.desc.contentEquals(array.getDescriptor()) && ((f.access & flags) == flags)) + .findFirst() + .orElse(null); + + boolean process = false; + if (classNode.interfaces.contains(MARKER_IFACE.getInternalName())) { + process = true; + } else if (classNode.visibleAnnotations != null && !classNode.visibleAnnotations.isEmpty()) { + for (AnnotationNode annotation : classNode.visibleAnnotations) { + if (annotation.desc.equals(MARKER_ANNOTATION.getDescriptor())) { + process = true; + } + } + } + if (!process) { + return false; + } + + List constructors = classNode.methods.stream() + .filter(m -> m.name.equals("")) + .collect(Collectors.toList()); + + // Static methods named "create" with first argument as a string + List candidates = constructors.stream() + .map(ctor -> { + final String[] exceptions = ctor.exceptions == null ? null : ctor.exceptions.toArray(new String[0]); + final Type ctorDesc = Type.getMethodType(ctor.desc); + final Type creatorDesc = Type + .getMethodType(classType, ArrayUtils.remove(ctorDesc.getArgumentTypes(), 1)); + final MethodNode creator = new MethodNode( + ctor.access, + CREATE_METHOD_NAME, + creatorDesc.getDescriptor(), + null, + exceptions); + creator.access = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC; + return creator; + }) + .collect(Collectors.toList()); + + if (candidates.isEmpty()) { + throw new IllegalStateException( + "IExtensibleEnum has no candidate factory methods: " + classType.getClassName()); + } + + classNode.methods.addAll(candidates); + + candidates.forEach(mtd -> { + Type[] args = Type.getArgumentTypes(mtd.desc); + if (args.length == 0 || !args[0].equals(STRING)) { + if (LOGGER.isErrorEnabled()) { + String sb = "Enum has create method without String as first parameter:\n" + " Enum: " + + classType.getDescriptor() + + "\n" + + " Target: " + + mtd.name + + mtd.desc + + "\n"; + LOGGER.error(sb); + } + throw new IllegalStateException( + "Enum has create method without String as first parameter: " + mtd.name + mtd.desc); + } + + Type ret = Type.getReturnType(mtd.desc); + if (!ret.equals(classType)) { + if (LOGGER.isErrorEnabled()) { + String sb = "Enum has create method with incorrect return type:\n" + " Enum: " + + classType.getDescriptor() + + "\n" + + " Target: " + + mtd.name + + mtd.desc + + "\n" + + " Found: " + + ret.getClassName() + + ", Expected: " + + classType.getClassName(); + LOGGER.error(sb); + } + throw new IllegalStateException( + "Enum has create method with incorrect return type: " + mtd.name + mtd.desc); + } + + Type[] ctrArgs = new Type[args.length + 1]; + ctrArgs[0] = STRING; + ctrArgs[1] = Type.INT_TYPE; + for (int x = 1; x < args.length; x++) ctrArgs[1 + x] = args[x]; + + String desc = Type.getMethodDescriptor(Type.VOID_TYPE, ctrArgs); + + MethodNode ctr = classNode.methods.stream() + .filter(m -> m.name.equals("") && m.desc.equals(desc)) + .findFirst() + .orElse(null); + if (ctr == null) { + if (LOGGER.isErrorEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Enum has create method with no matching constructor:\n"); + sb.append(" Enum: ") + .append(classType.getDescriptor()) + .append("\n"); + sb.append(" Candidate: ") + .append(mtd.desc) + .append("\n"); + sb.append(" Target: ") + .append(desc) + .append("\n"); + classNode.methods.stream() + .filter(m -> m.name.equals("")) + .forEach( + m -> sb.append(" : ") + .append(m.desc) + .append("\n")); + LOGGER.error(sb.toString()); + } + throw new IllegalStateException("Enum has create method with no matching constructor: " + desc); + } + + if (values == null) { + if (LOGGER.isErrorEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Enum has create method but we could not find $VALUES. Found:\n"); + classNode.fields.stream() + .filter(f -> (f.access & Opcodes.ACC_STATIC) != 0) + .forEach( + m -> sb.append(" ") + .append(m.name) + .append(" ") + .append(m.desc) + .append("\n")); + LOGGER.error(sb.toString()); + } + throw new IllegalStateException("Enum has create method but we could not find $VALUES"); + } + + values.access &= values.access & ~Opcodes.ACC_FINAL; // Strip the final so JITer doesn't inline things. + + mtd.access |= Opcodes.ACC_SYNCHRONIZED; + mtd.instructions.clear(); + mtd.localVariables.clear(); + if (mtd.tryCatchBlocks != null) { + mtd.tryCatchBlocks.clear(); + } + if (mtd.visibleLocalVariableAnnotations != null) { + mtd.visibleLocalVariableAnnotations.clear(); + } + if (mtd.invisibleLocalVariableAnnotations != null) { + mtd.invisibleLocalVariableAnnotations.clear(); + } + InstructionAdapter ins = new InstructionAdapter(mtd); + + int vars = 0; + for (Type arg : args) vars += arg.getSize(); + + { + vars += 1; // int x + Label for_start = new Label(); + Label for_condition = new Label(); + Label for_inc = new Label(); + + ins.iconst(0); + ins.store(vars, Type.INT_TYPE); + ins.goTo(for_condition); + // if (!VALUES[x].name().equalsIgnoreCase(name)) goto for_inc + ins.mark(for_start); + ins.getstatic(classType.getInternalName(), values.name, values.desc); + ins.load(vars, Type.INT_TYPE); + ins.aload(array); + ins.invokevirtual(ENUM.getInternalName(), "name", NAME_DESC, false); + ins.load(0, STRING); + ins.invokevirtual(STRING.getInternalName(), "equalsIgnoreCase", EQUALS_DESC, false); + ins.ifeq(for_inc); + // return VALUES[x]; + ins.getstatic(classType.getInternalName(), values.name, values.desc); + ins.load(vars, Type.INT_TYPE); + ins.aload(array); + ins.areturn(classType); + // x++ + ins.mark(for_inc); + ins.iinc(vars, 1); + // if (x < VALUES.length) goto for_start + ins.mark(for_condition); + ins.load(vars, Type.INT_TYPE); + ins.getstatic(classType.getInternalName(), values.name, values.desc); + ins.arraylength(); + ins.ificmplt(for_start); + } + + { + vars += 1; // enum ret; + // ret = new ThisType(name, VALUES.length, args..) + ins.anew(classType); + ins.dup(); + ins.load(0, STRING); + ins.getstatic(classType.getInternalName(), values.name, values.desc); + ins.arraylength(); + int idx = 1; + for (int x = 1; x < args.length; x++) { + ins.load(idx, args[x]); + idx += args[x].getSize(); + } + ins.invokespecial(classType.getInternalName(), "", desc, false); + ins.store(vars, classType); + // VALUES = ArrayUtils.add(VALUES, ret) + ins.getstatic(classType.getInternalName(), values.name, values.desc); + ins.load(vars, classType); + ins.invokestatic(ARRAY_UTILS.getInternalName(), "add", ADD_DESC, false); + ins.checkcast(array); + ins.putstatic(classType.getInternalName(), values.name, values.desc); + // EnumHelper.cleanEnumCache(ThisType.class) + ins.visitLdcInsn(classType); + ins.invokestatic(UNSAFE_HACKS.getInternalName(), "cleanEnumCache", CLEAN_DESC, false); + // init ret + ins.load(vars, classType); + ins.invokeinterface(MARKER_IFACE.getInternalName(), "init", "()V"); + // return ret + ins.load(vars, classType); + ins.areturn(classType); + } + }); + return true; + } +} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java b/src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java new file mode 100644 index 00000000..5791dd66 --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java @@ -0,0 +1,93 @@ +package me.eigenraven.lwjgl3ify.core; + +import java.util.concurrent.atomic.AtomicBoolean; + +import io.github.crucible.CrucibleModContainer; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Fixes a compilation bug of the java 8 compiler leading to the following exception at runtime: + * cpw.mods.fml.common.LoaderException: java.lang.IncompatibleClassChangeError: Inconsistent constant pool data in + * classfile for class com/gtnewhorizon/structurelib/alignment/IAlignmentLimits. Method 'boolean + * lambda$static$0(net.minecraftforge.common.util.ForgeDirection, + * com.gtnewhorizon.structurelib.alignment.enumerable.Rotation, + * com.gtnewhorizon.structurelib.alignment.enumerable.Flip)' at index 77 is CONSTANT_MethodRef and should be + * CONSTANT_InterfaceMethodRef + */ +public class FixConstantPoolInterfaceMethodRefHelper { + + public boolean transform(ClassNode node) { + if (System.getProperty("java.specification.version", "1.8") + .trim() + .startsWith("1.8")) { + return false; + } + final boolean iAmAnInterface = ((node.access & Opcodes.ACC_INTERFACE) != 0); + boolean changesMade = false; + final String internalClassName = node.name; + if (node.methods != null) { + for (MethodNode method : node.methods) { + if (method.instructions != null) { + for (AbstractInsnNode insn : method.instructions) { + changesMade |= validateInstruction(internalClassName, iAmAnInterface, insn); + } + } + } + } + return changesMade; + } + + private boolean validateInstruction(String internalClassName, boolean iAmAnInterface, AbstractInsnNode rawInsn) { + AtomicBoolean changed = new AtomicBoolean(false); + switch (rawInsn.getType()) { + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + final InvokeDynamicInsnNode insn = (InvokeDynamicInsnNode) rawInsn; + insn.bsm = fixHandle(internalClassName, iAmAnInterface, insn.bsm, changed); + if (insn.bsmArgs != null) { + for (int i = 0; i < insn.bsmArgs.length; i++) { + final Object arg = insn.bsmArgs[i]; + if (arg instanceof Handle) { + Handle handle = (Handle) arg; + insn.bsmArgs[i] = fixHandle(internalClassName, iAmAnInterface, handle, changed); + } + } + } + break; + default: + // no-op + } + return changed.get(); + } + + private Handle fixHandle(String internalClassName, boolean iAmAnInterface, Handle handle, AtomicBoolean changed) { + if (!handle.isInterface()) { + final boolean fixSelfReference = handle.getOwner() + .equals(internalClassName) && iAmAnInterface; + boolean fixJavaReference = false; + if (!fixSelfReference && handle.getOwner() + .startsWith("java/")) { + final String regularName = handle.getOwner() + .replace('/', '.'); + try { + final Class javaClass = Class.forName(regularName); + if (javaClass.isInterface()) { + fixJavaReference = true; + } + } catch (ClassNotFoundException cnfe) { + // no-op + CrucibleModContainer.logger.warn("Reference to non-existing java class {} found.", regularName, cnfe); + } + } + if (fixSelfReference || fixJavaReference) { + changed.set(true); + return new Handle(handle.getTag(), handle.getOwner(), handle.getName(), handle.getDesc(), true); + } + } + return handle; + } +} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/core/LwjglRedirectTransformer.java b/src/main/java/me/eigenraven/lwjgl3ify/core/LwjglRedirectTransformer.java new file mode 100644 index 00000000..e0a6b329 --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/core/LwjglRedirectTransformer.java @@ -0,0 +1,86 @@ +package me.eigenraven.lwjgl3ify.core; + +import io.github.crucible.CrucibleModContainer; +import io.github.crucible.bootstrap.CrucibleMetadata; +import me.eigenraven.lwjgl3ify.api.Lwjgl3Aware; +import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.*; +import org.objectweb.asm.commons.ClassRemapper; +import org.objectweb.asm.commons.Remapper; + +public class LwjglRedirectTransformer extends Remapper implements IClassTransformer { + + int remaps = 0, calls = 0; + + public static LwjglRedirectTransformer activeInstance = null; + + public LwjglRedirectTransformer() { + // Only use the last constructed transformer + activeInstance = this; + } + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if (this != activeInstance) { + return basicClass; + } + if (basicClass == null) { + return null; + } + if (name.contains("lwjgl3ify")) { + return basicClass; + } + ClassReader reader = new ClassReader(basicClass); + ClassWriter writer = new ClassWriter(0); + ClassVisitor visitor = new EscapingClassRemapper(writer); + + try { + reader.accept(visitor, ClassReader.EXPAND_FRAMES); + } catch (Lwjgl3AwareException e) { + return basicClass; + } catch (Exception e) { + CrucibleModContainer.logger.warn("Couldn't remap class {}", transformedName, e); + return basicClass; + } + + return writer.toByteArray(); + } + + final String[] fromPrefixes = new String[] { "org/lwjgl/", "javax/xml/bind/", "javax/servlet/" }; + + final String[] toPrefixes = new String[] { "org/lwjglx/", "jakarta/xml/bind/", "jakarta/servlet/" }; + + @Override + public String map(String typeName) { + if (typeName == null) { + return null; + } + calls++; + for (int pfx = 0; pfx < fromPrefixes.length; pfx++) { + if (typeName.startsWith(fromPrefixes[pfx])) { + remaps++; + return toPrefixes[pfx] + typeName.substring(fromPrefixes[pfx].length()); + } + } + + return typeName; + } + + public static class Lwjgl3AwareException extends RuntimeException { + } + + public class EscapingClassRemapper extends ClassRemapper { + + public EscapingClassRemapper(ClassWriter writer) { + super(writer, LwjglRedirectTransformer.this); + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + if (desc.equals(Type.getDescriptor(Lwjgl3Aware.class))) { + throw new Lwjgl3AwareException(); + } + return super.visitAnnotation(desc, visible); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java b/src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java new file mode 100644 index 00000000..54ec17cf --- /dev/null +++ b/src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java @@ -0,0 +1,127 @@ +package me.eigenraven.lwjgl3ify.core; + +import java.util.ArrayList; +import java.util.List; + +import io.github.crucible.CrucibleModContainer; +import io.github.crucible.CrucibleConfigs; +import io.github.crucible.bootstrap.CrucibleMetadata; +import net.minecraft.launchwrapper.IClassTransformer; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; + +import me.eigenraven.lwjgl3ify.WasFinalObjectHolder; + +public class UnfinalizeObjectHoldersTransformer implements IClassTransformer { + + // Keep ClassNode-operating transformers together for efficiency (don't read/write the class multiple times) + final ExtensibleEnumTransformerHelper enumTransformer = new ExtensibleEnumTransformerHelper(); + final FixConstantPoolInterfaceMethodRefHelper cpiMethodRefTransformer = new FixConstantPoolInterfaceMethodRefHelper(); + + private static boolean isHolder(List annotations) { + if (annotations == null) { + return false; + } + for (AnnotationNode annotationNode : annotations) { + // Java 17 uses $ instead of / + final String desc = annotationNode.desc.replace('$', '/'); + if (desc.contains("cpw/mods/fml/common/registry/GameRegistry/ObjectHolder")) { + return true; + } + if (desc.contains("cpw/mods/fml/common/registry/GameRegistry/ItemStackHolder")) { + return true; + } + } + return false; + } + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if (basicClass == null) { + return null; + } + + // Crucible classes and some of its dependencies *must* be ignored because we depend on Crucible config + if (transformedName.startsWith("me.eigenraven.lwjgl3ify") || transformedName.startsWith("io.github.crucible") + || transformedName.startsWith("org.yaml.snakeyaml")) { + return basicClass; + } + try { + final ClassReader reader = new ClassReader(basicClass); + final ClassNode node = new ClassNode(); + reader.accept(node, ClassReader.EXPAND_FRAMES); + final Type classType = Type.getType("L" + name.replace('.', '/') + ";"); + + boolean transformClass = false; + boolean workDone = false; + if (transformedName.equals("net.minecraft.init.Blocks") + || transformedName.equals("net.minecraft.init.Items")) { + transformClass = true; + } + transformClass |= isHolder(node.visibleAnnotations); + if (transformedName.equals("team.chisel.init.ChiselBlocks")) { + CrucibleModContainer.logger.debug("chiselblocks"); + } + int fieldsModified = 0; + for (FieldNode field : node.fields) { + boolean transform = transformClass; + if (!transform) { + transform = isHolder(field.visibleAnnotations); + } + if (transform) { + workDone = true; + if ((field.access & Opcodes.ACC_FINAL) != 0) { + if (field.visibleAnnotations == null) { + field.visibleAnnotations = new ArrayList<>(1); + field.visibleAnnotations + .add(new AnnotationNode(Type.getDescriptor(WasFinalObjectHolder.class))); + } + field.access = field.access & (~Opcodes.ACC_FINAL); + } + fieldsModified++; + } + } + if (workDone) { + CrucibleModContainer.logger.info("Unfinalized {} Holder fields in {}", fieldsModified, transformedName); + } + + if (CrucibleConfigs.configs.lwjgl3ify_extensibleEnums + .contains(transformedName)) { + if (node.interfaces == null) { + node.interfaces = new ArrayList<>(1); + } + node.interfaces.add(enumTransformer.MARKER_IFACE.getInternalName()); + } + + final boolean enumsTransformed = enumTransformer.processClassWithFlags(node, classType); + + if (enumsTransformed) { + workDone = true; + CrucibleModContainer.logger.info("Dynamicized enum {}={}", name, transformedName); + } + + final boolean ifaceMethodRefsTransformed = cpiMethodRefTransformer.transform(node); + + if (ifaceMethodRefsTransformed) { + workDone = true; + CrucibleModContainer.logger + .warn("Fixed missing CONSTANT_InterfaceMethodRef miscompilation in {}={}", name, transformedName); + } + + if (workDone) { + final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + node.accept(writer); + return writer.toByteArray(); + } + } catch (Exception e) { + CrucibleModContainer.logger.error("Error when unfinalizing ObjectHolder transformer", e); + } + return basicClass; + } +} \ No newline at end of file diff --git a/src/main/java/org/bukkit/craftbukkit/v1_7_R4/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/v1_7_R4/CraftServer.java index be00d725..1551d27d 100644 --- a/src/main/java/org/bukkit/craftbukkit/v1_7_R4/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/v1_7_R4/CraftServer.java @@ -10,7 +10,7 @@ import com.mojang.authlib.GameProfile; import cpw.mods.fml.common.FMLLog; import io.github.crucible.CrucibleConfigs; -import io.github.crucible.CrucibleMetadata; +import io.github.crucible.bootstrap.CrucibleMetadata; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; diff --git a/src/main/java/org/bukkit/craftbukkit/v1_7_R4/boss/CraftBossBar.java b/src/main/java/org/bukkit/craftbukkit/v1_7_R4/boss/CraftBossBar.java index f6dd5d72..cb6d65ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/v1_7_R4/boss/CraftBossBar.java +++ b/src/main/java/org/bukkit/craftbukkit/v1_7_R4/boss/CraftBossBar.java @@ -1,6 +1,6 @@ package org.bukkit.craftbukkit.v1_7_R4.boss; -import io.github.crucible.CrucibleMetadata; +import io.github.crucible.bootstrap.CrucibleMetadata; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarFlag; import org.bukkit.boss.BarStyle; diff --git a/src/main/java/org/bukkit/craftbukkit/v1_7_R4/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/v1_7_R4/entity/CraftPlayer.java index 12ad2944..00d1501d 100644 --- a/src/main/java/org/bukkit/craftbukkit/v1_7_R4/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/v1_7_R4/entity/CraftPlayer.java @@ -2,7 +2,7 @@ import com.google.common.collect.ImmutableSet; import com.mojang.authlib.GameProfile; -import io.github.crucible.CrucibleMetadata; +import io.github.crucible.bootstrap.CrucibleMetadata; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import net.minecraft.entity.EntityTracker; From a31777149f1bc31df35b1f88d16e363c1a7d618a Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Mon, 1 Jan 2024 13:48:46 -0300 Subject: [PATCH 3/9] Updated SpecialSource to 1.10.0, allow newer java version plugins to work --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0567961f..a93dafb4 100644 --- a/build.gradle +++ b/build.gradle @@ -121,7 +121,7 @@ dependencies { libraries 'commons-lang:commons-lang:2.6' libraries 'org.avaje:ebean:2.7.3' libraries 'jline:jline:2.6' - libraries 'net.md-5:SpecialSource:1.7.4' + libraries 'net.md-5:SpecialSource:1.10.0' libraries 'net.sourceforge.argo:argo:2.25' libraries 'com.googlecode.json-simple:json-simple:1.1' libraries 'org.xerial:sqlite-jdbc:3.7.2' From 140818badf53683388e171ea4f67d2e7f133a0d1 Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Sun, 7 Jan 2024 17:12:05 -0300 Subject: [PATCH 4/9] Few tweaks to messages, removed duplicated bukkit material definition --- .../io/github/crucible/bootstrap/CrucibleServerMainHook.java | 4 +--- .../java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java index 5388b6c0..6441fdec 100644 --- a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java +++ b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java @@ -52,13 +52,11 @@ public static void relaunchMain(String[] args) throws Exception { System.setProperty((String) entry.getKey(), (String) entry.getValue()); } - System.out.println("[Crucible] This Crucible version has embedded a heavily modified version of lwjgl3ify (https://github.com/GTNewHorizons/lwjgl3ify/)."); - System.out.println("[Crucible] Do not, I repeat DO NOT report any issues to upstream, any issue you encounter is mostly likely because of a hybrid environment. Do open a Crucible issue instead."); Lwjgl3ifyGlue.checkJava(); if (!verifyLibraries()) { setupLibraries(); - System.out.println("[Crucible] Crucible installed! You need to start the server again."); + System.out.println("[Crucible] Crucible installed! A restart is required to be able to boot."); System.exit(0); } else { System.out.println("[Crucible] Everything in check, booting the server"); diff --git a/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java index 96b57db9..0c2acb40 100644 --- a/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java +++ b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java @@ -28,7 +28,7 @@ public class Lwjgl3ifyGlue { "vswe.stevesfactory.blocks.ConnectionBlockType", "vswe.stevesfactory.components.ComponentType", "vswe.stevesfactory.components.ConnectionSet", "vswe.stevesfactory.components.ConnectionOption", "ic2.core.init.InternalName", "gregtech.api.enums.Element", "gregtech.api.enums.OrePrefixes", - "net.minecraft.client.audio.MusicTicker$MusicType", "org.bukkit.Material", + "net.minecraft.client.audio.MusicTicker$MusicType", "buildcraft.api.transport.IPipeTile.PipeType", "thaumcraft.common.entities.golems.EnumGolemType", // Non-GTNH Mods Compat // The Lord of the Rings Mod: Legacy @@ -55,6 +55,9 @@ public class Lwjgl3ifyGlue { }; public static void checkJava() { + System.out.println("[Crucible] Crucible now supports Java 8-17 by embedding a modified version of lwjgl3ify (https://github.com/GTNewHorizons/lwjgl3ify/)."); + System.out.println("[Crucible] Do not report issues to upstream. All issues with newer Java version must be reported to Crucible's issue tracker instead."); + if (!Boolean.getBoolean("lwjgl3ify.skipjavacheck")) { final String specVer = System.getProperty("java.specification.version"); if (specVer.equals("17")) { From ff584304ec44a1ee6f50fc8dc4f36ce305defee6 Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Mon, 8 Jan 2024 11:39:44 -0300 Subject: [PATCH 5/9] Ensure essential Crucible classes are loaded ahead of time, avoid some issues with our tweakers tweaking ourselves --- .../github/crucible/bootstrap/CrucibleServerMainHook.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java index 6441fdec..78782f23 100644 --- a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java +++ b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java @@ -106,6 +106,13 @@ public static void restoreStreams() { // Too lazy for a coremod public static void coremodHandleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { + try { + // Ensure some essential classes are loaded before we register the tweaker + Class.forName("io.github.crucible.CrucibleConfigs", true, classLoader); + Class.forName("io.github.crucible.CrucibleModContainer", true, classLoader); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } Lwjgl3ifyGlue.doCoremodWork(classLoader); classLoader.addClassLoaderExclusion("io.github.crucible.bootstrap."); } From d6c1f18f207f3de0edbbaa7befcb0c5c647ce9e8 Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Mon, 8 Jan 2024 11:54:48 -0300 Subject: [PATCH 6/9] Added java9args for launching crucible --- java9args.txt | 36 +++++++++++++++++++ .../crucible/bootstrap/Lwjgl3ifyGlue.java | 7 +++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 java9args.txt diff --git a/java9args.txt b/java9args.txt new file mode 100644 index 00000000..e5618cc2 --- /dev/null +++ b/java9args.txt @@ -0,0 +1,36 @@ +--illegal-access=warn +-Djava.security.manager=allow +-Dfile.encoding=UTF-8 +-Dcrucible.weAreJava9=true +--add-opens +java.base/jdk.internal.loader=ALL-UNNAMED +--add-opens +java.base/java.net=ALL-UNNAMED +--add-opens +java.base/java.nio=ALL-UNNAMED +--add-opens +java.base/java.io=ALL-UNNAMED +--add-opens +java.base/java.lang=ALL-UNNAMED +--add-opens +java.base/java.lang.reflect=ALL-UNNAMED +--add-opens +java.base/java.text=ALL-UNNAMED +--add-opens +java.base/java.util=ALL-UNNAMED +--add-opens +java.base/jdk.internal.reflect=ALL-UNNAMED +--add-opens +java.base/sun.nio.ch=ALL-UNNAMED +--add-opens +jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming +--add-opens +java.desktop/sun.awt.image=ALL-UNNAMED +--add-opens +java.desktop/com.sun.imageio.plugins.png=ALL-UNNAMED +--add-modules jdk.dynalink +--add-opens +jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED +--add-modules java.sql.rowset +--add-opens +java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED \ No newline at end of file diff --git a/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java index 0c2acb40..626be974 100644 --- a/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java +++ b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java @@ -57,9 +57,14 @@ public class Lwjgl3ifyGlue { public static void checkJava() { System.out.println("[Crucible] Crucible now supports Java 8-17 by embedding a modified version of lwjgl3ify (https://github.com/GTNewHorizons/lwjgl3ify/)."); System.out.println("[Crucible] Do not report issues to upstream. All issues with newer Java version must be reported to Crucible's issue tracker instead."); + final String specVer = System.getProperty("java.specification.version"); + + // Is there any jvm where the specs is 8 instead of 1.8? + if (!Boolean.getBoolean("crucible.weAreJava9") && !(specVer.equals("1.8"))) { + System.out.println("[Crucible] Looks like you are missing the special java9+, the server may not launch without them."); + } if (!Boolean.getBoolean("lwjgl3ify.skipjavacheck")) { - final String specVer = System.getProperty("java.specification.version"); if (specVer.equals("17")) { try { final Class cRuntime = Class.forName("java.lang.Runtime"); From 34392a671b0d1ac6285fb935ce94fdcc4214e77a Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Mon, 8 Jan 2024 12:38:19 -0300 Subject: [PATCH 7/9] Apply brain --- .../mods/fml/common/TracingPrintStream.java.patch | 13 +++++++++++++ .../fml/common/patcher/ClassPatchManager.java.patch | 8 ++------ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 patches/cpw/mods/fml/common/TracingPrintStream.java.patch diff --git a/patches/cpw/mods/fml/common/TracingPrintStream.java.patch b/patches/cpw/mods/fml/common/TracingPrintStream.java.patch new file mode 100644 index 00000000..fdba2bd3 --- /dev/null +++ b/patches/cpw/mods/fml/common/TracingPrintStream.java.patch @@ -0,0 +1,13 @@ +--- ../src-base/minecraft/cpw/mods/fml/common/TracingPrintStream.java ++++ ../src-work/minecraft/cpw/mods/fml/common/TracingPrintStream.java +@@ -47,4 +47,10 @@ + return "[" + elem.getClassName() + ":" + elem.getMethodName() + ":" + elem.getLineNumber() + "]: "; + } + ++ @Override ++ public void close() { ++ // no-op ++ //println("Something tried to close the main output stream"); ++ //new Throwable().printStackTrace(); ++ } + } diff --git a/patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch b/patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch index 5a4f9abf..cabdec07 100644 --- a/patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch +++ b/patches/cpw/mods/fml/common/patcher/ClassPatchManager.java.patch @@ -29,7 +29,7 @@ public static final ClassPatchManager INSTANCE = new ClassPatchManager(); public static final boolean dumpPatched = Boolean.parseBoolean(System.getProperty("fml.dumpPatchedClasses", "false")); -@@ -155,10 +159,24 @@ +@@ -155,10 +159,20 @@ FMLRelaunchLog.log(Level.ERROR, "The binary patch set is missing. Either you are in a development environment, or things are not going to work!"); return; } @@ -46,11 +46,7 @@ - Pack200.newUnpacker().unpack(binpatchesDecompressed, jos); + + //Pack200.newUnpacker().unpack(binpatchesDecompressed, jos); -+ Archive archive = new Archive(binpatchesDecompressed, jos); -+ archive.setQuiet(true); -+ // Crucible note: YES, this *IS* needed, Thermos logging is so broken beyond repair that not setting a log file will break *EVERYTHING* - juanmuscaria -+ archive.setLogFile("logs/.ignoreMe"); -+ archive.unpack(); ++ new Pack200UnpackerAdapter().unpack(binpatchesDecompressed, jos); + // Crucible end + jis = new JarInputStream(new ByteArrayInputStream(jarBytes.toByteArray())); From ba95571ca0ac22b6b0898584a84acaea00778165 Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Mon, 15 Jan 2024 14:40:02 -0300 Subject: [PATCH 8/9] Try to avoid more class loading issues... --- .../fml/relauncher/CoreModManager.java.patch | 25 ++++++++++++------- .../bootstrap/CrucibleServerMainHook.java | 5 ++-- .../core/ExtensibleEnumTransformerHelper.java | 3 ++- ...xConstantPoolInterfaceMethodRefHelper.java | 6 +++-- .../UnfinalizeObjectHoldersTransformer.java | 20 +++++++-------- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch b/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch index fe562294..63d27bb2 100644 --- a/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch +++ b/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch @@ -85,10 +85,21 @@ public static void handleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { CoreModManager.mcDir = mcDir; -@@ -219,7 +230,23 @@ +@@ -206,6 +217,9 @@ + } + + FMLRelaunchLog.fine("All fundamental core mods are successfully located"); ++ // Crucible start - too lazy for creating a coremod ++ CrucibleServerMainHook.coremodHandleLaunch(mcDir, classLoader, tweaker); ++ // Crucible end + // Now that we have the root plugins loaded - lets see what else might + // be around + String commandLineCoremods = System.getProperty("fml.coreMods.load", ""); +@@ -219,7 +233,19 @@ loadCoreMod(classLoader, coreModClassName, null); } discoverCoreMods(mcDir, classLoader); +- + // Cauldron start - group output of @MCVersion warnings + if (!noVersionAnnotationCoreMods.isEmpty()) + { @@ -102,14 +113,10 @@ + FMLRelaunchLog.warning(sb.toString()); + } + // Cauldron end - -+ // Crucible start - too lazy for creating a coremod -+ CrucibleServerMainHook.coremodHandleLaunch(mcDir, classLoader, tweaker); -+ // Crucible end } private static void discoverCoreMods(File mcDir, LaunchClassLoader classLoader) -@@ -336,6 +363,10 @@ +@@ -336,6 +362,10 @@ String cascadedTweaker = mfAttributes.getValue("TweakClass"); if (cascadedTweaker != null) { @@ -120,7 +127,7 @@ FMLRelaunchLog.info("Loading tweaker %s from %s", cascadedTweaker, coreMod.getName()); Integer sortOrder = Ints.tryParse(Strings.nullToEmpty(mfAttributes.getValue("TweakOrder"))); sortOrder = (sortOrder == null ? Integer.valueOf(0) : sortOrder); -@@ -365,6 +396,10 @@ +@@ -365,6 +395,10 @@ FMLRelaunchLog.fine("Not found coremod data in %s", coreMod.getName()); continue; } @@ -131,7 +138,7 @@ // Support things that are mod jars, but not FML mod jars try { -@@ -377,40 +412,76 @@ +@@ -377,40 +411,76 @@ else { FMLRelaunchLog.finer("Found FMLCorePluginContainsFMLMod marker in %s, it will be examined later for regular @Mod instances", @@ -225,7 +232,7 @@ } /** -@@ -467,19 +538,22 @@ +@@ -467,19 +537,22 @@ MCVersion requiredMCVersion = coreModClazz.getAnnotation(IFMLLoadingPlugin.MCVersion.class); if (!Arrays.asList(rootPlugins).contains(coreModClass) && (requiredMCVersion == null || Strings.isNullOrEmpty(requiredMCVersion.value()))) { diff --git a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java index 78782f23..3badf381 100644 --- a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java +++ b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java @@ -106,14 +106,13 @@ public static void restoreStreams() { // Too lazy for a coremod public static void coremodHandleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { + classLoader.addClassLoaderExclusion("io.github.crucible.bootstrap."); try { - // Ensure some essential classes are loaded before we register the tweaker + // Ensure our config is loaded way before everything that may need it Class.forName("io.github.crucible.CrucibleConfigs", true, classLoader); - Class.forName("io.github.crucible.CrucibleModContainer", true, classLoader); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } Lwjgl3ifyGlue.doCoremodWork(classLoader); - classLoader.addClassLoaderExclusion("io.github.crucible.bootstrap."); } } \ No newline at end of file diff --git a/src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java b/src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java index 647ed3ea..f98312e5 100644 --- a/src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java +++ b/src/main/java/me/eigenraven/lwjgl3ify/core/ExtensibleEnumTransformerHelper.java @@ -8,6 +8,7 @@ import io.github.crucible.CrucibleModContainer; import org.apache.commons.lang3.ArrayUtils; +import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -23,7 +24,7 @@ public class ExtensibleEnumTransformerHelper { - private final Logger LOGGER = CrucibleModContainer.logger; + private final Logger LOGGER = LogManager.getLogger("lwjgl3ify"); private final Type STRING = Type.getType(String.class); private final Type ENUM = Type.getType(Enum.class); public final Type MARKER_IFACE = Type.getType(IExtensibleEnum.class); diff --git a/src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java b/src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java index 5791dd66..29b0f363 100644 --- a/src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java +++ b/src/main/java/me/eigenraven/lwjgl3ify/core/FixConstantPoolInterfaceMethodRefHelper.java @@ -2,7 +2,8 @@ import java.util.concurrent.atomic.AtomicBoolean; -import io.github.crucible.CrucibleModContainer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.objectweb.asm.Handle; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; @@ -20,6 +21,7 @@ * CONSTANT_InterfaceMethodRef */ public class FixConstantPoolInterfaceMethodRefHelper { + private final Logger LOGGER = LogManager.getLogger("lwjgl3ify"); public boolean transform(ClassNode node) { if (System.getProperty("java.specification.version", "1.8") @@ -80,7 +82,7 @@ private Handle fixHandle(String internalClassName, boolean iAmAnInterface, Handl } } catch (ClassNotFoundException cnfe) { // no-op - CrucibleModContainer.logger.warn("Reference to non-existing java class {} found.", regularName, cnfe); + LOGGER.warn("Reference to non-existing java class {} found.", regularName, cnfe); } } if (fixSelfReference || fixJavaReference) { diff --git a/src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java b/src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java index 54ec17cf..f184e8ae 100644 --- a/src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java +++ b/src/main/java/me/eigenraven/lwjgl3ify/core/UnfinalizeObjectHoldersTransformer.java @@ -3,11 +3,11 @@ import java.util.ArrayList; import java.util.List; -import io.github.crucible.CrucibleModContainer; import io.github.crucible.CrucibleConfigs; -import io.github.crucible.bootstrap.CrucibleMetadata; import net.minecraft.launchwrapper.IClassTransformer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; @@ -19,7 +19,7 @@ import me.eigenraven.lwjgl3ify.WasFinalObjectHolder; public class UnfinalizeObjectHoldersTransformer implements IClassTransformer { - + private final Logger LOGGER = LogManager.getLogger("lwjgl3ify"); // Keep ClassNode-operating transformers together for efficiency (don't read/write the class multiple times) final ExtensibleEnumTransformerHelper enumTransformer = new ExtensibleEnumTransformerHelper(); final FixConstantPoolInterfaceMethodRefHelper cpiMethodRefTransformer = new FixConstantPoolInterfaceMethodRefHelper(); @@ -47,9 +47,7 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) return null; } - // Crucible classes and some of its dependencies *must* be ignored because we depend on Crucible config - if (transformedName.startsWith("me.eigenraven.lwjgl3ify") || transformedName.startsWith("io.github.crucible") - || transformedName.startsWith("org.yaml.snakeyaml")) { + if (transformedName.startsWith("me.eigenraven.lwjgl3ify")) { return basicClass; } try { @@ -66,7 +64,7 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) } transformClass |= isHolder(node.visibleAnnotations); if (transformedName.equals("team.chisel.init.ChiselBlocks")) { - CrucibleModContainer.logger.debug("chiselblocks"); + LOGGER.debug("chiselblocks"); } int fieldsModified = 0; for (FieldNode field : node.fields) { @@ -88,7 +86,7 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) } } if (workDone) { - CrucibleModContainer.logger.info("Unfinalized {} Holder fields in {}", fieldsModified, transformedName); + LOGGER.info("Unfinalized {} Holder fields in {}", fieldsModified, transformedName); } if (CrucibleConfigs.configs.lwjgl3ify_extensibleEnums @@ -103,14 +101,14 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) if (enumsTransformed) { workDone = true; - CrucibleModContainer.logger.info("Dynamicized enum {}={}", name, transformedName); + LOGGER.info("Dynamicized enum {}={}", name, transformedName); } final boolean ifaceMethodRefsTransformed = cpiMethodRefTransformer.transform(node); if (ifaceMethodRefsTransformed) { workDone = true; - CrucibleModContainer.logger + LOGGER .warn("Fixed missing CONSTANT_InterfaceMethodRef miscompilation in {}={}", name, transformedName); } @@ -120,7 +118,7 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) return writer.toByteArray(); } } catch (Exception e) { - CrucibleModContainer.logger.error("Error when unfinalizing ObjectHolder transformer", e); + LOGGER.error("Error when unfinalizing ObjectHolder transformer", e); } return basicClass; } From 20bc506d77d9adaed327d2e9a64b7121f2eb9e34 Mon Sep 17 00:00:00 2001 From: Juan Patricio Date: Fri, 2 Feb 2024 11:55:39 -0300 Subject: [PATCH 9/9] Try to avoid more class loading issues... Again --- .../fml/relauncher/CoreModManager.java.patch | 25 ++++++++++--------- .../bootstrap/CrucibleCoremodHook.java | 20 +++++++++++++++ .../bootstrap/CrucibleServerMainHook.java | 12 --------- .../crucible/bootstrap/Lwjgl3ifyGlue.java | 9 +++++-- 4 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 src/main/java/io/github/crucible/bootstrap/CrucibleCoremodHook.java diff --git a/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch b/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch index 63d27bb2..496115d1 100644 --- a/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch +++ b/patches/cpw/mods/fml/relauncher/CoreModManager.java.patch @@ -19,16 +19,17 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; -@@ -31,6 +32,8 @@ +@@ -31,6 +32,9 @@ import java.util.jar.Attributes; import java.util.jar.JarFile; +import io.github.crucible.CrucibleModContainer; ++import io.github.crucible.bootstrap.CrucibleCoremodHook; +import io.github.crucible.bootstrap.CrucibleServerMainHook; import net.minecraft.launchwrapper.ITweaker; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; -@@ -57,10 +60,11 @@ +@@ -57,10 +61,11 @@ import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; public class CoreModManager { @@ -41,7 +42,7 @@ private static List loadedCoremods = Lists.newArrayList(); private static List loadPlugins; private static boolean deobfuscatedEnvironment; -@@ -70,6 +74,7 @@ +@@ -70,6 +75,7 @@ private static List accessTransformers = Lists.newArrayList(); private static class FMLPluginWrapper implements ITweaker { @@ -49,7 +50,7 @@ public final String name; public final IFMLLoadingPlugin coreModInstance; public final List predepends; -@@ -99,14 +104,17 @@ +@@ -99,14 +105,17 @@ } @Override @@ -75,7 +76,7 @@ FMLRelaunchLog.fine("Injection complete"); FMLRelaunchLog.fine("Running coremod plugin for %s {%s}", name, coreModInstance.getClass().getName()); -@@ -160,6 +168,9 @@ +@@ -160,6 +169,9 @@ } @@ -85,17 +86,17 @@ public static void handleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { CoreModManager.mcDir = mcDir; -@@ -206,6 +217,9 @@ +@@ -206,6 +218,9 @@ } FMLRelaunchLog.fine("All fundamental core mods are successfully located"); + // Crucible start - too lazy for creating a coremod -+ CrucibleServerMainHook.coremodHandleLaunch(mcDir, classLoader, tweaker); ++ CrucibleCoremodHook.coremodHandleLaunch(mcDir, classLoader, tweaker); + // Crucible end // Now that we have the root plugins loaded - lets see what else might // be around String commandLineCoremods = System.getProperty("fml.coreMods.load", ""); -@@ -219,7 +233,19 @@ +@@ -219,7 +234,19 @@ loadCoreMod(classLoader, coreModClassName, null); } discoverCoreMods(mcDir, classLoader); @@ -116,7 +117,7 @@ } private static void discoverCoreMods(File mcDir, LaunchClassLoader classLoader) -@@ -336,6 +362,10 @@ +@@ -336,6 +363,10 @@ String cascadedTweaker = mfAttributes.getValue("TweakClass"); if (cascadedTweaker != null) { @@ -127,7 +128,7 @@ FMLRelaunchLog.info("Loading tweaker %s from %s", cascadedTweaker, coreMod.getName()); Integer sortOrder = Ints.tryParse(Strings.nullToEmpty(mfAttributes.getValue("TweakOrder"))); sortOrder = (sortOrder == null ? Integer.valueOf(0) : sortOrder); -@@ -365,6 +395,10 @@ +@@ -365,6 +396,10 @@ FMLRelaunchLog.fine("Not found coremod data in %s", coreMod.getName()); continue; } @@ -138,7 +139,7 @@ // Support things that are mod jars, but not FML mod jars try { -@@ -377,40 +411,76 @@ +@@ -377,40 +412,76 @@ else { FMLRelaunchLog.finer("Found FMLCorePluginContainsFMLMod marker in %s, it will be examined later for regular @Mod instances", @@ -232,7 +233,7 @@ } /** -@@ -467,19 +537,22 @@ +@@ -467,19 +538,22 @@ MCVersion requiredMCVersion = coreModClazz.getAnnotation(IFMLLoadingPlugin.MCVersion.class); if (!Arrays.asList(rootPlugins).contains(coreModClass) && (requiredMCVersion == null || Strings.isNullOrEmpty(requiredMCVersion.value()))) { diff --git a/src/main/java/io/github/crucible/bootstrap/CrucibleCoremodHook.java b/src/main/java/io/github/crucible/bootstrap/CrucibleCoremodHook.java new file mode 100644 index 00000000..9621729b --- /dev/null +++ b/src/main/java/io/github/crucible/bootstrap/CrucibleCoremodHook.java @@ -0,0 +1,20 @@ +package io.github.crucible.bootstrap; + +import cpw.mods.fml.common.launcher.FMLTweaker; +import net.minecraft.launchwrapper.LaunchClassLoader; + +import java.io.File; + +public class CrucibleCoremodHook { + // Too lazy for a coremod + public static void coremodHandleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { + classLoader.addClassLoaderExclusion("io.github.crucible.bootstrap."); + try { + // Ensure our config is loaded way before everything that may need it + Class.forName("io.github.crucible.CrucibleConfigs", true, classLoader); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + Lwjgl3ifyGlue.doCoremodWork(classLoader); + } +} diff --git a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java index 3badf381..05c1fdc9 100644 --- a/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java +++ b/src/main/java/io/github/crucible/bootstrap/CrucibleServerMainHook.java @@ -103,16 +103,4 @@ public static void restoreStreams() { System.setOut(originalOut); System.setErr(originalErr); } - - // Too lazy for a coremod - public static void coremodHandleLaunch(File mcDir, LaunchClassLoader classLoader, FMLTweaker tweaker) { - classLoader.addClassLoaderExclusion("io.github.crucible.bootstrap."); - try { - // Ensure our config is loaded way before everything that may need it - Class.forName("io.github.crucible.CrucibleConfigs", true, classLoader); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - Lwjgl3ifyGlue.doCoremodWork(classLoader); - } } \ No newline at end of file diff --git a/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java index 626be974..c842149c 100644 --- a/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java +++ b/src/main/java/io/github/crucible/bootstrap/Lwjgl3ifyGlue.java @@ -55,8 +55,6 @@ public class Lwjgl3ifyGlue { }; public static void checkJava() { - System.out.println("[Crucible] Crucible now supports Java 8-17 by embedding a modified version of lwjgl3ify (https://github.com/GTNewHorizons/lwjgl3ify/)."); - System.out.println("[Crucible] Do not report issues to upstream. All issues with newer Java version must be reported to Crucible's issue tracker instead."); final String specVer = System.getProperty("java.specification.version"); // Is there any jvm where the specs is 8 instead of 1.8? @@ -64,6 +62,13 @@ public static void checkJava() { System.out.println("[Crucible] Looks like you are missing the special java9+, the server may not launch without them."); } + if (specVer.equals("1.8")) { + System.out.println("[Crucible] Crucible now supports Java 8-21 by embedding a modified version of lwjgl3ify (https://github.com/GTNewHorizons/lwjgl3ify/)."); + } else { + System.out.println("[Crucible] Crucible is running modified version of lwjgl3ify (https://github.com/GTNewHorizons/lwjgl3ify/)."); + } + System.out.println("[Crucible] Do not report issues to upstream. All issues with newer Java version must be reported to Crucible's issue tracker instead."); + if (!Boolean.getBoolean("lwjgl3ify.skipjavacheck")) { if (specVer.equals("17")) { try {