mirror of
https://github.com/GTNewHorizons/CodeChickenCore.git
synced 2026-10-27 06:43:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f02dbc956c | ||
|
|
63f36ca383 | ||
|
|
bb008a1265 | ||
|
|
bb98bdc6d4 | ||
|
|
4e5bcf829c |
No files matched your search
@@ -27,3 +27,4 @@ whitelist.json
|
||||
*.iws
|
||||
src/main/resources/mixins.*.json
|
||||
*.bat
|
||||
.DS_Store
|
||||
@@ -3,3 +3,8 @@
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhconvention'
|
||||
}
|
||||
|
||||
minecraft {
|
||||
//extraRunJvmArguments.add("-Dccc.dev.runtimePublic=true")
|
||||
//extraRunJvmArguments.add("-Dccc.dev.deobfuscate=true")
|
||||
}
|
||||
+39
-4
@@ -39,9 +39,33 @@ remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/co
|
||||
# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE.
|
||||
developmentEnvironmentUserName = Developer
|
||||
|
||||
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
|
||||
# See https://github.com/bsideup/jabel for details on how this works.
|
||||
enableModernJavaSyntax = true
|
||||
# Enables modern Java syntax support. Valid values:
|
||||
# - false: No modern syntax, Java 8 only
|
||||
# - jabel: Jabel syntax-only support, compiles to J8 bytecode
|
||||
# - jvmDowngrader: Full modern Java via JVM Downgrader (syntax + stdlib APIs)
|
||||
# - modern: Native modern Java bytecode, no downgrading
|
||||
enableModernJavaSyntax = jabel
|
||||
|
||||
# If set, ignores the above setting and compiles with the given toolchain. This may cause unexpected issues,
|
||||
# and should *not* be used in most situations. -1 disables this.
|
||||
# forceToolchainVersion = -1
|
||||
|
||||
# Target JVM version for JVM Downgrader bytecode downgrading.
|
||||
# Only used when enableModernJavaSyntax = jvmDowngrader
|
||||
# downgradeTargetVersion = 8
|
||||
|
||||
# Comma-separated list of Java versions for multi-release jar support (JVM Downgrader only).
|
||||
# Classes will be available in META-INF/versions/N/ for each version N in this list.
|
||||
# Default: "21,25" (J25+ gets native classes, J21-24 gets partial downgrade, J8-20 gets full downgrade).
|
||||
# jvmDowngraderMultiReleaseVersions = 21,25
|
||||
|
||||
# Specifies how JVM Downgrader API stubs are provided. Options:
|
||||
# - shade: Shade minimized stubs into the jar
|
||||
# - gtnhlib: GTNHLib provides stubs at runtime (adds version constraint)
|
||||
# - external: Another dependency provides stubs (no constraint, no warning)
|
||||
# - (empty): Warning reminding you to configure stubs
|
||||
# Note: 'shade' option requires you to verify license compliance, see: https://github.com/unimined/JvmDowngrader/blob/main/LICENSE.md
|
||||
# jvmDowngraderStubsProvider =
|
||||
|
||||
# Enables injecting missing generics into the decompiled source code for a better coding experience.
|
||||
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
|
||||
@@ -90,7 +114,9 @@ usesMixinDebug = false
|
||||
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
|
||||
mixinPlugin =
|
||||
|
||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
||||
# Specify the package that contains all of your Mixins. The package must exist or
|
||||
# the build will fail. If you have a package property defined in your mixins.<modid>.json,
|
||||
# it must match with this or the build will fail.
|
||||
mixinsPackage =
|
||||
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
@@ -166,6 +192,12 @@ curseForgeRelations =
|
||||
# projects. New projects should not use this parameter.
|
||||
# customArchiveBaseName =
|
||||
|
||||
# Optional parameter to customize the default working directory used by the runClient* tasks. Relative to the project directory.
|
||||
# runClientWorkingDirectory = run/client
|
||||
|
||||
# Optional parameter to customize the default working directory used by the runServer* tasks. Relative to the project directory.
|
||||
# runServerWorkingDirectory = run/server
|
||||
|
||||
# Optional parameter to have the build automatically fail if an illegal version is used.
|
||||
# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'.
|
||||
# The check is ONLY performed if the version is a git tag.
|
||||
@@ -195,3 +227,6 @@ curseForgeRelations =
|
||||
# This is meant to be set in $HOME/.gradle/gradle.properties.
|
||||
# ideaCheckSpotlessOnBuild = true
|
||||
|
||||
# Non-GTNH properties
|
||||
org.gradle.configuration-cache = true
|
||||
org.gradle.parallel = true
|
||||
@@ -0,0 +1,12 @@
|
||||
#This file is generated by updateDaemonJvm
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/46949723aaa20c7b64d7ecfed7207034/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/f636c800fdb3f9ae33f019dfa048ba72/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1e91f45234d88a64dafb961c93ddc75a/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/552c7bffe0370c66410a51c55985b511/redirect
|
||||
toolchainVersion=25
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -114,7 +114,6 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -172,7 +171,6 @@ fi
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
@@ -212,8 +210,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+1
-2
@@ -70,11 +70,10 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.41'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.21'
|
||||
}
|
||||
|
||||
|
||||
@@ -5,32 +5,19 @@ import java.lang.reflect.Field;
|
||||
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import cpw.mods.fml.common.asm.transformers.AccessTransformer;
|
||||
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
|
||||
|
||||
// This AccessTransformer will make all minecraft classes public at runtime in MCP just as they are in modloader.
|
||||
// You should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include
|
||||
// access transformers. Such mods are doing the wrong thing and should be fixed.
|
||||
public class CodeChickenAccessTransformer extends AccessTransformer {
|
||||
|
||||
private static boolean makeAllPublic;
|
||||
private static Field f_classNameBiMap;
|
||||
private static final Field f_classNameBiMap;
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
private static Object emptyMap = ImmutableBiMap.of();
|
||||
|
||||
public CodeChickenAccessTransformer() throws IOException {
|
||||
super();
|
||||
loadPublicConfig();
|
||||
}
|
||||
|
||||
private void loadPublicConfig() {
|
||||
if (ObfMapping.obfuscated) return;
|
||||
|
||||
makeAllPublic = CodeChickenCoreModContainer.config.getTag("dev.runtimePublic").setComment(
|
||||
"Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader."
|
||||
+ "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers."
|
||||
+ "\nSuch mods are doing the wrong thing and should be fixed.")
|
||||
.getBooleanValue(false);
|
||||
|
||||
if (!makeAllPublic) return;
|
||||
|
||||
static {
|
||||
try {
|
||||
f_classNameBiMap = FMLDeobfuscatingRemapper.class.getDeclaredField("classNameBiMap");
|
||||
f_classNameBiMap.setAccessible(true);
|
||||
@@ -39,16 +26,18 @@ public class CodeChickenAccessTransformer extends AccessTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
public CodeChickenAccessTransformer() throws IOException {}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||
boolean setPublic = makeAllPublic && name.startsWith("net.minecraft.");
|
||||
boolean setPublic = name.startsWith("net.minecraft.");
|
||||
if (setPublic) setClassMap(name);
|
||||
bytes = super.transform(name, transformedName, bytes);
|
||||
if (setPublic) restoreClassMap();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void restoreClassMap() {
|
||||
private static void restoreClassMap() {
|
||||
try {
|
||||
f_classNameBiMap.set(FMLDeobfuscatingRemapper.INSTANCE, emptyMap);
|
||||
} catch (Exception e) {
|
||||
@@ -56,7 +45,7 @@ public class CodeChickenAccessTransformer extends AccessTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
private void setClassMap(String name) {
|
||||
private static void setClassMap(String name) {
|
||||
try {
|
||||
f_classNameBiMap.set(FMLDeobfuscatingRemapper.INSTANCE, ImmutableBiMap.of(name.replace('.', '/'), ""));
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package codechicken.core.asm;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -13,7 +12,6 @@ import codechicken.core.ClientUtils;
|
||||
import codechicken.core.featurehack.LiquidTextures;
|
||||
import codechicken.core.internal.CCCEventHandler;
|
||||
import codechicken.core.launch.CodeChickenCorePlugin;
|
||||
import codechicken.lib.config.ConfigFile;
|
||||
import cpw.mods.fml.common.DummyModContainer;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.LoadController;
|
||||
@@ -26,14 +24,6 @@ import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
public class CodeChickenCoreModContainer extends DummyModContainer {
|
||||
|
||||
public static ConfigFile config;
|
||||
|
||||
public static void loadConfig() {
|
||||
if (config == null)
|
||||
config = new ConfigFile(new File(CodeChickenCorePlugin.minecraftDir, "config/CodeChickenCore.cfg"))
|
||||
.setComment("CodeChickenCore configuration file.");
|
||||
}
|
||||
|
||||
public CodeChickenCoreModContainer() {
|
||||
super(getModMetadata());
|
||||
}
|
||||
|
||||
@@ -7,35 +7,50 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import codechicken.lib.asm.ASMHelper;
|
||||
import codechicken.lib.asm.ClassHeirachyManager;
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
|
||||
public class DefaultImplementationTransformer implements IClassTransformer {
|
||||
|
||||
private static LaunchClassLoader cl = (LaunchClassLoader) ClassHeirachyManager.class.getClassLoader();
|
||||
private static final HashMap<String, InterfaceImpl> impls = new HashMap<>();
|
||||
|
||||
private static ClassNode getClassNode(String name) {
|
||||
try {
|
||||
return ASMHelper.createClassNode(cl.getClassBytes(name.replace('/', '.')));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
public static void registerDefaultImpl(String iname, String cname) {
|
||||
if (impls.isEmpty()) {
|
||||
String name = DefaultImplementationTransformer.class.getName();
|
||||
FMLRelaunchLog.finer("Registering transformer %s", name);
|
||||
Launch.classLoader.registerTransformer(name);
|
||||
}
|
||||
impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||
if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes;
|
||||
|
||||
ClassNode cnode = ASMHelper.createClassNode(bytes);
|
||||
boolean changed = false;
|
||||
for (String iname : cnode.interfaces) {
|
||||
InterfaceImpl impl = impls.get(iname);
|
||||
if (impl != null) changed |= impl.patch(cnode);
|
||||
}
|
||||
|
||||
return changed ? ASMHelper.createBytes(cnode, 0) : bytes;
|
||||
}
|
||||
|
||||
static class InterfaceImpl {
|
||||
|
||||
public final String iname;
|
||||
public ArrayList<MethodNode> impls = new ArrayList<MethodNode>();
|
||||
public ArrayList<MethodNode> impls = new ArrayList<>();
|
||||
|
||||
public InterfaceImpl(String iname, String cname) {
|
||||
this.iname = iname;
|
||||
HashSet<String> names = new HashSet<String>();
|
||||
HashSet<String> names = new HashSet<>();
|
||||
ClassNode inode = getClassNode(iname);
|
||||
for (MethodNode method : inode.methods) names.add(method.name + method.desc);
|
||||
|
||||
@@ -47,7 +62,7 @@ public class DefaultImplementationTransformer implements IClassTransformer {
|
||||
}
|
||||
|
||||
public boolean patch(ClassNode cnode) {
|
||||
LinkedList<String> names = new LinkedList<String>();
|
||||
LinkedList<String> names = new LinkedList<>();
|
||||
for (MethodNode method : cnode.methods) {
|
||||
ObfMapping m = new ObfMapping(cnode.name, method.name, method.desc).toRuntime();
|
||||
names.add(m.s_name + m.s_desc);
|
||||
@@ -69,25 +84,13 @@ public class DefaultImplementationTransformer implements IClassTransformer {
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
private static HashMap<String, InterfaceImpl> impls = new HashMap<String, InterfaceImpl>();
|
||||
|
||||
public static void registerDefaultImpl(String iname, String cname) {
|
||||
impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||
if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes;
|
||||
|
||||
ClassNode cnode = ASMHelper.createClassNode(bytes);
|
||||
boolean changed = false;
|
||||
for (String iname : cnode.interfaces) {
|
||||
InterfaceImpl impl = impls.get(iname);
|
||||
if (impl != null) changed |= impl.patch(cnode);
|
||||
private static ClassNode getClassNode(String name) {
|
||||
try {
|
||||
return ASMHelper.createClassNode(Launch.classLoader.getClassBytes(name.replace('/', '.')));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return changed ? ASMHelper.createBytes(cnode, 0) : bytes;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package codechicken.core.asm;
|
||||
|
||||
import static codechicken.core.launch.CodeChickenCorePlugin.logger;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -11,7 +9,9 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
@@ -21,14 +21,18 @@ import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import codechicken.core.launch.CodeChickenCorePlugin;
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
|
||||
public class DelegatedTransformer implements IClassTransformer {
|
||||
|
||||
private static ArrayList<IClassTransformer> delegatedTransformers;
|
||||
private static Method m_defineClass;
|
||||
private static Field f_cachedClasses;
|
||||
private static final ArrayList<IClassTransformer> delegatedTransformers;
|
||||
private static final Method m_defineClass;
|
||||
private static final Field f_cachedClasses;
|
||||
private static IClassTransformer[] transformers;
|
||||
|
||||
public DelegatedTransformer() {
|
||||
delegatedTransformers = new ArrayList<IClassTransformer>();
|
||||
static {
|
||||
delegatedTransformers = new ArrayList<>();
|
||||
try {
|
||||
m_defineClass = ClassLoader.class
|
||||
.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
|
||||
@@ -41,14 +45,75 @@ public class DelegatedTransformer implements IClassTransformer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String tname, byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
for (IClassTransformer trans : delegatedTransformers) bytes = trans.transform(name, tname, bytes);
|
||||
return bytes;
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
for (IClassTransformer t : transformers) {
|
||||
basicClass = t.transform(name, transformedName, basicClass);
|
||||
}
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
scanModsForDelegatedTransformers();
|
||||
final int size = delegatedTransformers.size();
|
||||
if (size == 0) {
|
||||
CodeChickenCorePlugin.logger
|
||||
.debug("No delegated transformer found, skipping registration of main DelegatedTransformer.");
|
||||
return;
|
||||
}
|
||||
CodeChickenCorePlugin.logger
|
||||
.debug("Found " + size + " delegated transformers, registering main DelegatedTransformer.");
|
||||
transformers = delegatedTransformers.toArray(new IClassTransformer[0]);
|
||||
String name = DelegatedTransformer.class.getName();
|
||||
FMLRelaunchLog.finer("Registering transformer %s", name);
|
||||
Launch.classLoader.registerTransformer(name);
|
||||
}
|
||||
|
||||
private static void scanModsForDelegatedTransformers() {
|
||||
File modsDir = new File(CodeChickenCorePlugin.minecraftDir, "mods");
|
||||
if (modsDir.exists()) {
|
||||
final File[] files = modsDir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
scanMod(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
File versionModsDir = new File(
|
||||
CodeChickenCorePlugin.minecraftDir,
|
||||
"mods/" + CodeChickenCorePlugin.currentMcVersion);
|
||||
if (versionModsDir.exists()) {
|
||||
final File[] files = versionModsDir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
scanMod(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void scanMod(File file) {
|
||||
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return;
|
||||
|
||||
try {
|
||||
try (JarFile jar = new JarFile(file)) {
|
||||
Manifest manifest = jar.getManifest();
|
||||
if (manifest == null) return;
|
||||
Attributes attr = manifest.getMainAttributes();
|
||||
if (attr == null) return;
|
||||
|
||||
String transformer = attr.getValue("CCTransformer");
|
||||
if (transformer != null) {
|
||||
addTransformer(transformer, jar, file);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CodeChickenCorePlugin.logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addTransformer(String transformer, JarFile jar, File jarFile) {
|
||||
logger.debug("Adding CCTransformer: " + transformer);
|
||||
CodeChickenCorePlugin.logger.debug("Adding CCTransformer: " + transformer);
|
||||
try {
|
||||
byte[] bytes;
|
||||
bytes = Launch.classLoader.getClassBytes(transformer);
|
||||
@@ -107,7 +172,7 @@ public class DelegatedTransformer implements IClassTransformer {
|
||||
byte[] depbytes = readFully(jar.getInputStream(entry));
|
||||
defineDependancies(depbytes, jar, jarFile, depStack);
|
||||
|
||||
logger.debug("Defining dependancy: " + dependancy);
|
||||
CodeChickenCorePlugin.logger.debug("Defining dependancy: " + dependancy);
|
||||
|
||||
defineClass(dependancy.replace('/', '.'), depbytes);
|
||||
}
|
||||
@@ -128,7 +193,6 @@ public class DelegatedTransformer implements IClassTransformer {
|
||||
while ((r = stream.read()) != -1) {
|
||||
bos.write(r);
|
||||
}
|
||||
|
||||
return bos.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import codechicken.lib.asm.ASMHelper;
|
||||
import codechicken.lib.asm.ASMInit;
|
||||
import codechicken.lib.asm.CC_ClassWriter;
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import codechicken.obfuscator.IHeirachyEvaluator;
|
||||
@@ -35,15 +34,11 @@ import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator {
|
||||
|
||||
static {
|
||||
ASMInit.init();
|
||||
}
|
||||
|
||||
public static class LoadPlugin implements IFMLLoadingPlugin {
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return new String[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,26 +113,20 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
CodeChickenCoreModContainer.loadConfig();
|
||||
run = new ObfuscationRun(
|
||||
false,
|
||||
ObfMapping.MCPRemapper.getConfFiles(),
|
||||
ObfuscationRun.fillDefaults(new HashMap<String, String>()));
|
||||
run.obf.setHeirachyEvaluator(instance);
|
||||
run.setQuiet().parseMappings();
|
||||
Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";"));
|
||||
|
||||
if (CodeChickenCoreModContainer.config.getTag("dev.deobfuscate")
|
||||
.setComment("set to true to completely deobfuscate mcp names")
|
||||
.getBooleanValue(!ObfMapping.obfuscated)) {
|
||||
run = new ObfuscationRun(
|
||||
false,
|
||||
ObfMapping.MCPRemapper.getConfFiles(),
|
||||
ObfuscationRun.fillDefaults(new HashMap<String, String>()));
|
||||
run.obf.setHeirachyEvaluator(instance);
|
||||
run.setQuiet().parseMappings();
|
||||
Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";"));
|
||||
|
||||
if (ObfMapping.obfuscated) {
|
||||
ObfMapping.loadMCPRemapper();
|
||||
run.setSeargeConstants();
|
||||
getTransformers().add(instance);
|
||||
} else {
|
||||
getTransformers().add(0, instance); // insert transformer as first.
|
||||
}
|
||||
if (ObfMapping.obfuscated) {
|
||||
ObfMapping.loadMCPRemapper();
|
||||
run.setSeargeConstants();
|
||||
getTransformers().add(instance);
|
||||
} else {
|
||||
getTransformers().add(0, instance); // insert transformer as first.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,15 @@ import static codechicken.lib.asm.InsnComparator.findOnce;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import codechicken.core.launch.CodeChickenCorePlugin;
|
||||
import codechicken.lib.asm.ASMBlock;
|
||||
import codechicken.lib.asm.ASMInit;
|
||||
import codechicken.lib.asm.ASMReader;
|
||||
import codechicken.lib.asm.ModularASMTransformer;
|
||||
import codechicken.lib.asm.ModularASMTransformer.MethodReplacer;
|
||||
@@ -20,20 +21,29 @@ import codechicken.lib.asm.ModularASMTransformer.MethodTransformer;
|
||||
import codechicken.lib.asm.ModularASMTransformer.MethodWriter;
|
||||
import codechicken.lib.asm.ObfMapping;
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
|
||||
public class TweakTransformer implements IClassTransformer, Opcodes {
|
||||
|
||||
static {
|
||||
ASMInit.init();
|
||||
}
|
||||
|
||||
private static ModularASMTransformer transformer = new ModularASMTransformer();
|
||||
private static Map<String, ASMBlock> blocks = ASMReader.loadResource("/assets/codechickencore/asm/tweaks.asm");
|
||||
private static final ModularASMTransformer transformer = new ModularASMTransformer();
|
||||
private static final Map<String, ASMBlock> blocks = ASMReader
|
||||
.loadResource("/assets/codechickencore/asm/tweaks.asm");
|
||||
public static ConfigTag tweaks;
|
||||
|
||||
public static void load() {
|
||||
CodeChickenCoreModContainer.loadConfig();
|
||||
tweaks = CodeChickenCoreModContainer.config.getTag("tweaks")
|
||||
loadTransformersFromConfig();
|
||||
if (transformer.isEmpty()) {
|
||||
CodeChickenCorePlugin.logger
|
||||
.debug("No tweaks parsed from config, skipping registration of TweakTransformer.");
|
||||
return;
|
||||
}
|
||||
String name = TweakTransformer.class.getName();
|
||||
FMLRelaunchLog.finer("Registering transformer %s", name);
|
||||
Launch.classLoader.registerTransformer(name);
|
||||
}
|
||||
|
||||
private static void loadTransformersFromConfig() {
|
||||
tweaks = CodeChickenCorePlugin.config.getTag("tweaks")
|
||||
.setComment("Various tweaks that can be applied to game mechanics.").useBraces();
|
||||
tweaks.removeTag("persistantLava");
|
||||
|
||||
@@ -103,7 +113,7 @@ public class TweakTransformer implements IClassTransformer, Opcodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String tname, byte[] bytes) {
|
||||
public final byte[] transform(String name, String tname, byte[] bytes) {
|
||||
return transformer.transform(name, bytes);
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,6 @@ import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JOptionPane;
|
||||
@@ -21,48 +18,87 @@ import javax.swing.event.HyperlinkListener;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import codechicken.core.asm.CodeChickenCoreModContainer;
|
||||
import codechicken.core.asm.DelegatedTransformer;
|
||||
import codechicken.core.asm.MCPDeobfuscationTransformer;
|
||||
import codechicken.core.asm.Tags;
|
||||
import codechicken.core.asm.TweakTransformer;
|
||||
import codechicken.lib.config.ConfigFile;
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionParser;
|
||||
import cpw.mods.fml.relauncher.CoreModManager;
|
||||
import cpw.mods.fml.relauncher.FMLInjectionData;
|
||||
import cpw.mods.fml.relauncher.IFMLCallHook;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions;
|
||||
|
||||
@TransformerExclusions(value = { "codechicken.core.asm", "codechicken.obfuscator" })
|
||||
@MCVersion("1.7.10")
|
||||
public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook {
|
||||
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
||||
@IFMLLoadingPlugin.TransformerExclusions({ "codechicken.core.asm", "codechicken.obfuscator", "codechicken.lib.asm",
|
||||
"codechicken.lib.config" })
|
||||
public class CodeChickenCorePlugin implements IFMLLoadingPlugin {
|
||||
|
||||
public static final String mcVersion = "[1.7.10]";
|
||||
|
||||
@Deprecated
|
||||
public static final String version = Tags.VERSION;
|
||||
|
||||
public static ConfigFile config;
|
||||
public static File minecraftDir;
|
||||
public static String currentMcVersion;
|
||||
public static Logger logger = LogManager.getLogger("CodeChickenCore");
|
||||
|
||||
public CodeChickenCorePlugin() {
|
||||
if (minecraftDir != null) return; // get called twice, once for IFMLCallHook
|
||||
|
||||
if (minecraftDir != null) return;
|
||||
minecraftDir = (File) FMLInjectionData.data()[6];
|
||||
currentMcVersion = (String) FMLInjectionData.data()[4];
|
||||
config = new ConfigFile(new File(minecraftDir, "config/CodeChickenCore.cfg"))
|
||||
.setComment("CodeChickenCore configuration file.");
|
||||
if (Boolean.getBoolean("ccc.dev.deobfuscate")) {
|
||||
injectDeobfPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
injectDeobfPlugin();
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
versionCheck(mcVersion, "CodeChickenCore");
|
||||
return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.lib.asm.RedirectorTransformer" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
if (Boolean.getBoolean("ccc.dev.runtimePublic")) {
|
||||
return "codechicken.core.asm.CodeChickenAccessTransformer";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return "codechicken.core.asm.CodeChickenCoreModContainer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
ConfigTag checkRAM = CodeChickenCorePlugin.config.getTag("checks")
|
||||
.setComment("Configuration options for checking various requirements for a modpack.").useBraces();
|
||||
if (checkRAM.getTag("checkRAM")
|
||||
.setComment("If set to true, check RAM available for Minecraft before continuing to load")
|
||||
.getBooleanValue(false)) {
|
||||
systemCheck(checkRAM);
|
||||
}
|
||||
TweakTransformer.load();
|
||||
DelegatedTransformer.load();
|
||||
}
|
||||
|
||||
private void injectDeobfPlugin() {
|
||||
try {
|
||||
Class<?> wrapperClass = Class.forName("cpw.mods.fml.relauncher.CoreModManager$FMLPluginWrapper");
|
||||
Constructor wrapperConstructor = wrapperClass
|
||||
Constructor<?> wrapperConstructor = wrapperClass
|
||||
.getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class);
|
||||
Field f_loadPlugins = CoreModManager.class.getDeclaredField("loadPlugins");
|
||||
wrapperConstructor.setAccessible(true);
|
||||
@@ -76,7 +112,7 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook {
|
||||
0,
|
||||
new String[0]));
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to inject MCPDeobfuscation Transformer", e);
|
||||
logger.error("Failed to inject FMLPluginWrapper for MCPDeobfuscation Transformer", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,74 +222,4 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook {
|
||||
FMLCommonHandler.instance().exitJava(-98, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
versionCheck(mcVersion, "CodeChickenCore");
|
||||
return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.core.asm.TweakTransformer",
|
||||
"codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer",
|
||||
"codechicken.lib.asm.RedirectorTransformer" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return "codechicken.core.asm.CodeChickenAccessTransformer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return "codechicken.core.asm.CodeChickenCoreModContainer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {}
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
CodeChickenCoreModContainer.loadConfig();
|
||||
ConfigTag checkRAM;
|
||||
checkRAM = CodeChickenCoreModContainer.config.getTag("checks")
|
||||
.setComment("Configuration options for checking various requirements for a modpack.").useBraces();
|
||||
if (checkRAM.getTag("checkRAM")
|
||||
.setComment("If set to true, check RAM available for Minecraft before continuing to load")
|
||||
.getBooleanValue(false))
|
||||
systemCheck(checkRAM);
|
||||
TweakTransformer.load();
|
||||
scanCodeChickenMods();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void scanCodeChickenMods() {
|
||||
File modsDir = new File(minecraftDir, "mods");
|
||||
for (File file : modsDir.listFiles()) scanMod(file);
|
||||
File versionModsDir = new File(minecraftDir, "mods/" + currentMcVersion);
|
||||
if (versionModsDir.exists()) for (File file : versionModsDir.listFiles()) scanMod(file);
|
||||
}
|
||||
|
||||
private void scanMod(File file) {
|
||||
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return;
|
||||
|
||||
try {
|
||||
JarFile jar = new JarFile(file);
|
||||
try {
|
||||
Manifest manifest = jar.getManifest();
|
||||
if (manifest == null) return;
|
||||
Attributes attr = manifest.getMainAttributes();
|
||||
if (attr == null) return;
|
||||
|
||||
String transformer = attr.getValue("CCTransformer");
|
||||
if (transformer != null) DelegatedTransformer.addTransformer(transformer, jar, file);
|
||||
} finally {
|
||||
jar.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
package codechicken.lib.asm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
|
||||
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
|
||||
|
||||
@@ -18,47 +16,60 @@ import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
|
||||
*/
|
||||
public class ClassHeirachyManager implements IClassTransformer {
|
||||
|
||||
private static final Map<String, ClassInfo> superclasses = new ConcurrentHashMap<>(1000);
|
||||
|
||||
static {
|
||||
ASMInit.init();
|
||||
superclasses.put("java.lang.Object", ClassInfo.OBJECT);
|
||||
}
|
||||
|
||||
public static class SuperCache {
|
||||
|
||||
String superclass;
|
||||
public HashSet<String> parents = new HashSet<String>();
|
||||
private boolean flattened;
|
||||
|
||||
public void add(String parent) {
|
||||
parents.add(parent);
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
if (!superclasses.containsKey(transformedName)) {
|
||||
declareASM(transformedName, bytes);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void flatten() {
|
||||
if (flattened) return;
|
||||
private static ClassInfo declareASM(String name, byte[] bytes) {
|
||||
final ClassReader classReader = new ClassReader(bytes);
|
||||
final ClassInfo classInfo = new ClassInfo(classReader);
|
||||
superclasses.put(name, classInfo);
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
for (String s : new ArrayList<String>(parents)) {
|
||||
SuperCache c = declareClass(s);
|
||||
if (c != null) {
|
||||
c.flatten();
|
||||
parents.addAll(c.parents);
|
||||
}
|
||||
private static ClassInfo declareReflection(String name) throws ClassNotFoundException {
|
||||
final Class<?> aclass = Class.forName(name);
|
||||
final ClassInfo classInfo = new ClassInfo(aclass);
|
||||
superclasses.put(name, classInfo);
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
private static ClassInfo declareClass(String name) {
|
||||
try {
|
||||
byte[] bytes = Launch.classLoader.getClassBytes(unKey(name));
|
||||
if (bytes != null) {
|
||||
return declareASM(name, bytes);
|
||||
}
|
||||
flattened = true;
|
||||
} catch (Exception ignored) {}
|
||||
try {
|
||||
return declareReflection(name);
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String toKey(String name) {
|
||||
if (ObfMapping.obfuscated) {
|
||||
return FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.');
|
||||
}
|
||||
return name.replace('/', '.');
|
||||
}
|
||||
|
||||
public static HashMap<String, SuperCache> superclasses = new HashMap<String, SuperCache>();
|
||||
private static LaunchClassLoader cl = Launch.classLoader;
|
||||
|
||||
public static String toKey(String name) {
|
||||
if (ObfMapping.obfuscated)
|
||||
name = FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.');
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String unKey(String name) {
|
||||
if (ObfMapping.obfuscated)
|
||||
name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.');
|
||||
return name;
|
||||
private static String unKey(String name) {
|
||||
if (ObfMapping.obfuscated) {
|
||||
return FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.');
|
||||
}
|
||||
return name.replace('/', '.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,83 +83,94 @@ public class ClassHeirachyManager implements IClassTransformer {
|
||||
|
||||
if (name.equals(superclass)) return true;
|
||||
|
||||
SuperCache cache = declareClass(name);
|
||||
if (cache == null) // just can't handle this
|
||||
return false;
|
||||
ClassInfo classInfo = superclasses.get(name);
|
||||
if (classInfo == null) classInfo = declareClass(name);
|
||||
if (classInfo == null) return false;
|
||||
|
||||
cache.flatten();
|
||||
return cache.parents.contains(superclass);
|
||||
}
|
||||
|
||||
private static SuperCache declareClass(String name) {
|
||||
name = toKey(name);
|
||||
SuperCache cache = superclasses.get(name);
|
||||
|
||||
if (cache != null) return cache;
|
||||
|
||||
try {
|
||||
byte[] bytes = cl.getClassBytes(unKey(name));
|
||||
if (bytes != null) cache = declareASM(bytes);
|
||||
} catch (Exception e) {}
|
||||
|
||||
if (cache != null) return cache;
|
||||
|
||||
try {
|
||||
cache = declareReflection(name);
|
||||
} catch (ClassNotFoundException e) {}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
private static SuperCache declareReflection(String name) throws ClassNotFoundException {
|
||||
Class<?> aclass = Class.forName(name);
|
||||
|
||||
SuperCache cache = getOrCreateCache(name);
|
||||
if (aclass.isInterface()) cache.superclass = "java.lang.Object";
|
||||
else if (name.equals("java.lang.Object")) return cache;
|
||||
else cache.superclass = toKey(aclass.getSuperclass().getName());
|
||||
|
||||
cache.add(cache.superclass);
|
||||
for (Class<?> iclass : aclass.getInterfaces()) cache.add(toKey(iclass.getName()));
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
private static SuperCache declareASM(byte[] bytes) {
|
||||
ClassNode node = ASMHelper.createClassNode(bytes);
|
||||
String name = toKey(node.name);
|
||||
|
||||
SuperCache cache = getOrCreateCache(name);
|
||||
cache.superclass = toKey(node.superName.replace('/', '.'));
|
||||
cache.add(cache.superclass);
|
||||
for (String iclass : node.interfaces) cache.add(toKey(iclass.replace('/', '.')));
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String tname, byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
|
||||
if (!superclasses.containsKey(tname)) declareASM(bytes);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static SuperCache getOrCreateCache(String name) {
|
||||
SuperCache cache = superclasses.get(name);
|
||||
if (cache == null) superclasses.put(name, cache = new SuperCache());
|
||||
return cache;
|
||||
return classInfo.hasSuper(superclass);
|
||||
}
|
||||
|
||||
public static String getSuperClass(String name, boolean runtime) {
|
||||
name = toKey(name);
|
||||
SuperCache cache = declareClass(name);
|
||||
if (cache == null) return "java.lang.Object";
|
||||
|
||||
cache.flatten();
|
||||
String s = cache.superclass;
|
||||
if (!runtime) s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s);
|
||||
ClassInfo classInfo = superclasses.get(name);
|
||||
if (classInfo == null) classInfo = declareClass(name);
|
||||
if (classInfo == null || classInfo.superclass == null) return "java.lang.Object";
|
||||
|
||||
final String s = classInfo.superclass;
|
||||
if (!runtime) {
|
||||
return FMLDeobfuscatingRemapper.INSTANCE.unmap(s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private static class ClassInfo {
|
||||
|
||||
public static final ClassInfo OBJECT = new ClassInfo();
|
||||
|
||||
public final String superclass;
|
||||
public final String[] interfaces;
|
||||
public ClassInfo parent;
|
||||
|
||||
private ClassInfo() {
|
||||
this.superclass = null;
|
||||
this.interfaces = null;
|
||||
}
|
||||
|
||||
public ClassInfo(ClassReader classReader) {
|
||||
final String superName = classReader.getSuperName();
|
||||
final String[] interfaces = classReader.getInterfaces();
|
||||
|
||||
if (superName == null || "java/lang/Object".equals(superName)) {
|
||||
superclass = "java.lang.Object";
|
||||
parent = OBJECT;
|
||||
} else {
|
||||
superclass = toKey(superName);
|
||||
}
|
||||
|
||||
if (interfaces == null || interfaces.length == 0) {
|
||||
this.interfaces = null;
|
||||
} else {
|
||||
this.interfaces = new String[interfaces.length];
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
this.interfaces[i] = toKey(interfaces[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ClassInfo(Class<?> aclass) {
|
||||
if (aclass.isInterface()) {
|
||||
this.superclass = "java.lang.Object";
|
||||
this.parent = OBJECT;
|
||||
} else {
|
||||
final Class<?> superclass = aclass.getSuperclass();
|
||||
if (superclass == null || "java.lang.Object".equals(superclass.getName())) {
|
||||
this.superclass = "java.lang.Object";
|
||||
this.parent = OBJECT;
|
||||
} else {
|
||||
this.superclass = toKey(superclass.getName());
|
||||
}
|
||||
}
|
||||
final Class<?>[] interfaces = aclass.getInterfaces();
|
||||
if (interfaces.length == 0) {
|
||||
this.interfaces = null;
|
||||
} else {
|
||||
this.interfaces = new String[interfaces.length];
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
this.interfaces[i] = toKey(interfaces[i].getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasSuper(String superclass) {
|
||||
if (this.superclass == null) return false;
|
||||
if (this.superclass.equals(superclass)) return true;
|
||||
ClassInfo parentInfo = this.parent;
|
||||
if (parentInfo == null) parentInfo = superclasses.get(this.superclass);
|
||||
if (parentInfo == null) parentInfo = declareClass(this.superclass);
|
||||
if (parentInfo == null) return false;
|
||||
this.parent = parentInfo;
|
||||
return parentInfo.hasSuper(superclass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,17 +275,22 @@ public class ModularASMTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<String, ClassNodeTransformerList> transformers = new HashMap<String, ClassNodeTransformerList>();
|
||||
public HashMap<String, ClassNodeTransformerList> transformers = new HashMap<>();
|
||||
|
||||
public void add(ClassNodeTransformer t) {
|
||||
ClassNodeTransformerList list = transformers.get(t.className());
|
||||
if (list == null) transformers.put(t.className(), list = new ClassNodeTransformerList());
|
||||
if (list == null) {
|
||||
transformers.put(t.className(), list = new ClassNodeTransformerList());
|
||||
}
|
||||
list.add(t);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return transformers.isEmpty();
|
||||
}
|
||||
|
||||
public byte[] transform(String name, byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
|
||||
ClassNodeTransformerList list = transformers.get(name);
|
||||
return list == null ? bytes : list.transform(bytes);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user