mirror of
https://github.com/GTNewHorizons/ThaumicEnergistics.git
synced 2026-10-25 20:32:27 +00:00
Transfer ASM coremod to mixins (#96)
This commit is contained in:
1 parent
43fa73e378
commit
283bb6049c
28 files changed
+281
-1188
No files matched your search
@@ -33,9 +33,3 @@ How To Compile
|
||||
2. Run ./gradlew setupDecompWorkspace build
|
||||
3. Your build shall be in build/libs/
|
||||
|
||||
How To Debug
|
||||
----
|
||||
1. Do step 1 of compile
|
||||
2. Add "-Dfml.coreMods.load=thaumicenergistics.fml.ThECore", without quotes, to your run & debug configuration.
|
||||
In Eclipse, Menu: Run > Run|Debug Configurations > Arguments Tab > VM Arguments.
|
||||
|
||||
+8
-8
@@ -1,20 +1,20 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.GTNewHorizons:NotEnoughItems:2.7.84-GTNH:dev")
|
||||
implementation("com.github.GTNewHorizons:CodeChickenCore:1.4.7:dev")
|
||||
implementation("com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-684-GTNH:dev")
|
||||
implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.40-GTNH:dev")
|
||||
implementation("com.github.GTNewHorizons:CodeChickenCore:1.4.8:dev")
|
||||
implementation("com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-751-GTNH:dev")
|
||||
implementation("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev")
|
||||
implementation("curse.maven:thaumcraft-nei-plugin-225095:2241913") { transitive = false }
|
||||
implementation(rfg.deobf("curse.maven:thaumcraft-nei-plugin-225095:2241913")) { transitive = false }
|
||||
|
||||
compileOnly('com.github.GTNewHorizons:ExtraCells2:2.5.35:dev') { transitive = false }
|
||||
compileOnly('com.github.GTNewHorizons:AE2FluidCraft-Rework:1.4.114-gtnh:dev') { transitive = false }
|
||||
compileOnly("com.github.GTNewHorizons:waila:1.8.12:dev") { transitive = false }
|
||||
compileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.51.454:dev") { transitive = false }
|
||||
compileOnly('com.github.GTNewHorizons:AE2FluidCraft-Rework:1.5.26-gtnh:dev') { transitive = false }
|
||||
compileOnly("com.github.GTNewHorizons:waila:1.9.15:dev") { transitive = false }
|
||||
compileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.132:dev") { transitive = false }
|
||||
compileOnly("curse.maven:computercraft-67504:2269339") { transitive = false }
|
||||
compileOnly("curse.maven:cofh-lib-220333:2388748") { transitive = false }
|
||||
compileOnly("net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev") { transitive = false }
|
||||
|
||||
runtimeOnlyNonPublishable('com.github.GTNewHorizons:GTNHLib:0.6.39:dev')
|
||||
runtimeOnlyNonPublishable('com.github.GTNewHorizons:GTNHLib:0.8.18:dev')
|
||||
runtimeOnly("com.github.GTNewHorizons:Baubles:1.0.4:dev")
|
||||
}
|
||||
+13
-5
@@ -83,7 +83,7 @@ apiPackage = api
|
||||
accessTransformersFile =
|
||||
|
||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||
usesMixins = false
|
||||
usesMixins = true
|
||||
|
||||
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
|
||||
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
|
||||
@@ -91,18 +91,20 @@ usesMixins = false
|
||||
separateMixinSourceSet =
|
||||
|
||||
# Adds some debug arguments like verbose output and class export.
|
||||
usesMixinDebug = false
|
||||
usesMixinDebug = true
|
||||
|
||||
# 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!
|
||||
mixinsPackage =
|
||||
# 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 = mixins
|
||||
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
# This parameter is for legacy compatibility only
|
||||
# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin
|
||||
coreModClass = fml.ThECore
|
||||
coreModClass =
|
||||
|
||||
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
|
||||
# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
|
||||
@@ -172,6 +174,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.
|
||||
|
||||
+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-8.14.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.42'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.48'
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import thaumicenergistics.common.utils.ThELog;
|
||||
modid = ThaumicEnergistics.MOD_ID,
|
||||
name = "Thaumic Energistics",
|
||||
version = ThaumicEnergistics.VERSION,
|
||||
dependencies = "required-after:ThE-core;required-after:appliedenergistics2@[rv3-beta-214,);required-after:Thaumcraft@[4.2.3.5,);after:Waila;after:extracells")
|
||||
dependencies = "required-after:appliedenergistics2@[rv3-beta-214,);required-after:Thaumcraft@[4.2.3.5,);after:Waila;after:extracells")
|
||||
public class ThaumicEnergistics {
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,6 @@ import thaumicenergistics.common.registries.RecipeRegistry;
|
||||
import thaumicenergistics.common.registries.ResearchRegistry;
|
||||
import thaumicenergistics.common.registries.ResearchRegistry.PseudoResearchTypes;
|
||||
import thaumicenergistics.common.registries.ResearchRegistry.ResearchTypes;
|
||||
import thaumicenergistics.fml.ThECore;
|
||||
|
||||
/**
|
||||
* {@link ItemGolemWirelessBackpack} feature.
|
||||
@@ -30,11 +29,6 @@ public class FeatureGolemBackpack extends ThEThaumcraftResearchFeature {
|
||||
|
||||
@Override
|
||||
protected boolean checkConfigs(final IThEConfig theConfig) {
|
||||
// Did the core fail to transform the required classes?
|
||||
if (ThECore.golemHooksTransformFailed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return theConfig.craftGolemWifiBackpack();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import thaumicenergistics.api.entities.IGolemHookHandler.InteractionLevel;
|
||||
import thaumicenergistics.api.entities.IGolemHookSyncRegistry;
|
||||
import thaumicenergistics.common.utils.EffectiveSide;
|
||||
import thaumicenergistics.common.utils.ThELog;
|
||||
import thaumicenergistics.fml.ThECore;
|
||||
|
||||
/**
|
||||
* Golem hook system.<br>
|
||||
@@ -565,11 +564,6 @@ public class GolemHooks {
|
||||
* @param handler
|
||||
*/
|
||||
public static void registerHandler(final @Nonnull IGolemHookHandler handler) {
|
||||
// Ensure the required transforms are present.
|
||||
if (ThECore.golemHooksTransformFailed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Add the handler
|
||||
GolemHooks.registeredHandlers.add(handler);
|
||||
|
||||
@@ -11,35 +11,24 @@ import cpw.mods.fml.relauncher.Side;
|
||||
*/
|
||||
public final class EffectiveSide {
|
||||
|
||||
/**
|
||||
* Cache the handler
|
||||
*/
|
||||
private static FMLCommonHandler FCH = FMLCommonHandler.instance();
|
||||
|
||||
/**
|
||||
* True if the thread executing this code is client side.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isClientSide() {
|
||||
return FCH.getEffectiveSide().isClient();
|
||||
public static boolean isClientSide() {
|
||||
return FMLCommonHandler.instance().getEffectiveSide().isClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the thread executing this code is server side.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isServerSide() {
|
||||
return FCH.getEffectiveSide().isServer();
|
||||
public static boolean isServerSide() {
|
||||
return FMLCommonHandler.instance().getEffectiveSide().isServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective side for the context in the game.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static final Side side() {
|
||||
return FCH.getEffectiveSide();
|
||||
public static Side side() {
|
||||
return FMLCommonHandler.instance().getEffectiveSide();
|
||||
}
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
package thaumicenergistics.fml;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.util.Printer;
|
||||
import org.objectweb.asm.util.Textifier;
|
||||
import org.objectweb.asm.util.TraceMethodVisitor;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
|
||||
public abstract class AClassTransformer {
|
||||
|
||||
protected static final String InstanceConstructorName = "<init>";
|
||||
|
||||
private static Printer asmPrinter = new Textifier();
|
||||
|
||||
private static TraceMethodVisitor asmVisitor = new TraceMethodVisitor(AClassTransformer.asmPrinter);
|
||||
|
||||
/**
|
||||
* Canonical name of the class to be transformed.
|
||||
*/
|
||||
public final String classCanonicalName;
|
||||
|
||||
protected AClassTransformer(final String classCanonicalName) {
|
||||
this.classCanonicalName = classCanonicalName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the first occurrence of the specified opcode.
|
||||
*
|
||||
* @param instructions
|
||||
* @param opcode
|
||||
* @return
|
||||
*/
|
||||
protected AbstractInsnNode findFirstOpCode(final InsnList instructions, final int opcode) {
|
||||
for (int index = 0; index < instructions.size(); ++index) {
|
||||
if (instructions.get(index).getOpcode() == opcode) {
|
||||
return instructions.get(index);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the last occurrence of the specified opcode.
|
||||
*
|
||||
* @param instructions
|
||||
* @param opcode
|
||||
* @return
|
||||
*/
|
||||
protected AbstractInsnNode findLastOpCode(final InsnList instructions, final int opcode) {
|
||||
for (int index = instructions.size() - 1; index > 0; --index) {
|
||||
if (instructions.get(index).getOpcode() == opcode) {
|
||||
return instructions.get(index);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the last occurrence of the specified type.
|
||||
*
|
||||
* @param instructions
|
||||
* @param type
|
||||
* @param number of occurrences to skip
|
||||
* @return
|
||||
*/
|
||||
protected AbstractInsnNode findLastType(final InsnList instructions, final int type, int skip) {
|
||||
for (int index = instructions.size() - 1; index > 0; --index) {
|
||||
if (instructions.get(index).getType() == type) {
|
||||
if (--skip < 0) {
|
||||
return instructions.get(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the next occurrence of the opcode after the specified instruction.
|
||||
*
|
||||
* @param fromInstruction
|
||||
* @param opcode
|
||||
* @return
|
||||
*/
|
||||
protected AbstractInsnNode findNextOpCode(final AbstractInsnNode fromInstruction, final int opcode) {
|
||||
AbstractInsnNode nextInsn = fromInstruction;
|
||||
do {
|
||||
if (nextInsn.getOpcode() == opcode) {
|
||||
return nextInsn;
|
||||
}
|
||||
} while ((nextInsn = nextInsn.getNext()) != null);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates a sequence of instructions.
|
||||
*
|
||||
* @param instructions
|
||||
* @param opSequence
|
||||
* @param skipNons If true all -1 instructions will be skipped
|
||||
* @return The last instruction in the sequence.
|
||||
*/
|
||||
protected AbstractInsnNode findSequence(final InsnList instructions, final int opSequence[],
|
||||
final boolean skipNons) {
|
||||
int seqIndex = 0;
|
||||
AbstractInsnNode insertionPoint = null;
|
||||
for (int index = 0; index < instructions.size(); ++index) {
|
||||
// Get the instruction
|
||||
AbstractInsnNode ins = instructions.get(index);
|
||||
|
||||
if (skipNons && (ins.getOpcode() == -1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Does it match the sequence?
|
||||
if (ins.getOpcode() == opSequence[seqIndex]) {
|
||||
// Has the full sequence been found?
|
||||
if (++seqIndex == opSequence.length) {
|
||||
// Found the full sequence
|
||||
insertionPoint = ins;
|
||||
break;
|
||||
}
|
||||
} else if (ins.getOpcode() == opSequence[0]) {
|
||||
// Restart sequence
|
||||
seqIndex = 1;
|
||||
} else {
|
||||
// Reset sequence
|
||||
seqIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return insertionPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry to the log.
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
protected void log(final String text) {
|
||||
FMLRelaunchLog.log("ThE-Core", Level.INFO, text);
|
||||
}
|
||||
|
||||
protected void logInstructionDetails(final AbstractInsnNode insn) {
|
||||
// Visit the instruction
|
||||
insn.accept(AClassTransformer.asmVisitor);
|
||||
|
||||
// Create the string writer
|
||||
StringWriter sw = new StringWriter();
|
||||
|
||||
// Print the details into the writer
|
||||
AClassTransformer.asmPrinter.print(new PrintWriter(sw));
|
||||
|
||||
// Clear the printer
|
||||
AClassTransformer.asmPrinter.getText().clear();
|
||||
|
||||
// Log the details
|
||||
this.log(sw.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to take if the transform fails.
|
||||
*/
|
||||
protected abstract void onTransformFailure();
|
||||
|
||||
/**
|
||||
* Internal call to transform the class.
|
||||
*
|
||||
* @param classBytes
|
||||
* @return
|
||||
*/
|
||||
protected abstract void transform(ClassNode classNode);
|
||||
|
||||
/**
|
||||
* Transforms the class.
|
||||
*
|
||||
* @param classBytes
|
||||
* @return
|
||||
*/
|
||||
public final byte[] transformClass(final byte[] classBytes) {
|
||||
try {
|
||||
this.log(String.format("Transforming Class (%s)", this.classCanonicalName));
|
||||
|
||||
// Create the class node and read in the class
|
||||
ClassNode classNode = new ClassNode();
|
||||
ClassReader classReader = new ClassReader(classBytes);
|
||||
classReader.accept(classNode, 0);
|
||||
|
||||
// Transform
|
||||
this.transform(classNode);
|
||||
|
||||
// Create the writer
|
||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
classNode.accept(writer);
|
||||
|
||||
// Return the modified class
|
||||
return writer.toByteArray();
|
||||
} catch (Exception e) {
|
||||
this.log(String.format("Unable to transform (%s)", this.classCanonicalName));
|
||||
this.onTransformFailure();
|
||||
}
|
||||
return classBytes;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package thaumicenergistics.fml;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
|
||||
import thaumicenergistics.fml.classtransformers.ae.ClassTransformer_CraftingTreeProcess;
|
||||
import thaumicenergistics.fml.classtransformers.tc.ClassTransformer_Aspect;
|
||||
import thaumicenergistics.fml.classtransformers.tc.ClassTransformer_EntityGolemBase;
|
||||
import thaumicenergistics.fml.classtransformers.tc.ClassTransformer_ItemGolemBell;
|
||||
import thaumicenergistics.fml.classtransformers.tc.ClassTransformer_ItemGolemPlacer;
|
||||
import thaumicenergistics.fml.classtransformers.tc.ClassTransformer_RenderGolemBase;
|
||||
|
||||
public class ASMTransformer implements IClassTransformer {
|
||||
|
||||
/**
|
||||
* Map of all transformers<br>
|
||||
* Class name -> Transformer
|
||||
*/
|
||||
private final HashMap<String, AClassTransformer> tranformers;
|
||||
|
||||
public ASMTransformer() {
|
||||
// Create the transformers map
|
||||
this.tranformers = new HashMap<>();
|
||||
|
||||
// Add Thaumcraft transformers
|
||||
this.addTransformer(new ClassTransformer_Aspect());
|
||||
this.addTransformer(new ClassTransformer_RenderGolemBase());
|
||||
this.addTransformer(new ClassTransformer_ItemGolemPlacer());
|
||||
this.addTransformer(new ClassTransformer_ItemGolemBell());
|
||||
this.addTransformer(new ClassTransformer_EntityGolemBase());
|
||||
|
||||
// Add AE transformers
|
||||
this.addTransformer(new ClassTransformer_CraftingTreeProcess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a transformer to the map.
|
||||
*
|
||||
* @param transformer
|
||||
*/
|
||||
private void addTransformer(final AClassTransformer transformer) {
|
||||
this.tranformers.put(transformer.classCanonicalName, transformer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(final String name, final String transformedName, final byte[] basicClass) {
|
||||
AClassTransformer transformer;
|
||||
if ((transformer = this.tranformers.getOrDefault(transformedName, null)) != null) {
|
||||
return transformer.transformClass(basicClass);
|
||||
}
|
||||
|
||||
return basicClass;
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package thaumicenergistics.fml;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.DummyModContainer;
|
||||
import cpw.mods.fml.common.LoadController;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
|
||||
/**
|
||||
* Thaumic Energistics Core Mod.
|
||||
*
|
||||
* @author Nividica
|
||||
*
|
||||
*/
|
||||
@MCVersion("1.7.10")
|
||||
public class ThECore extends DummyModContainer implements IFMLLoadingPlugin {
|
||||
|
||||
/**
|
||||
* Set to true if any classes required for golem hooks can not be transformed.
|
||||
*/
|
||||
public static boolean golemHooksTransformFailed = false;
|
||||
|
||||
private final ModMetadata metadata = new ModMetadata();
|
||||
|
||||
public ThECore() {
|
||||
this.metadata.autogenerated = false;
|
||||
this.metadata.authorList.add("Nividica");
|
||||
this.metadata.credits = "Nividica";
|
||||
this.metadata.modId = this.getModId();
|
||||
this.metadata.version = this.getVersion();
|
||||
this.metadata.name = this.getName();
|
||||
this.metadata.url = "http://minecraft.curseforge.com/projects/thaumic-energistics";
|
||||
this.metadata.logoFile = "assets/thaumicenergistics/meta/logo.png";
|
||||
this.metadata.description = "Embedded Coremod for Thaumic Energistics";
|
||||
this.metadata.parent = "thaumicenergistics";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return new String[] { "thaumicenergistics.fml.ASMTransformer" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVersion() {
|
||||
return this.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return "thaumicenergistics.fml.ThECore";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModId() {
|
||||
return "ThE-core";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Thaumic Energistics Core";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "1.0.0.1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(final Map<String, Object> data) {}
|
||||
|
||||
@Override
|
||||
public boolean registerBus(final EventBus bus, final LoadController controller) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
package thaumicenergistics.fml.classtransformers.ae;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import thaumicenergistics.fml.AClassTransformer;
|
||||
|
||||
/**
|
||||
* Applied Energistics class <em>CraftingTreeProcess</em>
|
||||
* <ul>
|
||||
* <li>Adds <em>this.world = world</em> to constructor.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class ClassTransformer_CraftingTreeProcess extends AClassTransformer {
|
||||
|
||||
public ClassTransformer_CraftingTreeProcess() {
|
||||
super("appeng.crafting.CraftingTreeProcess");
|
||||
}
|
||||
|
||||
private void transformConstructor(final MethodNode method) {
|
||||
int opSequence[] = new int[] { Opcodes.ILOAD, Opcodes.PUTFIELD, Opcodes.ALOAD, Opcodes.INVOKEVIRTUAL,
|
||||
Opcodes.ASTORE };
|
||||
AbstractInsnNode insertionPoint = this.findSequence(method.instructions, opSequence, true);
|
||||
|
||||
// Insert this.world = world
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// world
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 6));
|
||||
|
||||
// this.world = world
|
||||
instructionList.add(
|
||||
new FieldInsnNode(
|
||||
Opcodes.PUTFIELD,
|
||||
"appeng/crafting/CraftingTreeProcess",
|
||||
"world",
|
||||
"Lnet/minecraft/world/World;"));
|
||||
|
||||
// Insert the new code
|
||||
method.instructions.insert(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransformFailure() {
|
||||
this.log("Recipes containing Thaumcraft's primordial pearl will not function with AE2's crafting system.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transform(final ClassNode classNode) {
|
||||
// Transform methods
|
||||
for (MethodNode method : classNode.methods) {
|
||||
// Constructor
|
||||
if (method.name.equals(AClassTransformer.InstanceConstructorName)) {
|
||||
this.transformConstructor(method);
|
||||
break; // Stop searching.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
package thaumicenergistics.fml.classtransformers.tc;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import thaumicenergistics.fml.AClassTransformer;
|
||||
|
||||
/**
|
||||
* Thaumcraft class <em>Aspect</em>
|
||||
* <ul>
|
||||
* <li>Adds hook to <em>constructor</em></li>
|
||||
* </ul>
|
||||
*/
|
||||
public class ClassTransformer_Aspect extends AClassTransformer {
|
||||
|
||||
private static final String CLASS_Aspect = "thaumcraft/api/aspects/Aspect";
|
||||
private static final String CLASS_AspectHooks = "thaumicenergistics/common/integration/tc/AspectHooks";
|
||||
|
||||
public ClassTransformer_Aspect() {
|
||||
super("thaumcraft.api.aspects.Aspect");
|
||||
}
|
||||
|
||||
private boolean transformConstructor(final MethodNode method) {
|
||||
// Is this the full constructor?
|
||||
// Check description
|
||||
if (!"(Ljava/lang/String;I[Lthaumcraft/api/aspects/Aspect;Lnet/minecraft/util/ResourceLocation;I)V"
|
||||
.equals(method.desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int opSequence[] = new int[] { Opcodes.GETSTATIC, Opcodes.ALOAD, Opcodes.ALOAD, Opcodes.INVOKEVIRTUAL,
|
||||
Opcodes.POP };
|
||||
AbstractInsnNode insertionPoint = this.findSequence(method.instructions, opSequence, false);
|
||||
|
||||
// Insert the hook
|
||||
// AspectHooks.hook_AspectInit( this )
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// AspectHooks.hook_AspectInit( Aspect )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
ClassTransformer_Aspect.CLASS_AspectHooks,
|
||||
"hook_AspectInit",
|
||||
"(L" + ClassTransformer_Aspect.CLASS_Aspect + ";)V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insert(insertionPoint, instructionList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransformFailure() {
|
||||
// No action required.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transform(final ClassNode classNode) {
|
||||
// Transform methods
|
||||
for (MethodNode method : classNode.methods) {
|
||||
// Constructor
|
||||
if (method.name.equals(AClassTransformer.InstanceConstructorName)) {
|
||||
if (this.transformConstructor(method)) {
|
||||
return; // Stop searching.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-336
@@ -1,336 +0,0 @@
|
||||
package thaumicenergistics.fml.classtransformers.tc;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import thaumicenergistics.fml.AClassTransformer;
|
||||
import thaumicenergistics.fml.ThECore;
|
||||
|
||||
/**
|
||||
* Thaumcraft class <em>EntityGolemBase</em>
|
||||
* <ul>
|
||||
* <li>Adds field <em>hookHandlers</em> of type HashMap</li>
|
||||
* <li>Adds hook to method <em>setupGolem</em></li>
|
||||
* <li>Adds hook to method <em>customInteraction</em></li>
|
||||
* <li>Adds hook to method <em>writeEntityNBT</em></li>
|
||||
* <li>Adds hook to method <em>readEntityFromNBT</em></li>
|
||||
* <li>Adds hook to method <em>func_70088_a | entityInit</em></li>
|
||||
* <li>Adds hook to method <em>func_70030_z | onEntityUpdate</em></li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Nividica
|
||||
*
|
||||
*/
|
||||
public class ClassTransformer_EntityGolemBase extends AClassTransformer {
|
||||
|
||||
public ClassTransformer_EntityGolemBase() {
|
||||
super("thaumcraft.common.entities.golems.EntityGolemBase");
|
||||
}
|
||||
|
||||
private void insertMethod_GolemBase_onEntityUpdate(final ClassNode classNode, final boolean isObf) {
|
||||
// Create the onEntityUpdate() method
|
||||
String oEU_Name = (isObf ? "func_70030_z" : "onEntityUpdate");
|
||||
MethodNode onEntityUpdate = new MethodNode(Opcodes.ACC_PUBLIC, oEU_Name, "()V", null, null);
|
||||
|
||||
// super.onEntityUpdate()
|
||||
onEntityUpdate.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
onEntityUpdate.instructions.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESPECIAL,
|
||||
"net/minecraft/entity/monster/EntityGolem",
|
||||
oEU_Name,
|
||||
"()V",
|
||||
false));
|
||||
|
||||
// GolemHooks.hook_onEntityUpdate( this, this.hookHandlers )
|
||||
// this
|
||||
onEntityUpdate.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
// this.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(onEntityUpdate.instructions, 0, false);
|
||||
// GolemHooks.hook_onEntityUpdate( EntityGolemBase, Hashmap )
|
||||
onEntityUpdate.instructions.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_onEntityUpdate",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";)V",
|
||||
false));
|
||||
|
||||
// return
|
||||
onEntityUpdate.instructions.add(new InsnNode(Opcodes.RETURN));
|
||||
|
||||
// Add the method to the class
|
||||
classNode.methods.add(onEntityUpdate);
|
||||
}
|
||||
|
||||
private void transformMethod_CustomInteraction(final MethodNode method) {
|
||||
int opSequence[] = new int[] { Opcodes.ALOAD, Opcodes.INVOKEVIRTUAL, Opcodes.ICONST_M1 };
|
||||
AbstractInsnNode insertionPoint = this.findSequence(method.instructions, opSequence, false);
|
||||
|
||||
// Go two back
|
||||
insertionPoint = insertionPoint.getPrevious().getPrevious();
|
||||
|
||||
// Find the last label
|
||||
LabelNode lastLabel = (LabelNode) this.findLastType(method.instructions, AbstractInsnNode.LABEL, 1);
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.hook_CustomInteraction( this, player, this.hookHandlers );
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// player
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 1));
|
||||
|
||||
// this.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 0, false);
|
||||
|
||||
// GolemHooks.setupGolemHook( EntityGolemBase, Hashmap )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_CustomInteraction",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";Lnet/minecraft/entity/player/EntityPlayer;L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";)Z",
|
||||
false));
|
||||
|
||||
// Insert the return check
|
||||
instructionList.add(new JumpInsnNode(Opcodes.IFNE, lastLabel));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insertBefore(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
private void transformMethod_EntityInit(final MethodNode method) {
|
||||
// Locate the return statement
|
||||
AbstractInsnNode insertionPoint = this.findLastOpCode(method.instructions, Opcodes.RETURN);
|
||||
|
||||
// Insert the hookHandlers initializer
|
||||
// hookHandlers = new HashMap<IGolemHookHandler, Object>();
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// new HashMap
|
||||
instructionList
|
||||
.add(new TypeInsnNode(Opcodes.NEW, GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers));
|
||||
instructionList.add(new InsnNode(Opcodes.DUP));
|
||||
|
||||
// Hashmap.<init>
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESPECIAL,
|
||||
GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers,
|
||||
"<init>",
|
||||
"()V",
|
||||
false));
|
||||
|
||||
// .hookHandlers =
|
||||
instructionList.add(
|
||||
new FieldInsnNode(
|
||||
Opcodes.PUTFIELD,
|
||||
GolemHookTransformHelper.CLASS_EntityGolemBase,
|
||||
GolemHookTransformHelper.FIELD_EntityGolemBase_hookHandlers,
|
||||
"L" + GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers + ";"));
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.hook_EntityInit( this, this.hookHandlers );
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// this.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 0, false);
|
||||
|
||||
// GolemHooks.hook_EntityInit( EntityGolemBase, Hashmap )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_EntityInit",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";)V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insertBefore(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
private void transformMethod_ReadEntityFromNBT(final MethodNode method) {
|
||||
// Locate the super call
|
||||
AbstractInsnNode insertionPoint = this.findFirstOpCode(method.instructions, Opcodes.INVOKESPECIAL);
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.hook_ReadEntityFromNBT( this, this.hookHandlers, nbt);
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// this.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 0, false);
|
||||
|
||||
// nbt
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 1));
|
||||
|
||||
// GolemHooks.hook_ReadEntityFromNBT( EntityGolemBase, Hashmap, NBTTagCompound )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_ReadEntityFromNBT",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";"
|
||||
+ "Lnet/minecraft/nbt/NBTTagCompound;"
|
||||
+ ")V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insert(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
private void transformMethod_SetupGolem(final MethodNode method) {
|
||||
// Set the insertion point to the instruction before return
|
||||
// Previous node is important, since the method returns a value, the previous
|
||||
// instruction is what sets that return value.
|
||||
AbstractInsnNode insertionPoint = this.findLastOpCode(method.instructions, Opcodes.IRETURN);
|
||||
insertionPoint = insertionPoint.getPrevious();
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.setupGolemHook( this, this.hookHandlers );
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// this.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 0, false);
|
||||
|
||||
// GolemHooks.setupGolemHook( EntityGolemBase, Hashmap )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_SetupGolem",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";)V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insertBefore(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
private void transformMethod_WriteEntityToNBT(final MethodNode method) {
|
||||
// Locate the return statement
|
||||
AbstractInsnNode insertionPoint = this.findLastOpCode(method.instructions, Opcodes.RETURN);
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.hook_WriteEntityToNBT( this, this.hookHandlers, nbt);
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// this
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
|
||||
// this.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 0, false);
|
||||
|
||||
// nbt
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 1));
|
||||
|
||||
// GolemHooks.hook_WriteEntityToNBT( EntityGolemBase, Hashmap, NBTTagCompound )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_WriteEntityToNBT",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";"
|
||||
+ "Lnet/minecraft/nbt/NBTTagCompound;"
|
||||
+ ")V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insertBefore(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransformFailure() {
|
||||
ThECore.golemHooksTransformFailed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transform(final ClassNode classNode) {
|
||||
// Add the handlers field
|
||||
// public HashMap<IGolemHookHandler, Object> hookHandlers;
|
||||
classNode.fields.add(
|
||||
new FieldNode(
|
||||
Opcodes.ACC_PUBLIC,
|
||||
GolemHookTransformHelper.FIELD_EntityGolemBase_hookHandlers,
|
||||
"L" + GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers + ";",
|
||||
"L" + GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ "<L"
|
||||
+ GolemHookTransformHelper.INTERFACE_IGolemHookHandler
|
||||
+ ";Ljava/lang/Object;>;",
|
||||
null));
|
||||
|
||||
boolean isObf = false;
|
||||
|
||||
// Transform methods
|
||||
for (MethodNode method : classNode.methods) {
|
||||
// Look for an obfuscated method
|
||||
if (method.name.equals("func_70014_b")) {
|
||||
isObf = true;
|
||||
}
|
||||
// Setup golem
|
||||
if (method.name.equals("setupGolem")) {
|
||||
this.transformMethod_SetupGolem(method);
|
||||
}
|
||||
// Custom interaction
|
||||
else if (method.name.equals("customInteraction")) {
|
||||
this.transformMethod_CustomInteraction(method);
|
||||
}
|
||||
// Write entity NBT
|
||||
else if (method.name.equals("func_70014_b") || method.name.equals("writeEntityToNBT")) {
|
||||
this.transformMethod_WriteEntityToNBT(method);
|
||||
}
|
||||
// Read entity from NBT
|
||||
else if (method.name.equals("func_70037_a") || method.name.equals("readEntityFromNBT")) {
|
||||
this.transformMethod_ReadEntityFromNBT(method);
|
||||
}
|
||||
// Entity Init
|
||||
else if (method.name.equals("func_70088_a") || method.name.equals("entityInit")) {
|
||||
this.transformMethod_EntityInit(method);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the onEntityUpdate method.
|
||||
this.insertMethod_GolemBase_onEntityUpdate(classNode, isObf);
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
package thaumicenergistics.fml.classtransformers.tc;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import thaumicenergistics.fml.AClassTransformer;
|
||||
import thaumicenergistics.fml.ThECore;
|
||||
|
||||
/**
|
||||
* Thaumcraft class <em>ItemGolemBell</em>
|
||||
* <ul>
|
||||
* <li>Adds hook to method <em>onLeftClickEntity</em></li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Nividica
|
||||
*
|
||||
*/
|
||||
public class ClassTransformer_ItemGolemBell extends AClassTransformer {
|
||||
|
||||
public ClassTransformer_ItemGolemBell() {
|
||||
super("thaumcraft.common.entities.golems.ItemGolemBell");
|
||||
}
|
||||
|
||||
private void transformMethod_OnLeftClickEntity(final MethodNode method) {
|
||||
int opSequence[] = new int[] { Opcodes.GETSTATIC, Opcodes.ICONST_1, Opcodes.ILOAD, Opcodes.INVOKESPECIAL,
|
||||
Opcodes.ASTORE };
|
||||
|
||||
// Locate the sequence
|
||||
AbstractInsnNode insertionPoint = this.findSequence(method.instructions, opSequence, true);
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.hook_Bell_OnLeftClickGolem( entity, dropped, player, ((EntityGolemBase)entity).hookHandlers )
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// ((EntityGolemBase)entity)
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 3));
|
||||
instructionList.add(new TypeInsnNode(Opcodes.CHECKCAST, GolemHookTransformHelper.CLASS_EntityGolemBase));
|
||||
|
||||
// dropped
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 9));
|
||||
|
||||
// player
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 2));
|
||||
|
||||
// ((EntityGolemBase)entity).hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 3, true);
|
||||
|
||||
// GolemHooks.hook_Bell_OnLeftClickGolem( EntityGolemBase, ItemStack, EntityPlayer, Hashmap )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_Bell_OnLeftClickGolem",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/player/EntityPlayer;L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";)V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insert(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransformFailure() {
|
||||
ThECore.golemHooksTransformFailed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transform(final ClassNode classNode) {
|
||||
// Transform methods
|
||||
for (MethodNode method : classNode.methods) {
|
||||
// Left click entity
|
||||
if (method.name.equals("onLeftClickEntity")) {
|
||||
this.transformMethod_OnLeftClickEntity(method);
|
||||
return; // Stop searching.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
package thaumicenergistics.fml.classtransformers.tc;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import thaumicenergistics.fml.AClassTransformer;
|
||||
import thaumicenergistics.fml.ThECore;
|
||||
|
||||
/**
|
||||
* Thaumcraft class <em>ItemGolemPlacer</em>
|
||||
* <ul>
|
||||
* <li>Adds hook to method <em>spawnCreature</em></li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Nividica
|
||||
*
|
||||
*/
|
||||
public class ClassTransformer_ItemGolemPlacer extends AClassTransformer {
|
||||
|
||||
public ClassTransformer_ItemGolemPlacer() {
|
||||
super("thaumcraft.common.entities.golems.ItemGolemPlacer");
|
||||
}
|
||||
|
||||
private void transformMethod_SpawnCreature(final MethodNode method) {
|
||||
// Locate "golem.setup(side);"
|
||||
int opSequence[] = new int[] { Opcodes.PUTFIELD, Opcodes.ALOAD, Opcodes.ILOAD, Opcodes.INVOKEVIRTUAL };
|
||||
AbstractInsnNode insertionPoint = this.findSequence(method.instructions, opSequence, true);
|
||||
|
||||
// Move back to the aload
|
||||
insertionPoint = insertionPoint.getPrevious().getPrevious();
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.hook_Placer_SpawnGolem( golem, stack, golem.hookHandlers )
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// golem
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 12));
|
||||
|
||||
// stack
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 9));
|
||||
|
||||
// golem.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 12, false);
|
||||
|
||||
// GolemHooks.hook_Placer_SpawnGolem( EntityGolemBase, ItemStack, Hashmap )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_Placer_SpawnGolem",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";Lnet/minecraft/item/ItemStack;L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";)V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insertBefore(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransformFailure() {
|
||||
ThECore.golemHooksTransformFailed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transform(final ClassNode classNode) {
|
||||
// Transform methods
|
||||
for (MethodNode method : classNode.methods) {
|
||||
// Spawn creature
|
||||
if (method.name.equals("spawnCreature")) {
|
||||
this.transformMethod_SpawnCreature(method);
|
||||
break; // Stop searching.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
package thaumicenergistics.fml.classtransformers.tc;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import thaumicenergistics.fml.AClassTransformer;
|
||||
import thaumicenergistics.fml.ThECore;
|
||||
|
||||
/**
|
||||
* Thaumcraft class <em>RenderGolemBase</em>
|
||||
* <ul>
|
||||
* <li>Adds hook to method <em>render</em></li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Nividica
|
||||
*
|
||||
*/
|
||||
public class ClassTransformer_RenderGolemBase extends AClassTransformer {
|
||||
|
||||
public ClassTransformer_RenderGolemBase() {
|
||||
super("thaumcraft.client.renderers.entity.RenderGolemBase");
|
||||
}
|
||||
|
||||
private void transformMethod_Render(final MethodNode method) {
|
||||
// Find the return
|
||||
AbstractInsnNode insertionPoint = this.findLastOpCode(method.instructions, Opcodes.RETURN);
|
||||
|
||||
// Insert the hook
|
||||
// GolemHooks.hook_RenderGolem( e, e.hookHandlers, par2, par4, par6, par9 )
|
||||
InsnList instructionList = new InsnList();
|
||||
|
||||
// e
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, 1));
|
||||
|
||||
// e.hookHandlers
|
||||
GolemHookTransformHelper.addGetField_hookHandlers(instructionList, 1, false);
|
||||
|
||||
// par2
|
||||
instructionList.add(new VarInsnNode(Opcodes.DLOAD, 2));
|
||||
|
||||
// par4
|
||||
instructionList.add(new VarInsnNode(Opcodes.DLOAD, 4));
|
||||
|
||||
// par6
|
||||
instructionList.add(new VarInsnNode(Opcodes.DLOAD, 6));
|
||||
|
||||
// par9
|
||||
instructionList.add(new VarInsnNode(Opcodes.FLOAD, 9));
|
||||
|
||||
// GolemHooks.hook_RenderGolem( EntityGolemBase, Hashmap, double, double, double, float )
|
||||
instructionList.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
GolemHookTransformHelper.CLASS_GolemHooks,
|
||||
"hook_RenderGolem",
|
||||
"(L" + GolemHookTransformHelper.CLASS_EntityGolemBase
|
||||
+ ";L"
|
||||
+ GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers
|
||||
+ ";DDDF)V",
|
||||
false));
|
||||
|
||||
// Insert the static call
|
||||
method.instructions.insertBefore(insertionPoint, instructionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransformFailure() {
|
||||
ThECore.golemHooksTransformFailed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transform(final ClassNode classNode) {
|
||||
// Transform methods
|
||||
for (MethodNode method : classNode.methods) {
|
||||
if (method.name.equals("render")) {
|
||||
// Render
|
||||
this.transformMethod_Render(method);
|
||||
break; // Stop searching.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package thaumicenergistics.fml.classtransformers.tc;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
class GolemHookTransformHelper {
|
||||
|
||||
public static final String CLASS_EntityGolemBase = "thaumcraft/common/entities/golems/EntityGolemBase";
|
||||
public static final String CLASS_GolemHooks = "thaumicenergistics/common/integration/tc/GolemHooks";
|
||||
public static final String INTERFACE_IGolemHookHandler = "thaumicenergistics/api/entities/IGolemHookHandler";
|
||||
public static final String FIELD_EntityGolemBase_hookHandlers = "hookHandlers";
|
||||
public static final String FIELDTYPE_EntityGolemBase_hookHandlers = "java/util/HashMap";
|
||||
|
||||
/**
|
||||
* Adds a reference to a golems hookHandlers field to the stack.
|
||||
*
|
||||
* @param instructionList
|
||||
* @param golemVar
|
||||
* @param checkCast If the var specified is not type EntityGolemBase(such as just Entity or EntityLiving) a
|
||||
* cast check must be performed.
|
||||
*/
|
||||
public static void addGetField_hookHandlers(final InsnList instructionList, final int golemVar,
|
||||
final boolean checkCast) {
|
||||
instructionList.add(new VarInsnNode(Opcodes.ALOAD, golemVar));
|
||||
if (checkCast) {
|
||||
instructionList.add(new TypeInsnNode(Opcodes.CHECKCAST, GolemHookTransformHelper.CLASS_EntityGolemBase));
|
||||
}
|
||||
instructionList.add(
|
||||
new FieldInsnNode(
|
||||
Opcodes.GETFIELD,
|
||||
GolemHookTransformHelper.CLASS_EntityGolemBase,
|
||||
GolemHookTransformHelper.FIELD_EntityGolemBase_hookHandlers,
|
||||
"L" + GolemHookTransformHelper.FIELDTYPE_EntityGolemBase_hookHandlers + ";"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package thaumicenergistics.mixins;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.gtnewhorizon.gtnhmixins.ILateMixinLoader;
|
||||
import com.gtnewhorizon.gtnhmixins.LateMixin;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
|
||||
@LateMixin
|
||||
public class ThaumicEnergisticsLateMixinLoader implements ILateMixinLoader {
|
||||
|
||||
@Override
|
||||
public String getMixinConfig() {
|
||||
return "mixins.thaumicenergistics.late.json";
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getMixins(Set<String> loadedMods) {
|
||||
List<String> mixins = new ArrayList<>();
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
mixins.add("thaumcraft.MixinRenderGolemBase");
|
||||
}
|
||||
mixins.add("thaumcraft.MixinAspect");
|
||||
mixins.add("thaumcraft.MixinEntityGolemBase");
|
||||
mixins.add("thaumcraft.MixinItemGolemBell");
|
||||
mixins.add("thaumcraft.MixinItemGolemPlacer");
|
||||
return mixins;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package thaumicenergistics.mixins.interfaces;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import thaumicenergistics.api.entities.IGolemHookHandler;
|
||||
|
||||
public interface EntityGolemBaseExt {
|
||||
|
||||
HashMap<IGolemHookHandler, Object> thenergistic$getHandlers();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package thaumicenergistics.mixins.late.thaumcraft;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import thaumcraft.api.aspects.Aspect;
|
||||
import thaumicenergistics.common.integration.tc.AspectHooks;
|
||||
|
||||
@Mixin(Aspect.class)
|
||||
public class MixinAspect {
|
||||
|
||||
@Inject(
|
||||
method = "<init>(Ljava/lang/String;I[Lthaumcraft/api/aspects/Aspect;Lnet/minecraft/util/ResourceLocation;I)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Ljava/util/LinkedHashMap;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
|
||||
remap = false,
|
||||
shift = At.Shift.AFTER))
|
||||
private void injectInit(CallbackInfo ci) {
|
||||
AspectHooks.hook_AspectInit((Aspect) (Object) this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package thaumicenergistics.mixins.late.thaumcraft;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.minecraft.entity.monster.EntityGolem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||
|
||||
import thaumcraft.common.entities.golems.EntityGolemBase;
|
||||
import thaumicenergistics.api.entities.IGolemHookHandler;
|
||||
import thaumicenergistics.common.integration.tc.GolemHooks;
|
||||
import thaumicenergistics.mixins.interfaces.EntityGolemBaseExt;
|
||||
|
||||
@Mixin(EntityGolemBase.class)
|
||||
public class MixinEntityGolemBase extends EntityGolem implements EntityGolemBaseExt {
|
||||
|
||||
@Unique
|
||||
private HashMap<IGolemHookHandler, Object> thenergistic$hookHandlers;
|
||||
|
||||
public MixinEntityGolemBase(World world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Inject(method = "setupGolem", at = @At("TAIL"), remap = false)
|
||||
private void injectSetupGolem(CallbackInfoReturnable<Boolean> cir) {
|
||||
GolemHooks.hook_SetupGolem((EntityGolemBase) (Object) this, thenergistic$hookHandlers);
|
||||
}
|
||||
|
||||
@Inject(method = "entityInit", at = @At("TAIL"))
|
||||
private void injectEntityInit(CallbackInfo ci) {
|
||||
thenergistic$hookHandlers = new HashMap<>();
|
||||
GolemHooks.hook_EntityInit((EntityGolemBase) (Object) this, thenergistic$hookHandlers);
|
||||
}
|
||||
|
||||
@Inject(method = "writeEntityToNBT", at = @At("TAIL"))
|
||||
private void injectWriteNBT(NBTTagCompound nbt, CallbackInfo ci) {
|
||||
GolemHooks.hook_WriteEntityToNBT((EntityGolemBase) (Object) this, thenergistic$hookHandlers, nbt);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "readEntityFromNBT",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/entity/monster/EntityGolem;readEntityFromNBT(Lnet/minecraft/nbt/NBTTagCompound;)V",
|
||||
shift = At.Shift.AFTER))
|
||||
private void injectReadNBT(NBTTagCompound nbt, CallbackInfo ci) {
|
||||
GolemHooks.hook_ReadEntityFromNBT((EntityGolemBase) (Object) this, thenergistic$hookHandlers, nbt);
|
||||
}
|
||||
|
||||
@WrapWithCondition(
|
||||
method = "customInteraction",
|
||||
remap = false,
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/entity/player/EntityPlayer;openGui(Ljava/lang/Object;ILnet/minecraft/world/World;III)V"))
|
||||
private boolean wrapCustomInteraction(EntityPlayer player, Object mod, int modGuiId, World world, int x, int y,
|
||||
int z) {
|
||||
return !GolemHooks.hook_CustomInteraction((EntityGolemBase) (Object) this, player, thenergistic$hookHandlers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityUpdate() {
|
||||
super.onEntityUpdate();
|
||||
GolemHooks.hook_onEntityUpdate((EntityGolemBase) (Object) this, thenergistic$hookHandlers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<IGolemHookHandler, Object> thenergistic$getHandlers() {
|
||||
return thenergistic$hookHandlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package thaumicenergistics.mixins.late.thaumcraft;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
|
||||
import thaumcraft.common.entities.golems.EntityGolemBase;
|
||||
import thaumcraft.common.entities.golems.ItemGolemBell;
|
||||
import thaumicenergistics.common.integration.tc.GolemHooks;
|
||||
import thaumicenergistics.mixins.interfaces.EntityGolemBaseExt;
|
||||
|
||||
@Mixin(ItemGolemBell.class)
|
||||
public class MixinItemGolemBell {
|
||||
|
||||
@ModifyVariable(
|
||||
method = "onLeftClickEntity",
|
||||
remap = false,
|
||||
at = @At(value = "STORE", ordinal = 1),
|
||||
name = "dropped")
|
||||
private ItemStack injectOnLeftClickEntity(ItemStack dropped, ItemStack stack, EntityPlayer player, Entity entity) {
|
||||
GolemHooks.hook_Bell_OnLeftClickGolem(
|
||||
(EntityGolemBase) entity,
|
||||
dropped,
|
||||
player,
|
||||
((EntityGolemBaseExt) entity).thenergistic$getHandlers());
|
||||
return dropped;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package thaumicenergistics.mixins.late.thaumcraft;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
|
||||
import thaumcraft.common.entities.golems.EntityGolemBase;
|
||||
import thaumcraft.common.entities.golems.ItemGolemPlacer;
|
||||
import thaumicenergistics.common.integration.tc.GolemHooks;
|
||||
import thaumicenergistics.mixins.interfaces.EntityGolemBaseExt;
|
||||
|
||||
@Mixin(ItemGolemPlacer.class)
|
||||
public class MixinItemGolemPlacer {
|
||||
|
||||
@Inject(
|
||||
method = "spawnCreature",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lthaumcraft/common/entities/golems/EntityGolemBase;setup(I)V",
|
||||
shift = At.Shift.BEFORE),
|
||||
remap = false)
|
||||
private void inject(World par0World, double par2, double par4, double par6, int side, ItemStack stack,
|
||||
EntityPlayer player, CallbackInfoReturnable<Boolean> cir, @Local(name = "golem") EntityGolemBase golem) {
|
||||
GolemHooks.hook_Placer_SpawnGolem(golem, stack, ((EntityGolemBaseExt) golem).thenergistic$getHandlers());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package thaumicenergistics.mixins.late.thaumcraft;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import thaumcraft.client.renderers.entity.RenderGolemBase;
|
||||
import thaumcraft.common.entities.golems.EntityGolemBase;
|
||||
import thaumicenergistics.common.integration.tc.GolemHooks;
|
||||
import thaumicenergistics.mixins.interfaces.EntityGolemBaseExt;
|
||||
|
||||
@Mixin(RenderGolemBase.class)
|
||||
public class MixinRenderGolemBase {
|
||||
|
||||
@Inject(method = "render", at = @At("RETURN"), remap = false)
|
||||
private void onRender(EntityGolemBase e, double x, double y, double z, float par8, float partialTicks,
|
||||
CallbackInfo ci) {
|
||||
GolemHooks.hook_RenderGolem(e, ((EntityGolemBaseExt) e).thenergistic$getHandlers(), x, y, z, partialTicks);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8.5-GTNH",
|
||||
"refmap": "mixins.thaumicenergistics.refmap.json",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8.5-GTNH",
|
||||
"package": "thaumicenergistics.mixins.late",
|
||||
"refmap": "mixins.thaumicenergistics.refmap.json",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8"
|
||||
}
|
||||
Reference in new issue
Block a user