diff options
Diffstat (limited to 'src/main/java/wtf/kity/uncrackable/mixin/FallingBlockEntityMixin.java')
| -rw-r--r-- | src/main/java/wtf/kity/uncrackable/mixin/FallingBlockEntityMixin.java | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/main/java/wtf/kity/uncrackable/mixin/FallingBlockEntityMixin.java b/src/main/java/wtf/kity/uncrackable/mixin/FallingBlockEntityMixin.java new file mode 100644 index 0000000..500f970 --- /dev/null +++ b/src/main/java/wtf/kity/uncrackable/mixin/FallingBlockEntityMixin.java @@ -0,0 +1,112 @@ +package wtf.kity.uncrackable.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import org.objectweb.asm.Opcodes; +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; + +@Mixin(FallingBlockEntity.class) +public abstract class FallingBlockEntityMixin extends Entity { + public FallingBlockEntityMixin(EntityType<?> entityType, Level level) { + super(entityType, level); + } + + /// If the egg falls into the void, teleport back up to build limit. + @Inject(method = "tick", at = @At("HEAD")) + private void beforeTick(CallbackInfo ci) { + Vec3 pos = this.position(); + if (pos.y < this.level().getMinBuildHeight()) { + this.teleportTo(pos.x, this.level().getMaxBuildHeight(), pos.z); + } + } + + /// Egg should never time out. Skip add-assign operation entirely for the egg. + @WrapOperation( + method = "tick", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/world/entity/item/FallingBlockEntity;time:I", + opcode = Opcodes.PUTFIELD + ) + ) + private void setTime(FallingBlockEntity instance, int value, Operation<Void> original) { + if (!instance.getBlockState().is(Blocks.DRAGON_EGG)) { + original.call(instance, value); + } + } + + /// Egg should not drop as an item if it lands above build height. + @WrapOperation( + method = "tick", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/world/entity/item/FallingBlockEntity;dropItem:Z", + opcode = Opcodes.GETFIELD + ) + ) + private boolean getDropItem(FallingBlockEntity instance, Operation<Boolean> original) { + if (instance.getBlockState().is(Blocks.DRAGON_EGG)) { + return false; + } + return original.call(instance); + } + + /// If it lands inside a block, destroy the block as if by piston push. + /// We override block shapes for non-piston-destructible blocks in`BlockBehaviorMixin` + /// so normally this only applies to piston-destructible blocks, unless a block is pushed + /// into the egg while it's an entity. + @WrapOperation( + method = "tick", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/state/BlockState;canBeReplaced(Lnet/minecraft/world/item/context/BlockPlaceContext;)Z" + ) + ) + private boolean canBeReplaced( + BlockState instance, + BlockPlaceContext blockPlaceContext, + Operation<Boolean> original, + @Local BlockPos blockPos + ) { + if (original.call(instance, blockPlaceContext)) { + return true; + } + + if (instance.is(Blocks.DRAGON_EGG)) { + BlockEntity blockentity = instance.hasBlockEntity() ? this.level().getBlockEntity(blockPos) : null; + Block.dropResources(instance, this.level(), blockPos, blockentity); + instance.onDestroyedByPushReaction(this.level(), blockPos, Direction.DOWN, this.level().getFluidState(blockPos)); + return true; + } + + return false; + } + + /// The egg should never drop as an item, so we always pretend that the ground beneath it is landable. + @WrapOperation( + method = "tick", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/FallingBlock;isFree(Lnet/minecraft/world/level/block/state/BlockState;)Z" + ) + ) + private boolean isFree(BlockState state, Operation<Boolean> original, @Local Block block) { + return original.call(state) && block != Blocks.DRAGON_EGG; + } +} |