diff --git a/src/main/java/twilightforest/block/AbstractSkullCandleBlock.java b/src/main/java/twilightforest/block/AbstractSkullCandleBlock.java index 5a59f7dc8a..d9be5416d8 100644 --- a/src/main/java/twilightforest/block/AbstractSkullCandleBlock.java +++ b/src/main/java/twilightforest/block/AbstractSkullCandleBlock.java @@ -231,7 +231,7 @@ public void animateTick(BlockState state, Level level, BlockPos pos, RandomSourc @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(LIGHTING, CANDLES); + builder.add(LIGHTING, CANDLES, POWERED); } @Nullable diff --git a/src/main/java/twilightforest/block/BurntThornsBlock.java b/src/main/java/twilightforest/block/BurntThornsBlock.java index 95a77b18a2..9a649e98f9 100644 --- a/src/main/java/twilightforest/block/BurntThornsBlock.java +++ b/src/main/java/twilightforest/block/BurntThornsBlock.java @@ -2,10 +2,12 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.InsideBlockEffectApplier; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -27,7 +29,7 @@ public PathType getBlockPathType(BlockState state, BlockGetter getter, BlockPos } @Override - public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier, boolean isPrecise) { // dissolve if (!level.isClientSide() && (entity instanceof LivingEntity || entity instanceof Projectile)) { level.destroyBlock(pos, false); @@ -35,7 +37,7 @@ public void entityInside(BlockState state, Level level, BlockPos pos, Entity ent } @Override - public boolean onDestroyedByPlayer(BlockState state, Level level, BlockPos pos, Player player, boolean willHarvest, FluidState fluid) { + public boolean onDestroyedByPlayer(BlockState state, Level level, BlockPos pos, Player player, ItemStack toolStack, boolean willHarvest, FluidState fluid) { state.getBlock().playerWillDestroy(level, pos, state, player); return level.setBlock(pos, fluid.createLegacyBlock(), level.isClientSide() ? Block.UPDATE_ALL_IMMEDIATE : Block.UPDATE_ALL); } diff --git a/src/main/java/twilightforest/block/MasonJarBlock.java b/src/main/java/twilightforest/block/MasonJarBlock.java index 0a7c3bdf00..666b41e845 100644 --- a/src/main/java/twilightforest/block/MasonJarBlock.java +++ b/src/main/java/twilightforest/block/MasonJarBlock.java @@ -11,10 +11,12 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.ShulkerBoxBlock; import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.entity.BlockEntity; @@ -27,6 +29,8 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.BlockHitResult; import net.neoforged.neoforge.common.world.AuxiliaryLightManager; +import net.neoforged.neoforge.transfer.item.ItemResource; +import net.neoforged.neoforge.transfer.transaction.Transaction; import twilightforest.block.entity.MasonJarBlockEntity; import twilightforest.init.TFSounds; @@ -35,7 +39,6 @@ public class MasonJarBlock extends JarBlock implements SimpleWaterloggedBlock { public static final MapCodec CODEC = simpleCodec(MasonJarBlock::new); private static final int SLOT = 0; - private static final int ALL = Integer.MAX_VALUE; public MasonJarBlock(BlockBehaviour.Properties properties) { super(properties); @@ -67,37 +70,63 @@ protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level l } private static void handleEmptyHand(ServerLevel server, BlockPos pos, Player player, InteractionHand hand, MasonJarBlockEntity jar, MasonJarBlockEntity.MasonJarItemStackHandler handler) { - ItemStack preview = handler.extractItem(SLOT, ALL, true); - if (preview.isEmpty()) { + ItemResource resource = handler.getResource(SLOT); + if (resource.isEmpty()) { wiggle(server, pos, jar); return; } + + ItemStack preview = resource.toStack(handler.getAmountAsInt(SLOT)); if (player.isSecondaryUseActive()) { player.sendOverlayMessage(Component.literal(preview.getHoverName().getString() + " x" + preview.getCount())); wiggle(server, pos, jar); return; } - ItemStack extracted = handler.extractItem(SLOT, ALL, false); - player.setItemInHand(hand, extracted); - server.playSound(null, pos, TFSounds.JAR_REMOVE.get(), SoundSource.BLOCKS, 1.0F, 1.0F); - server.gameEvent(player, GameEvent.BLOCK_CHANGE, pos); + + int maxAmount = Math.min(Item.ABSOLUTE_MAX_STACK_SIZE, resource.getItem().getMaxStackSize(resource.toStack())); + + try (Transaction transaction = Transaction.openRoot()) { + int countExtracted = handler.extract(SLOT, resource, maxAmount, transaction); + if (countExtracted <= 0) { + wiggle(server, pos, jar); + return; + } + + transaction.commit(); + server.sendBlockUpdated(pos, jar.getBlockState(), jar.getBlockState(), Block.UPDATE_ALL); + player.setItemInHand(hand, preview); + server.playSound(null, pos, TFSounds.JAR_REMOVE.get(), SoundSource.BLOCKS, 1.0F, 1.0F); + server.gameEvent(player, GameEvent.BLOCK_CHANGE, pos); + } } private static void handleInsert(ServerLevel server, BlockPos pos, Player player, InteractionHand hand, MasonJarBlockEntity jar, MasonJarBlockEntity.MasonJarItemStackHandler handler, ItemStack stack) { - // Simulate insert first; if nothing would go in then just wiggle - if (handler.insertItem(SLOT, stack, true).getCount() >= stack.getCount()) { - wiggle(server, pos, jar); - return; - } + ItemResource resource = ItemResource.of(stack); + int amountToInsert = stack.getCount(); + int oldRotation = jar.getItemRotation(); jar.setItemRotation(RotationSegment.convertToSegment(player.getYRot() + 180.0F)); - player.awardStat(Stats.ITEM_USED.get(stack.getItem())); - ItemStack before = stack.copy(); - ItemStack remainder = handler.insertItem(SLOT, stack, false); - player.setItemInHand(hand, player.hasInfiniteMaterials() ? before : remainder); - float filledRatio = (float) (before.getCount() - remainder.getCount()) / (float) before.getMaxStackSize(); - server.playSound(null, pos, TFSounds.JAR_INSERT.get(), SoundSource.BLOCKS, 1.0F, 0.7F + 0.5F * filledRatio); - server.gameEvent(player, GameEvent.BLOCK_CHANGE, pos); + + try (Transaction transaction = Transaction.openRoot()) { + int inserted = handler.insert(SLOT, resource, amountToInsert, transaction); + + if (inserted <= 0) { + jar.setItemRotation(oldRotation); + wiggle(server, pos, jar); + return; + } + + transaction.commit(); + + player.awardStat(Stats.ITEM_USED.get(stack.getItem())); + ItemStack before = stack.copy(); + ItemStack remainder = stack.copy(); + remainder.shrink(inserted); + player.setItemInHand(hand, player.hasInfiniteMaterials() ? before : remainder); + float filledRatio = (float) inserted / (float) before.getMaxStackSize(); + server.playSound(null, pos, TFSounds.JAR_INSERT.get(), SoundSource.BLOCKS, 1.0F, 0.7F + 0.5F * filledRatio); + server.gameEvent(player, GameEvent.BLOCK_CHANGE, pos); + } } private static void wiggle(ServerLevel server, BlockPos pos, MasonJarBlockEntity jar) { diff --git a/src/main/java/twilightforest/block/TFPortalBlock.java b/src/main/java/twilightforest/block/TFPortalBlock.java index 7fed86c92f..f5dc1d449f 100644 --- a/src/main/java/twilightforest/block/TFPortalBlock.java +++ b/src/main/java/twilightforest/block/TFPortalBlock.java @@ -158,7 +158,6 @@ public boolean tryToCreatePortal(ServerLevel level, BlockPos pos, ItemEntity cat MutableInt size = new MutableInt(0); if (recursivelyValidatePortal(level, pos, blocksChecked, size, state) && size.intValue() >= MIN_PORTAL_SIZE) { - if (!TFConfig.checkPortalPlacement) { boolean checkProgression = LandmarkUtil.isProgressionEnforced(level); if (!TFTeleporter.isSafeAround(level, pos, catalyst, checkProgression)) { diff --git a/src/main/java/twilightforest/block/TrophyPedestalBlock.java b/src/main/java/twilightforest/block/TrophyPedestalBlock.java index 59f85be487..1015a3b48a 100644 --- a/src/main/java/twilightforest/block/TrophyPedestalBlock.java +++ b/src/main/java/twilightforest/block/TrophyPedestalBlock.java @@ -3,6 +3,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; @@ -92,7 +93,7 @@ protected void neighborChanged(BlockState state, Level level, BlockPos pos, Bloc level.updateNeighbourForOutputSignal(pos, this); if (level.isClientSide() || state.getValue(ACTIVE) || !isTrophyOnTop(level, pos)) return; - if (LandmarkUtil.isProgressionEnforced(level)) { + if (LandmarkUtil.isProgressionEnforced((ServerLevel) level)) { if (this.areNearbyPlayersEligible(level, pos)) { this.doPedestalEffect(level, pos, state); } diff --git a/src/main/java/twilightforest/block/entity/DryingRackBlockEntity.java b/src/main/java/twilightforest/block/entity/DryingRackBlockEntity.java index fa96dba54c..4c4cdb08eb 100644 --- a/src/main/java/twilightforest/block/entity/DryingRackBlockEntity.java +++ b/src/main/java/twilightforest/block/entity/DryingRackBlockEntity.java @@ -169,59 +169,4 @@ public ClientboundBlockEntityDataPacket getUpdatePacket() { public CompoundTag getUpdateTag(HolderLookup.Provider registries) { return this.saveCustomOnly(registries); } - - //Based From MasonJarBlockEntity class's MasonJarItemStackHandler - public static class DryingRackHandler extends ItemStacksResourceHandler { - protected final DryingRackBlockEntity inventory; - - public DryingRackHandler(DryingRackBlockEntity blockEntity) { - super(1); - this.inventory = blockEntity; - } - - // Used for simple checks of what the one item is, without going through all the hoops. Used by the renderer and when saving contents to item - public ItemStack getItem() { - return this.stacks.getFirst().copy(); - } - - // Peeks at the stored item, without cloning it - private ItemStack peekItem() { - return this.stacks.getFirst(); - } - - // Used when syncing to client and when placing a jar that already has stored items - public void setItem(ItemStack itemStack) { - this.stacks.set(0, itemStack); - } - - @Override - public boolean isValid(int index, ItemResource resource) { - return resource.toStack().canFitInsideContainerItems(); - } - - @Override - public int extract(int index, ItemResource resource, int amount, TransactionContext transaction) { - if (this.inventory.drying) { - return 0; - } - int extracted = super.extract(index, resource, amount, transaction); - if (extracted > 0) { - this.inventory.setChanged(); - } - return extracted; - } - - @Override - public int insert(int index, ItemResource resource, int amount, TransactionContext transaction) { - int inserted = super.insert(index, resource, amount, transaction); - if (inserted > 0) { - this.inventory.setChanged(); - } - return inserted; - } - - public boolean isEmpty() { - return this.stacks.getFirst().isEmpty(); - } - } }