From 862d59d084642b89d6c94666d4d2e8df7d659708 Mon Sep 17 00:00:00 2001 From: Cadiboo <37298044+Cadiboo@users.noreply.github.com> Date: Sat, 16 Sep 2023 19:22:40 +1000 Subject: [PATCH] Fix in-game changes not saving to config --- .../github/cadiboo/nocubes/hooks/Hooks.java | 18 ++- .../FMLNetworkHandlerTransformer.java | 104 ++++++++++++++++++ .../tempcore/NoCubesClassTransformer.java | 4 + 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/github/cadiboo/nocubes/tempcore/FMLNetworkHandlerTransformer.java diff --git a/src/main/java/io/github/cadiboo/nocubes/hooks/Hooks.java b/src/main/java/io/github/cadiboo/nocubes/hooks/Hooks.java index 54a5caa7..7905fbc3 100644 --- a/src/main/java/io/github/cadiboo/nocubes/hooks/Hooks.java +++ b/src/main/java/io/github/cadiboo/nocubes/hooks/Hooks.java @@ -4,6 +4,7 @@ import io.github.cadiboo.nocubes.client.render.RenderDispatcher; import io.github.cadiboo.nocubes.collision.CollisionHandler; import io.github.cadiboo.nocubes.config.NoCubesConfig; +import io.github.cadiboo.nocubes.network.NoCubesNetwork; import net.minecraft.block.state.IBlockState; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.renderer.BlockRendererDispatcher; @@ -20,6 +21,7 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraft.world.border.WorldBorder; +import net.minecraftforge.fml.common.network.handshake.FMLHandshakeMessage; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -51,7 +53,7 @@ public static void preIteration(final RenderChunk renderChunk, final float x, fi @SideOnly(Side.CLIENT) public static boolean renderBlockDamage(final Tessellator tessellatorIn, final BufferBuilder bufferBuilderIn, final BlockPos blockpos, final IBlockState iblockstate, final WorldClient world, final TextureAtlasSprite textureatlassprite, final BlockRendererDispatcher blockrendererdispatcher) { if (!NoCubesConfig.Client.render || !NoCubes.smoothableHandler.isSmoothable(iblockstate)) { - return true; + return true; } RenderDispatcher.renderBreakingTexture(tessellatorIn, bufferBuilderIn, blockpos, iblockstate, world, textureatlassprite); return false; @@ -79,4 +81,18 @@ public static boolean canBlockStateRender(final IBlockState blockstate) { return !NoCubesConfig.Client.render || !NoCubes.smoothableHandler.isSmoothable(blockstate); } + /** + * Called from: {@link net.minecraftforge.fml.common.network.internal.FMLNetworkHandler#checkModList(FMLHandshakeMessage.ModList, Side)} when it is invoked during client/server connection handshake. + * Calls: Nothing + * Lets us find out if the server we are connecting to has NoCubes installed. + * NB: This is not called when looking at the list of servers in the 'Multiplayer' menu, only when actually connecting to a server. + * NB: This is also called for singleplayer. + */ + public static void onCheckModList(FMLHandshakeMessage.ModList modListPacket, Side side) { + // We only care about the server's mod list, not the client's + if (side == Side.SERVER) { + NoCubesNetwork.currentServerHasNoCubes = modListPacket.modList().containsKey(NoCubes.MOD_ID); + } + } + } diff --git a/src/main/java/io/github/cadiboo/nocubes/tempcore/FMLNetworkHandlerTransformer.java b/src/main/java/io/github/cadiboo/nocubes/tempcore/FMLNetworkHandlerTransformer.java new file mode 100644 index 00000000..bd634db3 --- /dev/null +++ b/src/main/java/io/github/cadiboo/nocubes/tempcore/FMLNetworkHandlerTransformer.java @@ -0,0 +1,104 @@ +package io.github.cadiboo.nocubes.tempcore; + +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.InsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; + +import java.util.List; + +import static io.github.cadiboo.nocubes.tempcore.NoCubesClassTransformer.finish; +import static io.github.cadiboo.nocubes.tempcore.NoCubesClassTransformer.log; +import static io.github.cadiboo.nocubes.tempcore.NoCubesClassTransformer.mapField; +import static io.github.cadiboo.nocubes.tempcore.NoCubesClassTransformer.start; + +/** + * @author Cadiboo + */ +final class FMLNetworkHandlerTransformer implements Opcodes { + + // Local variable indexes + private static final int ALOCALVARIABLE_this = 0; + private static final int ALOCALVARIABLE_movingEntity = 1; + private static final int ALOCALVARIABLE_area = 2; + private static final int ALOCALVARIABLE_entityShape = 3; + private static final int ILOCALVARIABLE_flag1 = 6; + + static void transform(final ClassNode classNode) { + + final List methods = classNode.methods; + + //getCollisionBoxes + { + final String targetMethodDesc = "(Lnet/minecraftforge/fml/common/network/handshake/FMLHandshakeMessage$ModList;Lnet/minecraftforge/fml/relauncher/Side;)Ljava/lang/String;"; + final String targetMethodName = "checkModList"; + + start("Find " + targetMethodName); + for (final MethodNode method : methods) { + + if (!method.name.equals(targetMethodName)) { + log("Did not match method name " + targetMethodName + " - " + method.name); + continue; + } else if (!method.desc.equals(targetMethodDesc)) { + log("Did not match method desc " + targetMethodDesc + " - " + method.desc); + continue; + } + log("Matched method " + method.name + " " + method.desc); + + finish(); + + start("Inject checkModList hook"); + injectCheckModList(method.instructions); + finish(); + break; + + } + } + } + + private static void injectCheckModList(InsnList instructions) { + AbstractInsnNode firstLabel = null; + int arrayLength = instructions.size(); + for (int i = 0; i < arrayLength; ++i) { + AbstractInsnNode instruction = instructions.get(i); + if (instruction.getType() == AbstractInsnNode.LABEL) { + firstLabel = instruction; + log("Found injection point " + instruction); + break; + } + } + if (firstLabel == null) { + throw new RuntimeException("Error: Couldn't find injection point!"); + } + + InsnList toInject = new InsnList(); + + // Make list of instructions to inject + toInject.add(new VarInsnNode(ALOAD, 0)); + toInject.add(new VarInsnNode(ALOAD, 1)); + toInject.add(new MethodInsnNode( + //int opcode + INVOKESTATIC, + //String owner + "io/github/cadiboo/nocubes/hooks/Hooks", + //String name + "onCheckModList", + //String descriptor + "(Lnet/minecraftforge/fml/common/network/handshake/FMLHandshakeMessage$ModList;Lnet/minecraftforge/fml/relauncher/Side;)V", + //boolean isInterface + false + )); + toInject.add(new LabelNode()); + + // Inject instructions + instructions.insert(firstLabel, toInject); + + } + +} diff --git a/src/main/java/io/github/cadiboo/nocubes/tempcore/NoCubesClassTransformer.java b/src/main/java/io/github/cadiboo/nocubes/tempcore/NoCubesClassTransformer.java index 09fa5ea1..30d99403 100644 --- a/src/main/java/io/github/cadiboo/nocubes/tempcore/NoCubesClassTransformer.java +++ b/src/main/java/io/github/cadiboo/nocubes/tempcore/NoCubesClassTransformer.java @@ -96,6 +96,10 @@ public byte[] transform(final String name, final String transformedName, @Nullab return transformClass(basicClass, transformedName, RenderGlobalTransformer::transform ); + case "net.minecraftforge.fml.common.network.internal.FMLNetworkHandler": + return transformClass(basicClass, transformedName, + FMLNetworkHandlerTransformer::transform + ); } return basicClass; }