Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/main/java/dev/anvilcraft/lib/block/IMoveableEntityBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dev.anvilcraft.lib.block;

import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.EntityBlock;

import javax.annotation.ParametersAreNonnullByDefault;

@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@SuppressWarnings("unused")
public interface IMoveableEntityBlock extends EntityBlock {
/**
* 在可推动方块实体方块被推动时所会执行的,它的返回值是需要传递的方块实体数据
* @param level 世界
* @param pos 方块位置
* @return 需要被传递的方块实体数据
*/
default CompoundTag clearData(Level level, BlockPos pos) {
return new CompoundTag();
}

/**
* 在在可推动方块实体方块抵达被推动的位置停下时,将被传递的方块实体数据重新设置进入方块实体的方法
* @param level 世界
* @param pos 方块位置
* @param nbt 需要被设置的方块实体数据
*/
default void setData(Level level, BlockPos pos, CompoundTag nbt) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.anvilcraft.lib.injection;

import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;

import javax.annotation.ParametersAreNonnullByDefault;

@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public interface IPistonMovingBlockEntityExtension {
default @Nullable CompoundTag anvillib$clearData() {
throw new AssertionError();
}

default void anvillib$setData(@Nullable CompoundTag nbt) {
throw new AssertionError();
}

default @Nullable BlockState anvillib$getMoveState() {
throw new AssertionError();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package dev.anvilcraft.lib.mixin.piston;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import dev.anvilcraft.lib.block.IMoveableEntityBlock;
import dev.anvilcraft.lib.injection.IPistonMovingBlockEntityExtension;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.piston.PistonBaseBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;

@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@Mixin(value = PistonBaseBlock.class, priority = 943)
abstract class PistonBaseBlockMixin {
@Unique
private CompoundTag anvillib$nbt;

@WrapOperation(
method = "isPushable",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;hasBlockEntity()Z")
)
private static boolean isPushable(BlockState instance, Operation<Boolean> original) {
return original.call(instance) && !(instance.getBlock() instanceof IMoveableEntityBlock);
}

@Inject(
method = "moveBlocks",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/Level;setBlock("
+ "Lnet/minecraft/core/BlockPos;"
+ "Lnet/minecraft/world/level/block/state/BlockState;"
+ "I"
+ ")Z",
ordinal = 1
)
)
private void setBlock(
Level level, BlockPos pos, Direction facing, boolean extending, CallbackInfoReturnable<Boolean> cir,
@Local(ordinal = 2) BlockPos blockpos,
@Local(ordinal = 1) Direction direction,
@Local(ordinal = 1) List<BlockState> list1,
@Local(ordinal = 1) int k
) {
if (level.isClientSide()) return;
this.anvillib$nbt = new CompoundTag();
if (list1.get(k).getBlock() instanceof IMoveableEntityBlock block) {
this.anvillib$nbt = block.clearData(level, blockpos.relative(direction.getOpposite()));
}
}

@WrapOperation(
method = "moveBlocks",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/piston/MovingPistonBlock;newMovingBlockEntity("
+ "Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;"
+ "Lnet/minecraft/world/level/block/state/BlockState;"
+ "Lnet/minecraft/core/Direction;ZZ"
+ ")Lnet/minecraft/world/level/block/entity/BlockEntity;",
ordinal = 0
)
)
private BlockEntity newMovingBlockEntity(
BlockPos pos,
BlockState blockState,
BlockState movedState,
Direction direction,
boolean extending,
boolean isSourcePiston,
Operation<BlockEntity> original
) {
BlockEntity blockEntity = original.call(pos, blockState, movedState, direction, extending, isSourcePiston);
if (blockEntity instanceof IPistonMovingBlockEntityExtension entity) {
entity.anvillib$setData(this.anvillib$nbt);
}
return blockEntity;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package dev.anvilcraft.lib.mixin.piston;

import com.llamalad7.mixinextras.sugar.Local;
import dev.anvilcraft.lib.block.IMoveableEntityBlock;
import dev.anvilcraft.lib.injection.IPistonMovingBlockEntityExtension;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.piston.PistonMovingBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import javax.annotation.ParametersAreNonnullByDefault;

@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@Mixin(PistonMovingBlockEntity.class)
abstract class PistonMovingBlockEntityMixin extends BlockEntity implements IPistonMovingBlockEntityExtension {
@Shadow
private BlockState movedState;
@Unique
private CompoundTag anvillib$nbt = new CompoundTag();

public PistonMovingBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState blockState) {
super(type, pos, blockState);
}

@Override
public CompoundTag anvillib$clearData() {
CompoundTag nbt = this.anvillib$nbt;
this.anvillib$nbt = new CompoundTag();
return nbt;
}

@Override
public void anvillib$setData(@Nullable CompoundTag nbt) {
if (nbt == null) return;
this.anvillib$nbt.merge(nbt);
}

@Override
public BlockState anvillib$getMoveState() {
return this.movedState;
}

@Inject(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/Level;"
+ "setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z",
shift = At.Shift.AFTER,
ordinal = 1
)
)
private static void tick(
Level level,
BlockPos pos,
BlockState state,
PistonMovingBlockEntity blockEntity,
CallbackInfo ci,
@Local(ordinal = 1) BlockState moveState
) {
if (level.isClientSide()) return;
// noinspection ConstantValue
if (!(blockEntity instanceof IPistonMovingBlockEntityExtension blockEntity1)) return;
if (!(moveState.getBlock() instanceof IMoveableEntityBlock entityBlock)) return;
CompoundTag tag = blockEntity1.anvillib$clearData();
if (tag != null) {
entityBlock.setData(level, pos, tag);
}
}

@Inject(
method = "finalTick", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/Level;"
+ "setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z",
shift = At.Shift.AFTER
)
)
private void finalTick(CallbackInfo ci, @Local BlockState moveState) {
if (this.level == null || this.level.isClientSide()) return;
// noinspection ConstantValue
if (!(this instanceof IPistonMovingBlockEntityExtension blockEntity1)) return;
if (!(moveState.getBlock() instanceof IMoveableEntityBlock entityBlock)) return;
CompoundTag tag = blockEntity1.anvillib$clearData();
// noinspection ConstantValue
if (tag != null) {
entityBlock.setData(level, this.worldPosition, tag);
}
}
}
4 changes: 3 additions & 1 deletion src/main/resources/anvillib.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"refmap": "anvillib.refmap.json",
"mixins": [
"ItemEntityMixin",
"RecipeManagerMixin"
"RecipeManagerMixin",
"piston.PistonBaseBlockMixin",
"piston.PistonMovingBlockEntityMixin"
],
"client": [
],
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/interface_injections.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"net/minecraft/world/item/crafting/RecipeManager": [
"dev/anvilcraft/lib/injection/IRecipeManagerExtension"
],
"net/minecraft/world/level/block/piston/PistonMovingBlockEntity": [
"dev/anvilcraft/lib/injection/IPistonMovingBlockEntityExtension"
]
}
Loading