Added transformer to fix coolant cells

Closes #83. Added class transformer which adds check for GT's brand new
HeatComponent interface
This commit is contained in:
TheDarkDnKTv 2021-03-20 09:03:48 +02:00
parent 12fa856051
commit 9e9f9b283e
5 changed files with 131 additions and 17 deletions

View file

@ -0,0 +1,17 @@
package gregtechmod.api.interfaces;
import net.minecraft.item.ItemStack;
/**
* Implementing this interface will mark item as IC2 reactor component which <u>stores</u> heat
* Used to fix IC2 through ASM to not allow put back warm cells
* @author TheDarkDnKTv
*
*/
public interface IHeatComponent {
/**
* @return amount of heat stored in stack
*/
int getHeatStored(ItemStack stack);
}

View file

@ -41,21 +41,19 @@ public class GT_CoolantCellIC_Item extends GT_CoolantCell_Item implements IReact
public int alterHeat(IReactor aReactor, ItemStack aStack, int x, int y, int aHeat) {
int tHeat = getHeatOfStack(aStack);
if (!aReactor.isFluidCooled() || aHeat > 0) {
tHeat += aHeat;
if (tHeat > heatStorage) {
aReactor.setItemAt(x, y, (ItemStack)null);
aHeat = heatStorage - tHeat + 1;
} else {
if (tHeat < 0) {
aHeat = tHeat;
tHeat = 0;
} else {
aHeat = 0;
}
setHeatForStack(aStack, tHeat);
}
tHeat += aHeat;
if (tHeat > heatStorage) {
aReactor.setItemAt(x, y, (ItemStack)null);
aHeat = heatStorage - tHeat + 1;
} else {
if (tHeat < 0) {
aHeat = tHeat;
tHeat = 0;
} else {
aHeat = 0;
}
setHeatForStack(aStack, tHeat);
}
return aHeat;

View file

@ -1,6 +1,8 @@
package gregtechmod.api.items;
import gregtechmod.api.GregTech_API;
import gregtechmod.api.interfaces.IHeatComponent;
import gregtechmod.api.util.GT_Utility;
import java.util.List;
@ -8,7 +10,7 @@ import net.minecraft.client.resources.I18n;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
public class GT_CoolantCell_Item extends GT_Generic_Item {
public class GT_CoolantCell_Item extends GT_Generic_Item implements IHeatComponent {
protected int heatStorage;
public GT_CoolantCell_Item(String aUnlocalized, int aMaxStore) {
@ -60,4 +62,13 @@ public class GT_CoolantCell_Item extends GT_Generic_Item {
}
return tNBT.getInteger("heat");
}
@Override
public int getHeatStored(ItemStack stack) {
if (GT_Utility.isStackValid(stack)) {
return getHeatOfStack(stack);
}
return 0;
}
}

View file

@ -22,7 +22,8 @@ public class GT_CoreMod implements IFMLLoadingPlugin {
@Override
public String[] getASMTransformerClass() {
return new String[] {
"gregtechmod.common.asm.EnergyNetTransformer"
"gregtechmod.common.asm.EnergyNetTransformer",
"gregtechmod.common.asm.IC2ReactorSlotTransformer"
};
}

View file

@ -0,0 +1,87 @@
package gregtechmod.common.asm;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
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.LineNumberNode;
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 cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import net.minecraft.launchwrapper.IClassTransformer;
import static org.objectweb.asm.Opcodes.*;
/**
* @author TheDarkDnKTv
*
*/
public class IC2ReactorSlotTransformer implements IClassTransformer {
private final static String TE_REACTOR = GT_CoreMod.getIC2CoreClass("block.reactor.tileentity.TileEntityNuclearReactorElectric");
private final static String STACK_TYPE = FMLDeobfuscatingRemapper.INSTANCE.map("net/minecraft/item/ItemStack");
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if (TE_REACTOR.equals(name)) {
ClassReader reader = new ClassReader(basicClass);
ClassNode clz = new ClassNode();
reader.accept(clz, 0);
for (MethodNode method : clz.methods) {
if (method.name.equals("isUsefulItem") && method.access == ACC_PUBLIC && method.desc.equals(String.format("(L%s;Z)Z", STACK_TYPE))) { // (Ladd;Z)Z
GT_CoreMod.log.info("Transforming " + TE_REACTOR);
try {
for (int i = 0; i < method.instructions.size(); i++) {
AbstractInsnNode ins = method.instructions.get(i);
if (ins.getOpcode() == ALOAD && ins.getNext().getOpcode() == INVOKEVIRTUAL && ((MethodInsnNode)ins.getNext()).name.equals("getClass")) {
ins = ins.getNext().getNext().getNext(); // IF_ACMPNE L5
LabelNode next = ((JumpInsnNode) ins).label;
LabelNode lb = new LabelNode(new Label());
((JumpInsnNode) ins).label = lb;
InsnList list = new InsnList();
{
final String GT = "gregtechmod/api/interfaces/IHeatComponent";
list.add(lb);
list.add(new LineNumberNode(301, lb));
list.add(new VarInsnNode(ALOAD, 3));
list.add(new TypeInsnNode(INSTANCEOF, GT));
list.add(new JumpInsnNode(IFEQ, next));
list.add(new VarInsnNode(ALOAD, 3));
list.add(new TypeInsnNode(CHECKCAST, GT));
list.add(new VarInsnNode(ALOAD, 1));
list.add(new MethodInsnNode(INVOKEINTERFACE, GT, "getHeatStored", String.format("(L%s;)I", STACK_TYPE), true));
list.add(new JumpInsnNode(IFLE, next));
list.add(new InsnNode(ICONST_0));
list.add(new InsnNode(IRETURN));
}
method.instructions.insertBefore(next, list);
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
clz.accept(writer);
return writer.toByteArray();
}
}
throw new NoSuchMethodException("Not found entry signature in isUsefulItem");
} catch (Throwable e) {
GT_CoreMod.log.error("Error on transformation");
GT_CoreMod.log.catching(e);
}
}
}
}
return basicClass;
}
}