diff --git a/changelog.txt b/changelog.txt index a3c3efd68..830efc4f5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,6 @@ - Fallen logs can rarely spawn on water - Fallen logs can no longer spawn on ice and other non terrain blocks (added tag for them) - Fallen log decoration (moss and vines) are now biome temperature and humidify dependent. No more moss in snowy biomes +- Freestanding ladders will now break off the wall when you break the top block - Matrix Enchanting Table appears in creative if automaticallyConvert is off -- Fixed Skull Pikes not functioning when there's a block on top, by lowering the detection point \ No newline at end of file +- Fixed Skull Pikes not functioning when there's a block on top, by lowering the detection point diff --git a/src/main/java/org/violetmoon/quark/content/tweaks/module/EnhancedLaddersModule.java b/src/main/java/org/violetmoon/quark/content/tweaks/module/EnhancedLaddersModule.java index f62a31aa1..f37ceb016 100644 --- a/src/main/java/org/violetmoon/quark/content/tweaks/module/EnhancedLaddersModule.java +++ b/src/main/java/org/violetmoon/quark/content/tweaks/module/EnhancedLaddersModule.java @@ -4,7 +4,6 @@ import net.minecraft.client.player.Input; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; @@ -21,13 +20,13 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LadderBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; @@ -64,10 +63,12 @@ public class EnhancedLaddersModule extends ZetaModule { @Config public static boolean allowInventorySneak = true; - private static boolean staticEnabled; + public static boolean staticEnabled; private static TagKey laddersTag; private static TagKey laddersBlockTag; + private static final DirectionProperty FACING = LadderBlock.FACING; + @LoadEvent public final void setup(ZCommonSetup event) { laddersTag = ItemTags.create(new ResourceLocation(Quark.MOD_ID, "ladders")); @@ -106,35 +107,23 @@ public void addAdditionalHints(ZGatherHints event) { event.accept(item, comp); } - private static boolean canAttachTo(BlockState state, Block ladder, LevelReader world, BlockPos pos, Direction facing) { - if(ladder instanceof LadderBlock) { - if(allowFreestanding) - return canLadderSurvive(state, world, pos); - - BlockPos offset = pos.relative(facing); - BlockState blockstate = world.getBlockState(offset); - return !blockstate.isSignalSource() && blockstate.isFaceSturdy(world, offset, facing); - } + // see LadderBlockMixin + public static boolean canSurviveTweak(boolean vanillaSurvive, BlockState state, LevelReader world, BlockPos pos) { + //With the freestanding feature enabled, ladders can survive if they are supported by a block (vanillaSurvive), + //or if they are underneath a ladder on the same wall. + if(vanillaSurvive) + return true; - return false; - } - - // replaces ladder survives logic - public static boolean canLadderSurvive(BlockState state, LevelReader world, BlockPos pos) { - if(!staticEnabled || !allowFreestanding) + if(!staticEnabled || !allowFreestanding || !state.is(laddersBlockTag) || !state.hasProperty(FACING)) return false; - if(!state.is(laddersBlockTag))return false; - - Direction facing = state.getValue(LadderBlock.FACING); - Direction opposite = facing.getOpposite(); - BlockPos oppositePos = pos.relative(opposite); - BlockState oppositeState = world.getBlockState(oppositePos); - boolean solid = oppositeState.isFaceSturdy(world, oppositePos, facing) && !(oppositeState.getBlock() instanceof LadderBlock); - BlockState topState = world.getBlockState(pos.above()); - return solid || (topState.getBlock() instanceof LadderBlock && (facing.getAxis() == Axis.Y || topState.getValue(LadderBlock.FACING) == facing)); + BlockState aboveState = world.getBlockState(pos.above()); + return aboveState.is(laddersBlockTag) && aboveState.hasProperty(FACING) && aboveState.getValue(FACING) == state.getValue(FACING); } + public static boolean shouldDoUpdateShapeTweak(BlockState state) { + return staticEnabled && allowFreestanding && state.is(laddersBlockTag); + } @PlayEvent public void onInteract(ZRightClickBlock event) { @@ -164,8 +153,7 @@ public void onInteract(ZRightClickBlock event) { if(water || stateDown.isAir()) { BlockState copyState = world.getBlockState(pos); - Direction facing = copyState.getValue(LadderBlock.FACING); - if(canAttachTo(copyState, block, world, posDown, facing.getOpposite())) { + if(copyState.canSurvive(world, posDown)) { world.setBlockAndUpdate(posDown, copyState.setValue(BlockStateProperties.WATERLOGGED, water)); world.playSound(null, posDown.getX(), posDown.getY(), posDown.getZ(), SoundEvents.LADDER_PLACE, SoundSource.BLOCKS, 1F, 1F); diff --git a/src/main/java/org/violetmoon/quark/mixin/mixins/BlockBehaviourMixin.java b/src/main/java/org/violetmoon/quark/mixin/mixins/BlockBehaviourMixin.java new file mode 100644 index 000000000..d8d74f902 --- /dev/null +++ b/src/main/java/org/violetmoon/quark/mixin/mixins/BlockBehaviourMixin.java @@ -0,0 +1,22 @@ +package org.violetmoon.quark.mixin.mixins; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +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; + +/** + * Exists to be subclassed by LadderBlockMixin basically + */ +@Mixin(BlockBehaviour.class) +public class BlockBehaviourMixin { + @Inject(method = "tick", at = @At("HEAD")) + public void quark$tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom, CallbackInfo ci) { + + } +} diff --git a/src/main/java/org/violetmoon/quark/mixin/mixins/LadderBlockMixin.java b/src/main/java/org/violetmoon/quark/mixin/mixins/LadderBlockMixin.java index 1b399f98d..3bcabe537 100644 --- a/src/main/java/org/violetmoon/quark/mixin/mixins/LadderBlockMixin.java +++ b/src/main/java/org/violetmoon/quark/mixin/mixins/LadderBlockMixin.java @@ -1,30 +1,55 @@ package org.violetmoon.quark.mixin.mixins; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.LadderBlock; import net.minecraft.world.level.block.state.BlockState; 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; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - import org.violetmoon.quark.content.tweaks.module.EnhancedLaddersModule; @Mixin(LadderBlock.class) -public class LadderBlockMixin { - +public class LadderBlockMixin extends BlockBehaviourMixin { + @ModifyReturnValue(method = "canSurvive", at = @At("RETURN")) + private boolean canSurviveTweak(boolean original, BlockState state, LevelReader level, BlockPos pos) { + return EnhancedLaddersModule.canSurviveTweak(original, state, level, pos); + } - @Inject(method = "canSurvive", at = @At("HEAD"), cancellable = true) - private void canSurvive(BlockState state, LevelReader level, BlockPos pos, CallbackInfoReturnable callbackInfoReturnable) { - if(EnhancedLaddersModule.canLadderSurvive(state, level, pos)) { - callbackInfoReturnable.setReturnValue(true); - callbackInfoReturnable.cancel(); + /** + * In vanilla, the only way to break a ladder is to break the block behind it. So in updateShape, + * vanilla only does ladder canSurvive checks if the update came from behind. But with Quark's + * freestanding ladder feature, it's possible to break a ladder by breaking a block *above* it. + */ + @Inject(method = "updateShape", at = @At(value = "HEAD"), cancellable = true) + private void updateShapeTweak(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos, CallbackInfoReturnable cir) { + if(EnhancedLaddersModule.shouldDoUpdateShapeTweak(pState) && pFacing == Direction.UP) { + //This is just for fun. Makes the ladders break like bamboo instead of instantly. + pLevel.scheduleTick(pCurrentPos, (LadderBlock) (Object) this, 1); + cir.setReturnValue(pState); } } + /** + * Override from BlockBehaviourMixin which does the actual injection + */ + @Override + public void quark$tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom, CallbackInfo ci) { + if(EnhancedLaddersModule.shouldDoUpdateShapeTweak(pState) && !pState.canSurvive(pLevel, pPos)) { + pLevel.destroyBlock(pPos, true); + } + } } diff --git a/src/main/resources/quark.mixins.json b/src/main/resources/quark.mixins.json index 1f9f3dbe1..16e6d671f 100644 --- a/src/main/resources/quark.mixins.json +++ b/src/main/resources/quark.mixins.json @@ -16,6 +16,7 @@ "BaseCoralPlantTypeBlockMixin", "BeaconBlockEntityMixin", "BeehiveBlockEntityMixin", + "BlockBehaviourMixin", "BlockItemMixin", "BoatMixin", "CeilingHangingSignBlockMixin",