Skip to content

Commit

Permalink
Fix infusion pillar dupe bug (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCodex6824 committed Jun 24, 2024
1 parent 25efe6f commit f5c7acd
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 32 deletions.
6 changes: 6 additions & 0 deletions src/main/java/thecodex6824/coremodlib/MethodDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@

import java.util.StringJoiner;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;

public class MethodDefinition {

Expand Down Expand Up @@ -71,6 +73,10 @@ public MethodInsnNode asMethodInsnNode(int opcode) {
return new MethodInsnNode(opcode, className, methodName, desc, itf);
}

public MethodNode createNewMethodNode(int access) {
return new MethodNode(Opcodes.ASM5, access, methodName, desc, null, null);
}

@Override
public String toString() {
StringJoiner argJoiner = new StringJoiner(", ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ private void initTransformers() {
transformers.add(BlockTransformers.FOCAL_MANIPULATOR_COMPONENTS);
transformers.add(BlockTransformers.FOCAL_MANIPULATOR_COMPONENTS_CLIENT);
transformers.add(BlockTransformers.FOCAL_MANIPULATOR_XP_COST_GUI);
transformers.add(BlockTransformers.PILLAR_DROP_FIX.get());
transformers.add(BlockTransformers.TABLE_TOP_SOLID.get());
transformers.add(BlockTransformers.THAUMATORIUM_TOP_EMPTY.get());
transformers.add(CastingTransformers.EXCHANGE_MOD_INTERFACEIFY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import thecodex6824.coremodlib.MethodDefinition;
import thecodex6824.coremodlib.PatchStateMachine;
import thecodex6824.thaumcraftfix.ThaumcraftFix;
import thecodex6824.thaumcraftfix.core.transformer.custom.BlockPillarDropFixTransformer;
import thecodex6824.thaumcraftfix.core.transformer.custom.ThrowingTransformerWrapper;

public class BlockTransformers {

Expand Down Expand Up @@ -337,6 +339,9 @@ public static boolean modifyFocalManipulatorCraftValid(boolean origResult, int t
.build()
);

public static final Supplier<ITransformer> PILLAR_DROP_FIX = () -> new ThrowingTransformerWrapper(
new BlockPillarDropFixTransformer());

public static final Supplier<ITransformer> TABLE_TOP_SOLID = () -> {
return new GenericStateMachineTransformer(
PatchStateMachine.builder(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import thecodex6824.coremodlib.PatchStateMachine;
import thecodex6824.thaumcraftfix.api.casting.IContainsFocusPackageNode;
import thecodex6824.thaumcraftfix.core.transformer.custom.ExchangeModInterfaceTransformer;
import thecodex6824.thaumcraftfix.core.transformer.custom.ThrowingTransformerWrapper;

public class CastingTransformers {

Expand Down Expand Up @@ -87,7 +88,8 @@ public static void setFocusPackageCasterUUID(FocusPackage focusPackage, UUID cas

private static final String HOOKS = Type.getInternalName(Hooks.class);

public static final ITransformer EXCHANGE_MOD_INTERFACEIFY = new ExchangeModInterfaceTransformer();
public static final ITransformer EXCHANGE_MOD_INTERFACEIFY = new ThrowingTransformerWrapper(
new ExchangeModInterfaceTransformer());

public static final ITransformer FOCUS_PACKAGE_INIT = new GenericStateMachineTransformer(
PatchStateMachine.builder(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ public static float getRobeRotationDivisor(Entity entity) {
private static final String HOOKS_CLIENT = Type.getInternalName(HooksClient.class);

// pretty much rewrites a model rotation method to not be incompatible with everything
// this does not use ThrowingTransformerWrapper because it was intentionally designed to be exceptionally brittle
// if it can't apply, it should not crash the game, and it will dump debug info itself
public static final ITransformer CUSTOM_ARMOR_NOT_CALLING_SUPER = new TransformerBipedRotationCustomArmor();

// compensates for the above transformer by adding a hook to set custom rotation points
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
package thecodex6824.thaumcraftfix.core.transformer;

import thecodex6824.thaumcraftfix.core.transformer.custom.AuraChunkThreadSafetyTransformer;
import thecodex6824.thaumcraftfix.core.transformer.custom.ThrowingTransformerWrapper;

public class MiscTransformers {

public static final ITransformer AURA_CHUNK_THREAD_SAFETY = new AuraChunkThreadSafetyTransformer();
public static final ITransformer AURA_CHUNK_THREAD_SAFETY = new ThrowingTransformerWrapper(
new AuraChunkThreadSafetyTransformer());

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import thecodex6824.coremodlib.PatchStateMachine;
import thecodex6824.thaumcraftfix.ThaumcraftFix;
import thecodex6824.thaumcraftfix.core.transformer.custom.PacketNoteHandlerRewriteTransformer;
import thecodex6824.thaumcraftfix.core.transformer.custom.ThrowingTransformerWrapper;

public class NetworkTransformers {

Expand Down Expand Up @@ -324,7 +325,8 @@ public static int checkProgressSyncStage(int originalStage, EntityPlayer player,
);
};

public static final Supplier<ITransformer> NOTE_HANDLER = () -> new PacketNoteHandlerRewriteTransformer();
public static final Supplier<ITransformer> NOTE_HANDLER = () -> new ThrowingTransformerWrapper(
new PacketNoteHandlerRewriteTransformer());

public static final Supplier<ITransformer> RESEARCH_TABLE_AIDS = () -> {
return new GenericStateMachineTransformer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ private Types() {}
public static final Type I_BLOCK_STATE = Type.getType("Lnet/minecraft/block/state/IBlockState;");
public static final Type TILE_ENTITY = Type.getType("Lnet/minecraft/tileentity/TileEntity;");

public static final Type ITEM = Type.getType("Lnet/minecraft/item/Item;");
public static final Type ITEM_STACK = Type.getType("Lnet/minecraft/item/ItemStack;");
public static final Type NBT_TAG_COMPOUND = Type.getType("Lnet/minecraft/nbt/NBTTagCompound;");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* Thaumcraft Fix
* Copyright (c) 2024 TheCodex6824.
*
* This file is part of Thaumcraft Fix.
*
* Thaumcraft Fix is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Thaumcraft Fix is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Thaumcraft Fix. If not, see <https://www.gnu.org/licenses/>.
*/

package thecodex6824.thaumcraftfix.core.transformer.custom;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;

import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import thaumcraft.api.blocks.BlocksTC;
import thecodex6824.coremodlib.MethodDefinition;
import thecodex6824.thaumcraftfix.core.transformer.ITransformer;
import thecodex6824.thaumcraftfix.core.transformer.TransformUtil;
import thecodex6824.thaumcraftfix.core.transformer.Types;

public class BlockPillarDropFixTransformer implements ITransformer {

private static final String PILLAR = "thaumcraft/common/blocks/basic/BlockPillar";

public static final class Hooks {

public static Item itemDropped(IBlockState state) {
Item ret = null;
if (state.getBlock() == BlocksTC.pillarAncient) {
ret = Item.getItemFromBlock(BlocksTC.stoneAncient);
}
else if (state.getBlock() == BlocksTC.pillarEldritch) {
ret = Item.getItemFromBlock(BlocksTC.stoneEldritchTile);
}
else {
ret = Item.getItemFromBlock(BlocksTC.stoneArcane);
}

return ret;
}

}

@Override
public boolean isTransformationNeeded(String transformedName) {
return "thaumcraft.common.blocks.basic.BlockPillar".equals(transformedName);
}

@Override
public boolean transform(ClassNode classNode, String name, String transformedName) {
MethodNode itemDropped = TransformUtil.findMethod(classNode, TransformUtil.remapMethod(new MethodDefinition(
PILLAR,
false,
"func_180660_a",
Types.ITEM,
Types.I_BLOCK_STATE, Types.RANDOM, Type.INT_TYPE
)));
itemDropped.instructions.clear();
itemDropped.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
itemDropped.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(Hooks.class),
"itemDropped",
Type.getMethodDescriptor(Types.ITEM, Types.I_BLOCK_STATE),
false
));
itemDropped.instructions.add(new InsnNode(Opcodes.ARETURN));

MethodNode quantityDropped = TransformUtil.remapMethod(new MethodDefinition(
PILLAR,
false,
"func_149745_a",
Type.INT_TYPE,
Types.RANDOM
)).createNewMethodNode(Opcodes.ACC_PUBLIC);
quantityDropped.instructions.add(new InsnNode(Opcodes.ICONST_2));
quantityDropped.instructions.add(new InsnNode(Opcodes.IRETURN));

MethodDefinition breakBlock = TransformUtil.remapMethod(new MethodDefinition(
PILLAR,
false,
"func_180663_b",
Type.VOID_TYPE,
Types.WORLD, Types.BLOCK_POS, Types.I_BLOCK_STATE
));
classNode.methods.removeIf(m -> m.name.equals(breakBlock.name()) &&
m.desc.equals(breakBlock.desc()));
classNode.methods.add(quantityDropped);

return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;

import thecodex6824.coremodlib.ASMUtil;
import thecodex6824.coremodlib.MethodDefinition;
import thecodex6824.thaumcraftfix.core.ThaumcraftFixCore;
import thecodex6824.thaumcraftfix.core.transformer.ITransformer;
import thecodex6824.thaumcraftfix.core.transformer.NetworkTransformers;
import thecodex6824.thaumcraftfix.core.transformer.TransformUtil;
Expand All @@ -53,35 +51,26 @@ public boolean transform(ClassNode classNode, String name, String transformedNam
Type.getType("Lnet/minecraftforge/fml/common/network/simpleimpl/IMessage;"),
Type.getType("Lthaumcraft/common/lib/network/misc/PacketNote;"), Type.getType("Lnet/minecraftforge/fml/common/network/simpleimpl/MessageContext;")
));
boolean success = false;
if (method != null) {
MethodNode wrapper = new MethodNode(method.access, method.name, method.desc, method.signature,
method.exceptions.toArray(new String[0]));
// change name of old method
method.name = ORIGINAL_METHOD_REDIRECT_NAME;

wrapper.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
wrapper.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
wrapper.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(NetworkTransformers.Hooks.class),
"handlePacketNote",
Type.getMethodDescriptor(Type.VOID_TYPE,
Type.getType("Lthaumcraft/common/lib/network/misc/PacketNote;"),
Type.getType("Lnet/minecraftforge/fml/common/network/simpleimpl/MessageContext;")),
false
));
wrapper.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
wrapper.instructions.add(new InsnNode(Opcodes.ARETURN));
MethodNode wrapper = new MethodNode(method.access, method.name, method.desc, method.signature,
method.exceptions.toArray(new String[0]));
// change name of old method
method.name = ORIGINAL_METHOD_REDIRECT_NAME;

classNode.methods.add(wrapper);
success = true;
}
wrapper.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
wrapper.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
wrapper.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(NetworkTransformers.Hooks.class),
"handlePacketNote",
Type.getMethodDescriptor(Type.VOID_TYPE,
Type.getType("Lthaumcraft/common/lib/network/misc/PacketNote;"),
Type.getType("Lnet/minecraftforge/fml/common/network/simpleimpl/MessageContext;")),
false
));
wrapper.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
wrapper.instructions.add(new InsnNode(Opcodes.ARETURN));

if (!success) {
ThaumcraftFixCore.getLogger().error("Class dump for debugging:");
ThaumcraftFixCore.getLogger().error(ASMUtil.dumpClass(classNode));
throw new RuntimeException("Could not patch PacketNote");
}
classNode.methods.add(wrapper);

return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package thecodex6824.thaumcraftfix.core.transformer.custom;

import org.objectweb.asm.tree.ClassNode;

import thecodex6824.coremodlib.ASMUtil;
import thecodex6824.thaumcraftfix.core.ThaumcraftFixCore;
import thecodex6824.thaumcraftfix.core.transformer.ITransformer;

public class ThrowingTransformerWrapper implements ITransformer {

private ITransformer wrapped;

public ThrowingTransformerWrapper(ITransformer toWrap) {
wrapped = toWrap;
}

@Override
public boolean isTransformationNeeded(String transformedName) {
return wrapped.isTransformationNeeded(transformedName);
}

@Override
public boolean transform(ClassNode classNode, String name, String transformedName) {
String origClassDump = ASMUtil.dumpClass(classNode);
Throwable toRethrow = null;
try {
if (!wrapped.transform(classNode, name, transformedName)) {
toRethrow = new RuntimeException("Patch returned false");
}
}
catch (Throwable anything) {
toRethrow = anything;
}

if (toRethrow != null) {
ThaumcraftFixCore.getLogger().error("Class dump before changes:");
ThaumcraftFixCore.getLogger().error(origClassDump);
ThaumcraftFixCore.getLogger().error("Class dump after changes:");
ThaumcraftFixCore.getLogger().error(ASMUtil.dumpClass(classNode));
throw new RuntimeException(toRethrow);
}

return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,21 @@ public boolean transform(ClassNode classNode, String name, String transformedNam
InsnList backupInstructions = ASMUtil.cloneInsnList(rot.instructions);
List<LocalVariableNode> backupLocals = ImmutableList.copyOf(rot.localVariables);

success = doTransform(rot);
Throwable caughtException = null;
try {
success = doTransform(rot);
}
catch (Throwable anything) {
caughtException = anything;
}

if (!success) {
rot.instructions = backupInstructions;
rot.localVariables.clear();
rot.localVariables.addAll(backupLocals);
if (caughtException != null) {
ThaumcraftFixCore.getLogger().error(caughtException);
}
}
}

Expand Down

0 comments on commit f5c7acd

Please sign in to comment.