The Eternal Offset
- Fixed Drills not leaving water sources when breaking ice blocks - Fixed Ploughs not able to break track blocks - Fixed Harvester replanting crops in invalid locations - Fixed Train Relocation not always triggering when targeting long bends - Display boards no longer predict trains behind wait conditions other than "timed delay" - Fixed scoreboard and deathcount display sources cropping entries before sorting - /create dumpRailways -> /create trains - Pipe flows are no longer stopped if the blocking state is considered #fan_transparent (-> fixes 1.19 mangrove root) - Fixed contraption interaction not firing when it happens far away from the contraptions origin - Fixed inaccurate contact point motion for collisions with oriented contraptions
This commit is contained in:
parent
aeee9f8793
commit
bf06e59938
13 changed files with 137 additions and 73 deletions
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<AbstractContraptionEntity> intersectingContraptions =
|
||||
mc.level.getEntitiesOfClass(AbstractContraptionEntity.class, aabb);
|
||||
|
||||
for (AbstractContraptionEntity contraptionEntity : intersectingContraptions) {
|
||||
Collection<WeakReference<AbstractContraptionEntity>> contraptions =
|
||||
ContraptionHandler.loadedContraptions.get(mc.level)
|
||||
.values();
|
||||
|
||||
for (WeakReference<AbstractContraptionEntity> 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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<IntAttached<MutableComponent>> notFound(String objective) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<ScheduleWaitCondition> list : scheduleEntry.conditions)
|
||||
for (ScheduleWaitCondition condition : list)
|
||||
if (condition instanceof ScheduledDelay wait)
|
||||
return wait.totalWaitTicks();
|
||||
Columns: for (List<ScheduleWaitCondition> 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]);
|
||||
|
|
|
@ -31,7 +31,7 @@ import net.minecraft.world.phys.Vec3;
|
|||
public class DumpRailwaysCommand {
|
||||
|
||||
static ArgumentBuilder<CommandSourceStack, ?> 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);
|
||||
|
|
|
@ -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<ItemStack> 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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue