diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java index dee22e4ba..1162e9835 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java @@ -3,23 +3,19 @@ package com.simibubi.create.content.contraptions.components.actors; import java.util.concurrent.atomic.AtomicInteger; import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; -import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.block.AirBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { @@ -40,7 +36,7 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { if (destroyProgress == -1) destroyNextTick(); } - + @Override public void lazyTick() { super.lazyTick(); @@ -93,9 +89,9 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { return; if (getSpeed() == 0) return; - + breakingPos = getBreakingPos(); - + if (ticksUntilNextProgress < 0) return; if (ticksUntilNextProgress-- > 0) @@ -114,7 +110,8 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { float breakSpeed = getBreakSpeed(); destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); - level.playSound(null, worldPosition, stateToBreak.getSoundType().getHitSound(), SoundSource.NEUTRAL, .25f, 1); + level.playSound(null, worldPosition, stateToBreak.getSoundType() + .getHitSound(), SoundSource.NEUTRAL, .25f, 1); if (destroyProgress >= 10) { onBlockBroken(stateToBreak); @@ -133,28 +130,26 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { } public static boolean isBreakable(BlockState stateToBreak, float blockHardness) { - return !(stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock - || blockHardness == -1); + return !(stateToBreak.getMaterial() + .isLiquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1); } public void onBlockBroken(BlockState stateToBreak) { - FluidState FluidState = level.getFluidState(breakingPos); - level.levelEvent(2001, breakingPos, Block.getId(stateToBreak)); - BlockEntity tileentity = stateToBreak.hasBlockEntity() ? level.getBlockEntity(breakingPos) : null; Vec3 vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), level.random, .125f); - - Block.getDrops(stateToBreak, (ServerLevel) level, breakingPos, tileentity).forEach((stack) -> { - if (!stack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) - && !level.restoringBlockSnapshots) { - ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack); - itementity.setDefaultPickUpDelay(); - itementity.setDeltaMovement(Vec3.ZERO); - level.addFreshEntity(itementity); - } + BlockHelper.destroyBlock(level, breakingPos, 1f, (stack) -> { + if (stack.isEmpty()) + return; + if (!level.getGameRules() + .getBoolean(GameRules.RULE_DOBLOCKDROPS)) + return; + if (level.restoringBlockSnapshots) + return; + + ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack); + itementity.setDefaultPickUpDelay(); + itementity.setDeltaMovement(Vec3.ZERO); + level.addFreshEntity(itementity); }); - if (level instanceof ServerLevel) - stateToBreak.spawnAfterBreak((ServerLevel) level, breakingPos, ItemStack.EMPTY); - level.setBlock(breakingPos, FluidState.createLegacyBlock(), 3); } protected float getBreakSpeed() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java index 9360166dc..53e6acefc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java @@ -104,7 +104,8 @@ public class HarvesterMovementBehaviour implements MovementBehaviour { dropItem(context, stack); }); - world.setBlockAndUpdate(pos, cutCrop(world, pos, stateVisited)); + BlockState cutCrop = cutCrop(world, pos, stateVisited); + world.setBlockAndUpdate(pos, cutCrop.canSurvive(world, pos) ? cutCrop : Blocks.AIR.defaultBlockState()); } public boolean isValidCrop(Level world, BlockPos pos, BlockState state) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java index 1cca39d6b..9f95c0652 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.actors; import com.simibubi.create.content.contraptions.components.actors.PloughBlock.PloughFakePlayer; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.logistics.trains.ITrackBlock; import com.simibubi.create.content.logistics.trains.track.FakeTrackBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.utility.VecHelper; @@ -105,6 +106,8 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { return false; if (state.getBlock() instanceof NetherPortalBlock) return false; + if (state.getBlock() instanceof ITrackBlock) + return true; if (state.getBlock() instanceof FakeTrackBlock) return false; return state.getCollisionShape(world, breakingPos) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index 9853a7371..cc31b9b52 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -304,13 +304,13 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit localVec = localVec.subtract(rotationOffset); localVec = applyRotation(localVec, partialTicks); localVec = localVec.add(rotationOffset) - .add(getAnchorVec()); + .add(getPrevAnchorVec()); return localVec; } public Vec3 toLocalVector(Vec3 globalVec, float partialTicks) { Vec3 rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); - globalVec = globalVec.subtract(getAnchorVec()) + globalVec = globalVec.subtract(getPrevAnchorVec()) .subtract(rotationOffset); globalVec = reverseRotation(globalVec, partialTicks); globalVec = globalVec.add(rotationOffset); @@ -519,6 +519,10 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit public Vec3 getAnchorVec() { return position(); } + + public Vec3 getPrevAnchorVec() { + return getPrevPositionVec(); + } public float getYawOffset() { return 0; @@ -792,9 +796,11 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit public Vec3 getContactPointMotion(Vec3 globalContactPoint) { if (prevPosInvalid) return Vec3.ZERO; + Vec3 contactPoint = toGlobalVector(toLocalVector(globalContactPoint, 0), 1); - return contactPoint.subtract(globalContactPoint) - .add(position().subtract(getPrevPositionVec())); + Vec3 contraptionLocalMovement = contactPoint.subtract(globalContactPoint); + Vec3 contraptionAnchorMovement = position().subtract(getPrevPositionVec()); + return contraptionLocalMovement.add(contraptionAnchorMovement); } public boolean canCollideWith(Entity e) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java index f9d40b9cb..0ebf07fee 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; -import java.util.List; +import java.lang.ref.WeakReference; +import java.util.Collection; import javax.annotation.Nullable; @@ -86,10 +87,19 @@ public class ContraptionHandlerClient { Vec3 origin = rayInputs.getFirst(); Vec3 target = rayInputs.getSecond(); AABB aabb = new AABB(origin, target).inflate(16); - List intersectingContraptions = - mc.level.getEntitiesOfClass(AbstractContraptionEntity.class, aabb); - for (AbstractContraptionEntity contraptionEntity : intersectingContraptions) { + Collection> contraptions = + ContraptionHandler.loadedContraptions.get(mc.level) + .values(); + + for (WeakReference ref : contraptions) { + AbstractContraptionEntity contraptionEntity = ref.get(); + if (contraptionEntity == null) + continue; + if (!contraptionEntity.getBoundingBox() + .intersects(aabb)) + continue; + BlockHitResult rayTraceResult = rayTraceContraption(origin, target, contraptionEntity); if (rayTraceResult == null) continue; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java index 9abd65cf4..cd140b891 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java @@ -493,7 +493,14 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { @Override public Vec3 getAnchorVec() { - return new Vec3(getX() - .5, getY(), getZ() - .5); + Vec3 anchorVec = super.getAnchorVec(); + return anchorVec.subtract(.5, 0, .5); + } + + @Override + public Vec3 getPrevAnchorVec() { + Vec3 prevAnchorVec = super.getPrevAnchorVec(); + return prevAnchorVec.subtract(.5, 0, .5); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java index 557fc3ace..4d4492ca1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java @@ -11,6 +11,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.network.NetworkEvent.Context; @@ -54,7 +55,9 @@ public class ContraptionInteractionPacket extends SimplePacketBase { if (!(entityByID instanceof AbstractContraptionEntity)) return; AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue() + 10; + AABB bb = contraptionEntity.getBoundingBox(); + double boundsExtra = Math.max(bb.getXsize(), bb.getYsize()); + double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue() + 10 + boundsExtra; if (!sender.hasLineOfSight(entityByID)) d -= 3; d *= d; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java index 5451e001b..0ac0e4274 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java @@ -8,6 +8,7 @@ import java.util.Set; import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow; import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock; import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; @@ -173,7 +174,8 @@ public class FluidPropagator { return false; if (VanillaFluidTargets.shouldPipesConnectTo(connectedState)) return true; - if (BlockHelper.hasBlockSolidSide(connectedState, reader, connectedPos, side.getOpposite())) + if (BlockHelper.hasBlockSolidSide(connectedState, reader, connectedPos, side.getOpposite()) + && !AllBlockTags.FAN_TRANSPARENT.matches(connectedState)) return false; if (hasFluidCapability(reader, connectedPos, side.getOpposite())) return false; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java index 70614052c..94947ac35 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java @@ -40,9 +40,10 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource { return sLevel.getScoreboard() .getPlayerScores(objective) .stream() - .limit(maxRows) - .map(score -> IntAttached.with(score.getScore(), Components.literal(score.getOwner()).copy())) - .sorted(IntAttached.comparator()); + .map(score -> IntAttached.with(score.getScore(), Components.literal(score.getOwner()) + .copy())) + .sorted(IntAttached.comparator()) + .limit(maxRows); } private ImmutableList> notFound(String objective) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java index 614ec29a3..fe0d6edde 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java @@ -84,12 +84,12 @@ public class TrainRelocationPacket extends SimplePacketBase { return; if (!sender.position() - .closerThan(Vec3.atCenterOf(pos), 26)) { + .closerThan(Vec3.atCenterOf(pos), 64)) { Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from clicked pos"); return; } if (!sender.position() - .closerThan(cce.position(), 26 + cce.getBoundingBox() + .closerThan(cce.position(), 64 + cce.getBoundingBox() .getXsize() / 2)) { Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from carriage entity"); return; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java index 6df3d0411..f7bc8a340 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java @@ -29,6 +29,9 @@ import net.minecraft.world.level.Level; public class ScheduleRuntime { + private static final int TBD = -1; + private static final int INVALID = -2; + public enum State { PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT } @@ -129,7 +132,7 @@ public class ScheduleRuntime { destinationReached(); return; } - if (train.navigation.startNavigation(nextStation, Double.MAX_VALUE, false) != -1) { + if (train.navigation.startNavigation(nextStation, Double.MAX_VALUE, false) != TBD) { state = State.IN_TRANSIT; ticksInTransit = 0; } @@ -231,7 +234,7 @@ public class ScheduleRuntime { isAutoSchedule = auto; train.status.newSchedule(); predictionTicks = new ArrayList<>(); - schedule.entries.forEach($ -> predictionTicks.add(-1)); + schedule.entries.forEach($ -> predictionTicks.add(TBD)); displayLinkUpdateRequested = true; } @@ -269,8 +272,10 @@ public class ScheduleRuntime { if (currentStation != null) predictions.add(createPrediction(current, currentStation.name, currentTitle, 0)); int departureTime = estimateStayDuration(current); - if (departureTime == -1) - accumulatedTime = -1; + if (departureTime == INVALID) + accumulatedTime = INVALID; + else + accumulatedTime += departureTime; } else { GlobalStation destination = train.navigation.destination; @@ -292,10 +297,10 @@ public class ScheduleRuntime { predictions.add(createPrediction(current, destination.name, currentTitle, accumulatedTime)); int departureTime = estimateStayDuration(current); - if (departureTime != -1) + if (departureTime != INVALID) accumulatedTime += departureTime; - if (departureTime == -1) - accumulatedTime = -1; + else + accumulatedTime = INVALID; } else predictForEntry(current, currentTitle, accumulatedTime, predictions); @@ -327,47 +332,56 @@ public class ScheduleRuntime { return accumulatedTime; if (predictionTicks.size() <= currentEntry) return accumulatedTime; - if (accumulatedTime == -1) { + + int departureTime = estimateStayDuration(index); + + if (accumulatedTime < 0) { predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime)); - return -1; + return Math.min(accumulatedTime, departureTime); } int predictedTime = predictionTicks.get(index); - int departureTime = estimateStayDuration(index); + accumulatedTime += predictedTime; - if (predictedTime == -1) - accumulatedTime = -1; - else { - accumulatedTime += predictedTime; - if (departureTime != -1) - accumulatedTime += departureTime; - } + if (predictedTime == TBD) + accumulatedTime = TBD; predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime)); - if (departureTime == -1) - return -1; - + if (accumulatedTime != TBD) + accumulatedTime += departureTime; + + if (departureTime == INVALID) + accumulatedTime = INVALID; + return accumulatedTime; } private int estimateStayDuration(int index) { if (index >= schedule.entries.size()) { if (!schedule.cyclic) - return 100000; + return INVALID; index = 0; } ScheduleEntry scheduleEntry = schedule.entries.get(index); - for (List list : scheduleEntry.conditions) - for (ScheduleWaitCondition condition : list) - if (condition instanceof ScheduledDelay wait) - return wait.totalWaitTicks(); + Columns: for (List list : scheduleEntry.conditions) { + int total = 0; + for (ScheduleWaitCondition condition : list) { + if (!(condition instanceof ScheduledDelay wait)) + continue Columns; + total += wait.totalWaitTicks(); + } + return total; + } - return 5; // TODO properly ask conditions for time prediction + return INVALID; } private TrainDeparturePrediction createPrediction(int index, String destination, String currentTitle, int time) { + if (time == INVALID) + return null; + int size = schedule.entries.size(); if (index >= size) { if (!schedule.cyclic) @@ -422,7 +436,7 @@ public class ScheduleRuntime { int[] readTransits = tag.getIntArray("TransitTimes"); if (schedule != null) { - schedule.entries.forEach($ -> predictionTicks.add(-1)); + schedule.entries.forEach($ -> predictionTicks.add(TBD)); if (readTransits.length == schedule.entries.size()) for (int i = 0; i < readTransits.length; i++) predictionTicks.set(i, readTransits[i]); diff --git a/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java b/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java index 64139ca20..90fa16b04 100644 --- a/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/DumpRailwaysCommand.java @@ -31,7 +31,7 @@ import net.minecraft.world.phys.Vec3; public class DumpRailwaysCommand { static ArgumentBuilder register() { - return Commands.literal("dumpRailways") + return Commands.literal("trains") .requires(cs -> cs.hasPermission(2)) .executes(ctx -> { CommandSourceStack source = ctx.getSource(); @@ -52,7 +52,7 @@ public class DumpRailwaysCommand { int orange = 0xFFAD60; chat.accept("", white); - chat.accept("-+------<< Railways Summary: >>------+-", white); + chat.accept("-+------<< Train Summary: >>------+-", white); int graphCount = railways.trackNetworks.size(); chat.accept("Track Networks: " + graphCount, blue); chat.accept("Signal Groups: " + railways.signalEdgeGroups.size(), blue); diff --git a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java index f2cb5d081..29b910212 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java @@ -24,6 +24,8 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; @@ -31,6 +33,7 @@ import net.minecraft.world.level.block.BaseRailBlock; import net.minecraft.world.level.block.BedBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.IceBlock; import net.minecraft.world.level.block.SlimeBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -40,6 +43,7 @@ import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Material; import net.minecraftforge.common.IPlantable; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.BlockEvent; @@ -155,9 +159,11 @@ public class BlockHelper { float effectChance, Consumer droppedItemCallback) { FluidState fluidState = world.getFluidState(pos); BlockState state = world.getBlockState(pos); + if (world.random.nextFloat() < effectChance) world.levelEvent(2001, pos, Block.getId(state)); BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null; + if (player != null) { BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); MinecraftForge.EVENT_BUS.post(event); @@ -177,9 +183,25 @@ public class BlockHelper { && (player == null || !player.isCreative())) { for (ItemStack itemStack : Block.getDrops(state, (ServerLevel) world, pos, tileentity, player, usedTool)) droppedItemCallback.accept(itemStack); + + // Simulating IceBlock#playerDestroy. Not calling method directly as it would drop item + // entities as a side-effect + if (state.getBlock() instanceof IceBlock + && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, usedTool) == 0) { + if (world.dimensionType() + .ultraWarm()) + return; + + Material material = world.getBlockState(pos.below()) + .getMaterial(); + if (material.blocksMotion() || material.isLiquid()) + world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState()); + return; + } + state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY); } - + world.setBlockAndUpdate(pos, fluidState.createLegacyBlock()); }