1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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;
}
}
|