diff --git a/src/main/java/ftbsc/bscv/modules/self/Immovable.java b/src/main/java/ftbsc/bscv/modules/self/Immovable.java new file mode 100644 index 0000000..b01a14e --- /dev/null +++ b/src/main/java/ftbsc/bscv/modules/self/Immovable.java @@ -0,0 +1,85 @@ +package ftbsc.bscv.modules.self; + +import com.google.auto.service.AutoService; + +import ftbsc.bscv.api.ILoadable; +import ftbsc.bscv.modules.AbstractModule; +import ftbsc.bscv.patches.BlockPushPatch.PlayerBlockPushEvent; +import ftbsc.bscv.patches.EntityPushPatch.PlayerEntityPushEvent; +import ftbsc.bscv.patches.LiquidPushPatch.PlayerLiquidPushEvent; +import ftbsc.bscv.patches.PacketPatch.PacketEvent; +import ftbsc.bscv.tools.Setting; +import net.minecraft.network.play.server.SEntityVelocityPacket; +import net.minecraft.network.play.server.SExplosionPacket; +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +@AutoService(ILoadable.class) +public class Immovable extends AbstractModule { + + public final ForgeConfigSpec.ConfigValue explosions; + public final ForgeConfigSpec.ConfigValue server; + public final ForgeConfigSpec.ConfigValue liquids; + public final ForgeConfigSpec.ConfigValue entities; + public final ForgeConfigSpec.ConfigValue blocks; + + public Immovable() { + super(); + + this.explosions = Setting.Bool.builder() + .fallback(true) + .name("explosions") + .comment("cancel velocity from explosions") + .build(this); + this.server = Setting.Bool.builder() + .fallback(true) + .name("server") + .comment("cancel velocity sent from server") + .build(this); + this.liquids = Setting.Bool.builder() + .fallback(true) + .name("liquids") + .comment("cancel velocity from liquids pushing") + .build(this); + this.entities = Setting.Bool.builder() + .fallback(true) + .name("entities") + .comment("cancel velocity from entities pushing") + .build(this); + this.blocks = Setting.Bool.builder() + .fallback(true) + .name("block") + .comment("cancel velocity from blocks pushing") + .build(this); + } + + @SubscribeEvent + public void onPacket(PacketEvent.Incoming event) { + if (event.packet instanceof SExplosionPacket && this.explosions.get()) { + event.setCanceled(true); + } + + if (event.packet instanceof SEntityVelocityPacket && this.server.get()) { + SEntityVelocityPacket packet = (SEntityVelocityPacket) event.packet; + if (packet.getId() == MC.player.getId()) { + event.setCanceled(true); + } + } + } + + @SubscribeEvent + public void onEntityCollisions(PlayerEntityPushEvent event) { + if (this.entities.get()) event.setCanceled(true); + } + + @SubscribeEvent + public void onBlockCollisions(PlayerBlockPushEvent event) { + if (this.blocks.get()) event.setCanceled(true); + } + + @SubscribeEvent + public void onLiquidCollisions(PlayerLiquidPushEvent event) { + if (this.liquids.get()) event.setCanceled(true); + } + +} diff --git a/src/main/java/ftbsc/bscv/patches/BlockPushPatch.java b/src/main/java/ftbsc/bscv/patches/BlockPushPatch.java new file mode 100644 index 0000000..50fb677 --- /dev/null +++ b/src/main/java/ftbsc/bscv/patches/BlockPushPatch.java @@ -0,0 +1,46 @@ +package ftbsc.bscv.patches; + +import ftbsc.lll.processor.annotations.Injector; +import ftbsc.lll.processor.annotations.Patch; +import ftbsc.lll.processor.annotations.Target; +import ftbsc.lll.tools.InsnSequence; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Cancelable; +import net.minecraftforge.eventbus.api.Event; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; + +public class BlockPushPatch { + + @Cancelable + public static class PlayerBlockPushEvent extends Event {} + + public static boolean shouldCancelBlockCollisions() { + return MinecraftForge.EVENT_BUS.post(new PlayerBlockPushEvent()); + } + + @Patch(value = ClientPlayerEntity.class, reason = "add hook to cancel block collisions") + public abstract static class BlockCollisionsOverride implements Opcodes { + @Target + abstract void moveTowardsClosestSpace(double x, double z); + + @Injector + public void inject(ClassNode clazz, MethodNode main) { + LabelNode skip = new LabelNode(); + InsnSequence is = new InsnSequence(); + is.add(new MethodInsnNode( + INVOKESTATIC, + "ftbsc/bscv/patches/BlockPushPatch", + "shouldCancelBlockCollisions", + "()Z" + )); + is.add(new JumpInsnNode(IFEQ, skip)); + is.add(new InsnNode(RETURN)); + is.add(skip); + + main.instructions.insert(is); // hook at top + } + } +} diff --git a/src/main/java/ftbsc/bscv/patches/EntityPushPatch.java b/src/main/java/ftbsc/bscv/patches/EntityPushPatch.java new file mode 100644 index 0000000..cbb63c6 --- /dev/null +++ b/src/main/java/ftbsc/bscv/patches/EntityPushPatch.java @@ -0,0 +1,51 @@ +package ftbsc.bscv.patches; + +import ftbsc.bscv.ICommons; +import ftbsc.lll.processor.annotations.Injector; +import ftbsc.lll.processor.annotations.Patch; +import ftbsc.lll.processor.annotations.Target; +import ftbsc.lll.tools.InsnSequence; +import net.minecraft.entity.Entity; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Cancelable; +import net.minecraftforge.eventbus.api.Event; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; + +public class EntityPushPatch implements ICommons { + + @Cancelable + public static class PlayerEntityPushEvent extends Event {} + + public static boolean shouldCancelEntityCollisions(Entity e) { + if (e.equals(MC.player)) { + return MinecraftForge.EVENT_BUS.post(new PlayerEntityPushEvent()); + } + return false; + } + + @Patch(value = Entity.class, reason = "add hook to cancel entity collisions") + public abstract static class EntityCollisionsOverride implements Opcodes { + @Target + abstract void push(double x, double y, double z); + + @Injector + public void inject(ClassNode clazz, MethodNode main) { + LabelNode skip = new LabelNode(); + InsnSequence is = new InsnSequence(); + is.add(new VarInsnNode(ALOAD, 0)); + is.add(new MethodInsnNode( + INVOKESTATIC, + "ftbsc/bscv/patches/EntityPushPatch", + "shouldCancelEntityCollisions", + "(Lnet/minecraft/entity/Entity;)Z" + )); + is.add(new JumpInsnNode(IFEQ, skip)); + is.add(new InsnNode(RETURN)); + is.add(skip); + + main.instructions.insert(is); // hook at top + } + } +} diff --git a/src/main/java/ftbsc/bscv/patches/LiquidPushPatch.java b/src/main/java/ftbsc/bscv/patches/LiquidPushPatch.java new file mode 100644 index 0000000..838bea3 --- /dev/null +++ b/src/main/java/ftbsc/bscv/patches/LiquidPushPatch.java @@ -0,0 +1,52 @@ +package ftbsc.bscv.patches; + +import ftbsc.bscv.ICommons; +import ftbsc.lll.processor.annotations.Injector; +import ftbsc.lll.processor.annotations.Patch; +import ftbsc.lll.processor.annotations.Target; +import ftbsc.lll.tools.InsnSequence; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Cancelable; +import net.minecraftforge.eventbus.api.Event; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; + +public class LiquidPushPatch implements ICommons { + + @Cancelable + public static class PlayerLiquidPushEvent extends Event {} + + public static boolean shouldCancelLiquidCollisions(PlayerEntity player) { + if (player.equals(MC.player)) { + return MinecraftForge.EVENT_BUS.post(new PlayerLiquidPushEvent()); + } + return false; + } + + @Patch(value = PlayerEntity.class, reason = "add hook to cancel liquid collisions") + public abstract static class LiquidCollisionsOverride implements Opcodes { + @Target + abstract boolean isPushedByFluid(); + + @Injector + public void inject(ClassNode clazz, MethodNode main) { + LabelNode skip = new LabelNode(); + InsnSequence is = new InsnSequence(); + is.add(new VarInsnNode(ALOAD, 0)); + is.add(new MethodInsnNode( + INVOKESTATIC, + "ftbsc/bscv/patches/LiquidPushPatch", + "shouldCancelLiquidCollisions", + "(Lnet/minecraft/entity/player/PlayerEntity;)Z" + )); + is.add(new JumpInsnNode(IFEQ, skip)); + is.add(new InsnNode(ICONST_0)); + is.add(new InsnNode(IRETURN)); + is.add(skip); + + main.instructions.insert(is); // hook at top + } + } +}