aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java
diff options
context:
space:
mode:
authorDJtheRedstoner <52044242+DJtheRedstoner@users.noreply.github.com>2021-08-25 09:52:20 -0400
committerDJtheRedstoner <52044242+DJtheRedstoner@users.noreply.github.com>2021-08-25 09:52:20 -0400
commit61afd7b0843ff4a4438eb9f97c4ba29e57408aa5 (patch)
tree3fa8f89498d01cb094d9bfc4d9c09ab47c474f5b /src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java
parent12888a9eb0469a5462e497a29eb4d3d15bb48f3c (diff)
downloadPerspectiveModv4-61afd7b0843ff4a4438eb9f97c4ba29e57408aa5.tar.gz
PerspectiveModv4-61afd7b0843ff4a4438eb9f97c4ba29e57408aa5.tar.bz2
PerspectiveModv4-61afd7b0843ff4a4438eb9f97c4ba29e57408aa5.zip
Revert "this is why we can't have nice things"
This reverts commit 12888a9eb0469a5462e497a29eb4d3d15bb48f3c.
Diffstat (limited to 'src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java')
-rw-r--r--src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java b/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java
new file mode 100644
index 0000000..c7db68b
--- /dev/null
+++ b/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java
@@ -0,0 +1,118 @@
+package me.djtheredstoner.perspectivemod.asm;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import me.djtheredstoner.perspectivemod.asm.transformers.ActiveRenderInfoTransformer;
+import me.djtheredstoner.perspectivemod.asm.transformers.EntityRendererTransformer;
+import me.djtheredstoner.perspectivemod.asm.transformers.MinecraftTransformer;
+import me.djtheredstoner.perspectivemod.asm.transformers.RenderManagerTransformer;
+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.tree.ClassNode;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+
+public class ClassTransformer implements IClassTransformer {
+
+ // create a logger to distinguish our errors from a normal error
+ private static final Logger LOGGER = LogManager.getLogger("Perspective Mod v4 Transformer");
+
+ // create a map of transformers
+ private final Multimap<String, ITransformer> transformerMap = ArrayListMultimap.create();
+
+ // make a jvm flag that could be used to dump transformed classes
+ // usable by adding -DdebugBytecode=true to the jvm arguments
+ public static final boolean outputBytecode = Boolean.parseBoolean(System.getProperty("debugBytecode", "false"));
+
+ public ClassTransformer() {
+ // any transformer will be registered here
+ registerTransformer(new EntityRendererTransformer());
+ registerTransformer(new RenderManagerTransformer());
+ registerTransformer(new MinecraftTransformer());
+ registerTransformer(new ActiveRenderInfoTransformer());
+ }
+
+ private void registerTransformer(ITransformer transformer) {
+ // loop through names of classes
+ for (String cls : transformer.getClassName()) {
+ // put the classes into the transformer map
+ transformerMap.put(cls, transformer);
+ }
+ }
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ @Override
+ public byte[] transform(String name, String transformedName, byte[] bytes) {
+ if (bytes == null) return null;
+
+ // get the list of transformers
+ Collection<ITransformer> transformers = transformerMap.get(transformedName);
+ // if empty, don't bother trying to run through transformation
+ if (transformers.isEmpty()) return bytes;
+
+ // wjat
+ ClassReader reader = new ClassReader(bytes);
+ ClassNode node = new ClassNode();
+ reader.accept(node, ClassReader.EXPAND_FRAMES);
+
+ // for every transformer, perform the transformations
+ for (ITransformer transformer : transformers) {
+ transformer.transform(node, transformedName);
+ }
+
+ // what?????
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+
+ try {
+ // write™
+ node.accept(writer);
+ } catch (Throwable t) {
+ LOGGER.error("Exception when transforming " + transformedName + " : " + t.getClass().getSimpleName());
+ t.printStackTrace();
+ }
+
+ if (outputBytecode) {
+ File bytecodeDirectory = new File("bytecode");
+ String transformedClassName;
+
+ // anonymous classes
+ if (transformedName.contains("$")) {
+ transformedClassName = transformedName.replace('$', '.') + ".class";
+ } else {
+ transformedClassName = transformedName + ".class";
+ }
+
+ if (!bytecodeDirectory.exists()) {
+ bytecodeDirectory.mkdirs();
+ }
+
+ File bytecodeOutput = new File(bytecodeDirectory, transformedClassName);
+
+ try {
+ if (!bytecodeOutput.exists()) {
+ bytecodeOutput.createNewFile();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ try (FileOutputStream os = new FileOutputStream(bytecodeOutput)) {
+ // write to the generated class to /run/bytecode/classfile.class
+ // with the class bytes from transforming
+ os.write(writer.toByteArray());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // return the written bytes and finalize transform
+ return writer.toByteArray();
+ }
+
+}