mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-18 07:53:07 +01:00
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 java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.sounds.SoundSource;
|
import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.entity.item.ItemEntity;
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.level.GameRules;
|
import net.minecraft.world.level.GameRules;
|
||||||
import net.minecraft.world.level.block.AirBlock;
|
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.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
|
@ -40,7 +36,7 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
if (destroyProgress == -1)
|
if (destroyProgress == -1)
|
||||||
destroyNextTick();
|
destroyNextTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lazyTick() {
|
public void lazyTick() {
|
||||||
super.lazyTick();
|
super.lazyTick();
|
||||||
|
@ -93,9 +89,9 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
return;
|
return;
|
||||||
if (getSpeed() == 0)
|
if (getSpeed() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
breakingPos = getBreakingPos();
|
breakingPos = getBreakingPos();
|
||||||
|
|
||||||
if (ticksUntilNextProgress < 0)
|
if (ticksUntilNextProgress < 0)
|
||||||
return;
|
return;
|
||||||
if (ticksUntilNextProgress-- > 0)
|
if (ticksUntilNextProgress-- > 0)
|
||||||
|
@ -114,7 +110,8 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
float breakSpeed = getBreakSpeed();
|
float breakSpeed = getBreakSpeed();
|
||||||
destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
|
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) {
|
if (destroyProgress >= 10) {
|
||||||
onBlockBroken(stateToBreak);
|
onBlockBroken(stateToBreak);
|
||||||
|
@ -133,28 +130,26 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBreakable(BlockState stateToBreak, float blockHardness) {
|
public static boolean isBreakable(BlockState stateToBreak, float blockHardness) {
|
||||||
return !(stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock
|
return !(stateToBreak.getMaterial()
|
||||||
|| blockHardness == -1);
|
.isLiquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onBlockBroken(BlockState stateToBreak) {
|
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);
|
Vec3 vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), level.random, .125f);
|
||||||
|
BlockHelper.destroyBlock(level, breakingPos, 1f, (stack) -> {
|
||||||
Block.getDrops(stateToBreak, (ServerLevel) level, breakingPos, tileentity).forEach((stack) -> {
|
if (stack.isEmpty())
|
||||||
if (!stack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)
|
return;
|
||||||
&& !level.restoringBlockSnapshots) {
|
if (!level.getGameRules()
|
||||||
ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack);
|
.getBoolean(GameRules.RULE_DOBLOCKDROPS))
|
||||||
itementity.setDefaultPickUpDelay();
|
return;
|
||||||
itementity.setDeltaMovement(Vec3.ZERO);
|
if (level.restoringBlockSnapshots)
|
||||||
level.addFreshEntity(itementity);
|
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() {
|
protected float getBreakSpeed() {
|
||||||
|
|
|
@ -104,7 +104,8 @@ public class HarvesterMovementBehaviour implements MovementBehaviour {
|
||||||
dropItem(context, stack);
|
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) {
|
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.actors.PloughBlock.PloughFakePlayer;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
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.content.logistics.trains.track.FakeTrackBlock;
|
||||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -105,6 +106,8 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
return false;
|
return false;
|
||||||
if (state.getBlock() instanceof NetherPortalBlock)
|
if (state.getBlock() instanceof NetherPortalBlock)
|
||||||
return false;
|
return false;
|
||||||
|
if (state.getBlock() instanceof ITrackBlock)
|
||||||
|
return true;
|
||||||
if (state.getBlock() instanceof FakeTrackBlock)
|
if (state.getBlock() instanceof FakeTrackBlock)
|
||||||
return false;
|
return false;
|
||||||
return state.getCollisionShape(world, breakingPos)
|
return state.getCollisionShape(world, breakingPos)
|
||||||
|
|
|
@ -304,13 +304,13 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
localVec = localVec.subtract(rotationOffset);
|
localVec = localVec.subtract(rotationOffset);
|
||||||
localVec = applyRotation(localVec, partialTicks);
|
localVec = applyRotation(localVec, partialTicks);
|
||||||
localVec = localVec.add(rotationOffset)
|
localVec = localVec.add(rotationOffset)
|
||||||
.add(getAnchorVec());
|
.add(getPrevAnchorVec());
|
||||||
return localVec;
|
return localVec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec3 toLocalVector(Vec3 globalVec, float partialTicks) {
|
public Vec3 toLocalVector(Vec3 globalVec, float partialTicks) {
|
||||||
Vec3 rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
Vec3 rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
globalVec = globalVec.subtract(getAnchorVec())
|
globalVec = globalVec.subtract(getPrevAnchorVec())
|
||||||
.subtract(rotationOffset);
|
.subtract(rotationOffset);
|
||||||
globalVec = reverseRotation(globalVec, partialTicks);
|
globalVec = reverseRotation(globalVec, partialTicks);
|
||||||
globalVec = globalVec.add(rotationOffset);
|
globalVec = globalVec.add(rotationOffset);
|
||||||
|
@ -519,6 +519,10 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
public Vec3 getAnchorVec() {
|
public Vec3 getAnchorVec() {
|
||||||
return position();
|
return position();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vec3 getPrevAnchorVec() {
|
||||||
|
return getPrevPositionVec();
|
||||||
|
}
|
||||||
|
|
||||||
public float getYawOffset() {
|
public float getYawOffset() {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -792,9 +796,11 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
public Vec3 getContactPointMotion(Vec3 globalContactPoint) {
|
public Vec3 getContactPointMotion(Vec3 globalContactPoint) {
|
||||||
if (prevPosInvalid)
|
if (prevPosInvalid)
|
||||||
return Vec3.ZERO;
|
return Vec3.ZERO;
|
||||||
|
|
||||||
Vec3 contactPoint = toGlobalVector(toLocalVector(globalContactPoint, 0), 1);
|
Vec3 contactPoint = toGlobalVector(toLocalVector(globalContactPoint, 0), 1);
|
||||||
return contactPoint.subtract(globalContactPoint)
|
Vec3 contraptionLocalMovement = contactPoint.subtract(globalContactPoint);
|
||||||
.add(position().subtract(getPrevPositionVec()));
|
Vec3 contraptionAnchorMovement = position().subtract(getPrevPositionVec());
|
||||||
|
return contraptionLocalMovement.add(contraptionAnchorMovement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canCollideWith(Entity e) {
|
public boolean canCollideWith(Entity e) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
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;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -86,10 +87,19 @@ public class ContraptionHandlerClient {
|
||||||
Vec3 origin = rayInputs.getFirst();
|
Vec3 origin = rayInputs.getFirst();
|
||||||
Vec3 target = rayInputs.getSecond();
|
Vec3 target = rayInputs.getSecond();
|
||||||
AABB aabb = new AABB(origin, target).inflate(16);
|
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);
|
BlockHitResult rayTraceResult = rayTraceContraption(origin, target, contraptionEntity);
|
||||||
if (rayTraceResult == null)
|
if (rayTraceResult == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -493,7 +493,14 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vec3 getAnchorVec() {
|
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
|
@Override
|
||||||
|
|
|
@ -11,6 +11,7 @@ import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
import net.minecraftforge.common.ForgeMod;
|
import net.minecraftforge.common.ForgeMod;
|
||||||
import net.minecraftforge.network.NetworkEvent.Context;
|
import net.minecraftforge.network.NetworkEvent.Context;
|
||||||
|
|
||||||
|
@ -54,7 +55,9 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
|
||||||
if (!(entityByID instanceof AbstractContraptionEntity))
|
if (!(entityByID instanceof AbstractContraptionEntity))
|
||||||
return;
|
return;
|
||||||
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
|
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))
|
if (!sender.hasLineOfSight(entityByID))
|
||||||
d -= 3;
|
d -= 3;
|
||||||
d *= d;
|
d *= d;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
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.PipeConnection.Flow;
|
||||||
import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock;
|
import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock;
|
||||||
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock;
|
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock;
|
||||||
|
@ -173,7 +174,8 @@ public class FluidPropagator {
|
||||||
return false;
|
return false;
|
||||||
if (VanillaFluidTargets.shouldPipesConnectTo(connectedState))
|
if (VanillaFluidTargets.shouldPipesConnectTo(connectedState))
|
||||||
return true;
|
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;
|
return false;
|
||||||
if (hasFluidCapability(reader, connectedPos, side.getOpposite()))
|
if (hasFluidCapability(reader, connectedPos, side.getOpposite()))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -40,9 +40,10 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource {
|
||||||
return sLevel.getScoreboard()
|
return sLevel.getScoreboard()
|
||||||
.getPlayerScores(objective)
|
.getPlayerScores(objective)
|
||||||
.stream()
|
.stream()
|
||||||
.limit(maxRows)
|
.map(score -> IntAttached.with(score.getScore(), Components.literal(score.getOwner())
|
||||||
.map(score -> IntAttached.with(score.getScore(), Components.literal(score.getOwner()).copy()))
|
.copy()))
|
||||||
.sorted(IntAttached.comparator());
|
.sorted(IntAttached.comparator())
|
||||||
|
.limit(maxRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableList<IntAttached<MutableComponent>> notFound(String objective) {
|
private ImmutableList<IntAttached<MutableComponent>> notFound(String objective) {
|
||||||
|
|
|
@ -84,12 +84,12 @@ public class TrainRelocationPacket extends SimplePacketBase {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!sender.position()
|
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");
|
Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from clicked pos");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!sender.position()
|
if (!sender.position()
|
||||||
.closerThan(cce.position(), 26 + cce.getBoundingBox()
|
.closerThan(cce.position(), 64 + cce.getBoundingBox()
|
||||||
.getXsize() / 2)) {
|
.getXsize() / 2)) {
|
||||||
Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from carriage entity");
|
Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from carriage entity");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -29,6 +29,9 @@ import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class ScheduleRuntime {
|
public class ScheduleRuntime {
|
||||||
|
|
||||||
|
private static final int TBD = -1;
|
||||||
|
private static final int INVALID = -2;
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT
|
PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT
|
||||||
}
|
}
|
||||||
|
@ -129,7 +132,7 @@ public class ScheduleRuntime {
|
||||||
destinationReached();
|
destinationReached();
|
||||||
return;
|
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;
|
state = State.IN_TRANSIT;
|
||||||
ticksInTransit = 0;
|
ticksInTransit = 0;
|
||||||
}
|
}
|
||||||
|
@ -231,7 +234,7 @@ public class ScheduleRuntime {
|
||||||
isAutoSchedule = auto;
|
isAutoSchedule = auto;
|
||||||
train.status.newSchedule();
|
train.status.newSchedule();
|
||||||
predictionTicks = new ArrayList<>();
|
predictionTicks = new ArrayList<>();
|
||||||
schedule.entries.forEach($ -> predictionTicks.add(-1));
|
schedule.entries.forEach($ -> predictionTicks.add(TBD));
|
||||||
displayLinkUpdateRequested = true;
|
displayLinkUpdateRequested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,8 +272,10 @@ public class ScheduleRuntime {
|
||||||
if (currentStation != null)
|
if (currentStation != null)
|
||||||
predictions.add(createPrediction(current, currentStation.name, currentTitle, 0));
|
predictions.add(createPrediction(current, currentStation.name, currentTitle, 0));
|
||||||
int departureTime = estimateStayDuration(current);
|
int departureTime = estimateStayDuration(current);
|
||||||
if (departureTime == -1)
|
if (departureTime == INVALID)
|
||||||
accumulatedTime = -1;
|
accumulatedTime = INVALID;
|
||||||
|
else
|
||||||
|
accumulatedTime += departureTime;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
GlobalStation destination = train.navigation.destination;
|
GlobalStation destination = train.navigation.destination;
|
||||||
|
@ -292,10 +297,10 @@ public class ScheduleRuntime {
|
||||||
predictions.add(createPrediction(current, destination.name, currentTitle, accumulatedTime));
|
predictions.add(createPrediction(current, destination.name, currentTitle, accumulatedTime));
|
||||||
|
|
||||||
int departureTime = estimateStayDuration(current);
|
int departureTime = estimateStayDuration(current);
|
||||||
if (departureTime != -1)
|
if (departureTime != INVALID)
|
||||||
accumulatedTime += departureTime;
|
accumulatedTime += departureTime;
|
||||||
if (departureTime == -1)
|
else
|
||||||
accumulatedTime = -1;
|
accumulatedTime = INVALID;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
predictForEntry(current, currentTitle, accumulatedTime, predictions);
|
predictForEntry(current, currentTitle, accumulatedTime, predictions);
|
||||||
|
@ -327,47 +332,56 @@ public class ScheduleRuntime {
|
||||||
return accumulatedTime;
|
return accumulatedTime;
|
||||||
if (predictionTicks.size() <= currentEntry)
|
if (predictionTicks.size() <= currentEntry)
|
||||||
return accumulatedTime;
|
return accumulatedTime;
|
||||||
if (accumulatedTime == -1) {
|
|
||||||
|
int departureTime = estimateStayDuration(index);
|
||||||
|
|
||||||
|
if (accumulatedTime < 0) {
|
||||||
predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime));
|
predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime));
|
||||||
return -1;
|
return Math.min(accumulatedTime, departureTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
int predictedTime = predictionTicks.get(index);
|
int predictedTime = predictionTicks.get(index);
|
||||||
int departureTime = estimateStayDuration(index);
|
accumulatedTime += predictedTime;
|
||||||
|
|
||||||
if (predictedTime == -1)
|
if (predictedTime == TBD)
|
||||||
accumulatedTime = -1;
|
accumulatedTime = TBD;
|
||||||
else {
|
|
||||||
accumulatedTime += predictedTime;
|
|
||||||
if (departureTime != -1)
|
|
||||||
accumulatedTime += departureTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime));
|
predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime));
|
||||||
|
|
||||||
if (departureTime == -1)
|
if (accumulatedTime != TBD)
|
||||||
return -1;
|
accumulatedTime += departureTime;
|
||||||
|
|
||||||
|
if (departureTime == INVALID)
|
||||||
|
accumulatedTime = INVALID;
|
||||||
|
|
||||||
return accumulatedTime;
|
return accumulatedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int estimateStayDuration(int index) {
|
private int estimateStayDuration(int index) {
|
||||||
if (index >= schedule.entries.size()) {
|
if (index >= schedule.entries.size()) {
|
||||||
if (!schedule.cyclic)
|
if (!schedule.cyclic)
|
||||||
return 100000;
|
return INVALID;
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduleEntry scheduleEntry = schedule.entries.get(index);
|
ScheduleEntry scheduleEntry = schedule.entries.get(index);
|
||||||
for (List<ScheduleWaitCondition> list : scheduleEntry.conditions)
|
Columns: for (List<ScheduleWaitCondition> list : scheduleEntry.conditions) {
|
||||||
for (ScheduleWaitCondition condition : list)
|
int total = 0;
|
||||||
if (condition instanceof ScheduledDelay wait)
|
for (ScheduleWaitCondition condition : list) {
|
||||||
return wait.totalWaitTicks();
|
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) {
|
private TrainDeparturePrediction createPrediction(int index, String destination, String currentTitle, int time) {
|
||||||
|
if (time == INVALID)
|
||||||
|
return null;
|
||||||
|
|
||||||
int size = schedule.entries.size();
|
int size = schedule.entries.size();
|
||||||
if (index >= size) {
|
if (index >= size) {
|
||||||
if (!schedule.cyclic)
|
if (!schedule.cyclic)
|
||||||
|
@ -422,7 +436,7 @@ public class ScheduleRuntime {
|
||||||
|
|
||||||
int[] readTransits = tag.getIntArray("TransitTimes");
|
int[] readTransits = tag.getIntArray("TransitTimes");
|
||||||
if (schedule != null) {
|
if (schedule != null) {
|
||||||
schedule.entries.forEach($ -> predictionTicks.add(-1));
|
schedule.entries.forEach($ -> predictionTicks.add(TBD));
|
||||||
if (readTransits.length == schedule.entries.size())
|
if (readTransits.length == schedule.entries.size())
|
||||||
for (int i = 0; i < readTransits.length; i++)
|
for (int i = 0; i < readTransits.length; i++)
|
||||||
predictionTicks.set(i, readTransits[i]);
|
predictionTicks.set(i, readTransits[i]);
|
||||||
|
|
|
@ -31,7 +31,7 @@ import net.minecraft.world.phys.Vec3;
|
||||||
public class DumpRailwaysCommand {
|
public class DumpRailwaysCommand {
|
||||||
|
|
||||||
static ArgumentBuilder<CommandSourceStack, ?> register() {
|
static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||||
return Commands.literal("dumpRailways")
|
return Commands.literal("trains")
|
||||||
.requires(cs -> cs.hasPermission(2))
|
.requires(cs -> cs.hasPermission(2))
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
CommandSourceStack source = ctx.getSource();
|
CommandSourceStack source = ctx.getSource();
|
||||||
|
@ -52,7 +52,7 @@ public class DumpRailwaysCommand {
|
||||||
int orange = 0xFFAD60;
|
int orange = 0xFFAD60;
|
||||||
|
|
||||||
chat.accept("", white);
|
chat.accept("", white);
|
||||||
chat.accept("-+------<< Railways Summary: >>------+-", white);
|
chat.accept("-+------<< Train Summary: >>------+-", white);
|
||||||
int graphCount = railways.trackNetworks.size();
|
int graphCount = railways.trackNetworks.size();
|
||||||
chat.accept("Track Networks: " + graphCount, blue);
|
chat.accept("Track Networks: " + graphCount, blue);
|
||||||
chat.accept("Signal Groups: " + railways.signalEdgeGroups.size(), 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.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
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.BlockGetter;
|
||||||
import net.minecraft.world.level.GameRules;
|
import net.minecraft.world.level.GameRules;
|
||||||
import net.minecraft.world.level.Level;
|
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.BedBlock;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
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.SlimeBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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.LevelChunk;
|
||||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.level.material.Material;
|
||||||
import net.minecraftforge.common.IPlantable;
|
import net.minecraftforge.common.IPlantable;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.event.world.BlockEvent;
|
import net.minecraftforge.event.world.BlockEvent;
|
||||||
|
@ -155,9 +159,11 @@ public class BlockHelper {
|
||||||
float effectChance, Consumer<ItemStack> droppedItemCallback) {
|
float effectChance, Consumer<ItemStack> droppedItemCallback) {
|
||||||
FluidState fluidState = world.getFluidState(pos);
|
FluidState fluidState = world.getFluidState(pos);
|
||||||
BlockState state = world.getBlockState(pos);
|
BlockState state = world.getBlockState(pos);
|
||||||
|
|
||||||
if (world.random.nextFloat() < effectChance)
|
if (world.random.nextFloat() < effectChance)
|
||||||
world.levelEvent(2001, pos, Block.getId(state));
|
world.levelEvent(2001, pos, Block.getId(state));
|
||||||
BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||||
|
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player);
|
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player);
|
||||||
MinecraftForge.EVENT_BUS.post(event);
|
MinecraftForge.EVENT_BUS.post(event);
|
||||||
|
@ -177,9 +183,25 @@ public class BlockHelper {
|
||||||
&& (player == null || !player.isCreative())) {
|
&& (player == null || !player.isCreative())) {
|
||||||
for (ItemStack itemStack : Block.getDrops(state, (ServerLevel) world, pos, tileentity, player, usedTool))
|
for (ItemStack itemStack : Block.getDrops(state, (ServerLevel) world, pos, tileentity, player, usedTool))
|
||||||
droppedItemCallback.accept(itemStack);
|
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);
|
state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
world.setBlockAndUpdate(pos, fluidState.createLegacyBlock());
|
world.setBlockAndUpdate(pos, fluidState.createLegacyBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue