Down the Checklist, Part II

- Fake Tracks no longer replace lava or flowing water
- Fixed passengers dismounting from contraptions teleporting into the ceiling for a tick
-  Fixed serverside collision mask not updating when doors open on a contraption
- Signals can now be seen from further away
- Fixed some model loading logspam
- Fixed curved tracks dropping items when destroyed in creative mode
- Fixed curved tracks sometimes reappearing after being broken once
- Fixed Fluid pipes not rendering a rim when facing a pump from its side
- Fixed Super glue not always taking effect when intersecting with another box
- Fixed Super glue blocking entities travelling on a belt
- Fixed Super glue disintegrating when pushed by a vanilla piston
- Fixed Tracks placed up against a solid wall placing as ascending slopes
- Fixed movement actors switching dimensions stalling indefinitely
- Fixed kinetic components showing speed requirement popups when moving very slowly
- Fixed display boards not always connecting properly when placed with placement assist
- Fixed display boards getting caught in kinetic ghost power loops
- Fixed display boards loading in with jumbled text
- Fixed players unable to hand schedules to conductors while seated
This commit is contained in:
simibubi 2022-06-21 19:43:53 +02:00
parent 08c67cc4bc
commit cdadd12b41
29 changed files with 218 additions and 117 deletions

View file

@ -208,6 +208,7 @@ d13940ed213d7acbc6ebe3bdd21175ef89e4d613 assets/create/blockstates/encased_fluid
8bc601601858042859cd834e7fa391a8235d3d75 assets/create/blockstates/exposed_copper_tile_slab.json
8a87e42262f3f161b0e6fe10b795ff00eccf768f assets/create/blockstates/exposed_copper_tile_stairs.json
fb41aa1a0828c9256b3f886fdcb55bb54252ba09 assets/create/blockstates/exposed_copper_tiles.json
7a2259a71fbbbb9491fc1e6a9c935bc9fef14042 assets/create/blockstates/fake_track.json
bb74442749b6bd688d45d919b541dbd66bbeb18a assets/create/blockstates/fluid_pipe.json
f0eaab18e16c4f3f65ebf3b55b08f0dc445720fe assets/create/blockstates/fluid_tank.json
5408d92ab02af86539ac42971d4033545970bb3a assets/create/blockstates/fluid_valve.json
@ -5022,7 +5023,7 @@ e98ea64ba1a6780456e135628239251add737f2e data/create/recipes/deploying/waxed_wea
72110302ade0a3b7d82c5e778c63e0b457a2470b data/create/recipes/dripstone_pillar_from_dripstone_block_stonecutting.json
27d9bf05a610447e90314e658dbbcd191f378fc9 data/create/recipes/dripstone_pillar_from_stone_types_dripstone_stonecutting.json
d81ceba2946286d374801e698a4ca2116395cbad data/create/recipes/emptying/builders_tea.json
d12905d723363a6a053f7925af576c416a7b0aee data/create/recipes/emptying/compat/farmersdelight/milk_bottle.json
c26d003e921720308c05ad7b9f3cb57de94a10a8 data/create/recipes/emptying/compat/farmersdelight/milk_bottle.json
20b7c7c62fa2e33199e08188dd8836844a6d9cfd data/create/recipes/emptying/honey_bottle.json
dfc1bbb05a4eca31f47d1b25c5975866cb4b61f9 data/create/recipes/exposed_copper_shingle_slab.json
4e1cfc70d9089d90adbed4bef37b36e66751f5db data/create/recipes/exposed_copper_shingle_slab_from_exposed_copper_shingles_stonecutting.json
@ -5035,7 +5036,7 @@ c2f40d447fbac4b4975e578fe32635658b73ebf7 data/create/recipes/exposed_copper_tile
133e79f78a7f2c2f63ac7695d2be57d56e8955f4 data/create/recipes/filling/blaze_cake.json
642e96ce5dd2f31e7a33c6ef4060eecb0bf2aa86 data/create/recipes/filling/builders_tea.json
1367357fc36adc4b67467d90589ef91e657380a4 data/create/recipes/filling/chocolate_glazed_berries.json
efeb30ea6e9a7dca0d8fc388fd9c96ee70078537 data/create/recipes/filling/compat/farmersdelight/milk_bottle.json
0e79248178f8c1690b4e5a5ad2ffaf63711ad3c7 data/create/recipes/filling/compat/farmersdelight/milk_bottle.json
5bec6c2068a3c1005810d18bd45ce916389b5423 data/create/recipes/filling/glowstone.json
5eb6227ccb6fa940b662d3ec029c3bd61fe61c8d data/create/recipes/filling/grass_block.json
244f27eadefefbc966ac384ac087c57d19484321 data/create/recipes/filling/gunpowder.json

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "create:block/fake_track"
}
}
}

View file

@ -13,5 +13,11 @@
"fluid": "minecraft:milk",
"amount": 250
}
],
"conditions": [
{
"modid": "farmersdelight",
"type": "forge:mod_loaded"
}
]
}

View file

@ -13,5 +13,11 @@
{
"item": "farmersdelight:milk_bottle"
}
],
"conditions": [
{
"modid": "farmersdelight",
"type": "forge:mod_loaded"
}
]
}

View file

@ -1509,8 +1509,8 @@ public class AllBlocks {
.nonSolid()
.replaceable()
.build())
.blockstate((c, p) -> p.models()
.withExistingParent(c.getName(), p.mcLoc("block/air")))
.blockstate((c, p) -> p.simpleBlock(c.get(), p.models()
.withExistingParent(c.getName(), p.mcLoc("block/air"))))
.lang("Track Marker for Maps")
.register();

View file

@ -141,7 +141,7 @@ public interface IRotate extends IWrenchable {
public Axis getRotationAxis(BlockState state);
public default SpeedLevel getMinimumRequiredSpeedLevel() {
return SpeedLevel.SLOW;
return SpeedLevel.NONE;
}
public default boolean hideStressImpact() {

View file

@ -44,7 +44,7 @@ public abstract class KineticBlock extends Block implements IRotate {
kineticTileEntity.preventSpeedUpdate = 2;
}
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
return false;
@ -57,7 +57,8 @@ public abstract class KineticBlock extends Block implements IRotate {
}
@Override
public void updateIndirectNeighbourShapes(BlockState stateIn, LevelAccessor worldIn, BlockPos pos, int flags, int count) {
public void updateIndirectNeighbourShapes(BlockState stateIn, LevelAccessor worldIn, BlockPos pos, int flags,
int count) {
if (worldIn.isClientSide())
return;
@ -66,10 +67,8 @@ public abstract class KineticBlock extends Block implements IRotate {
return;
KineticTileEntity kte = (KineticTileEntity) tileEntity;
if (kte.preventSpeedUpdate > 0) {
kte.preventSpeedUpdate--;
if (kte.preventSpeedUpdate > 0)
return;
}
// Remove previous information when block is added
kte.warnOfMovement();

View file

@ -93,6 +93,8 @@ public class KineticTileEntity extends SmartTileEntity
super.tick();
effects.tick();
preventSpeedUpdate = 0;
if (level.isClientSide) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio());

View file

@ -144,8 +144,10 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour {
CompoundTag data = context.data;
if (context.world.isClientSide)
return;
if (!data.contains("BreakingPos"))
if (!data.contains("BreakingPos")) {
context.stall = false;
return;
}
if (context.relativeMotion.equals(Vec3.ZERO)) {
context.stall = false;
return;

View file

@ -44,6 +44,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
@ -167,6 +168,15 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
new ContraptionSeatMappingPacket(getId(), contraption.getSeatMapping()));
}
@Override
public Vec3 getDismountLocationForPassenger(LivingEntity pLivingEntity) {
Vec3 loc = super.getDismountLocationForPassenger(pLivingEntity);
CompoundTag data = pLivingEntity.getPersistentData();
if (!data.contains("ContraptionDismountLocation"))
return loc;
return VecHelper.readNBT(data.getList("ContraptionDismountLocation", Tag.TAG_DOUBLE));
}
@Override
public void positionRider(Entity passenger, MoveFunction callback) {
if (!hasPassenger(passenger))

View file

@ -47,6 +47,7 @@ import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.level.portal.PortalInfo;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
@ -66,7 +67,8 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
for (SuperGlueEntity glueEntity : cached)
if (glueEntity.contains(blockPos) && glueEntity.contains(targetPos))
return true;
for (SuperGlueEntity glueEntity : level.getEntitiesOfClass(SuperGlueEntity.class, span(blockPos, targetPos))) {
for (SuperGlueEntity glueEntity : level.getEntitiesOfClass(SuperGlueEntity.class,
span(blockPos, targetPos).inflate(16))) {
if (!glueEntity.contains(blockPos) || !glueEntity.contains(targetPos))
continue;
if (cached != null)
@ -288,12 +290,17 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
return getBoundingBox().contains(Vec3.atCenterOf(pos));
}
@Override
public PushReaction getPistonPushReaction() {
return PushReaction.IGNORE;
}
@Override
public PortalInfo findDimensionEntryPoint(ServerLevel pDestination) {
portalEntrancePos = blockPosition();
return super.findDimensionEntryPoint(pDestination);
}
public void spawnParticles() {
AABB bb = getBoundingBox();
Vec3 origin = new Vec3(bb.minX, bb.minY, bb.minZ);

View file

@ -241,7 +241,8 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour {
BlockPos offsetPos = pos.relative(direction);
BlockState facingState = world.getBlockState(offsetPos);
if (facingState.getBlock() instanceof PumpBlock && facingState.getValue(PumpBlock.FACING) != direction)
if (facingState.getBlock() instanceof PumpBlock
&& facingState.getValue(PumpBlock.FACING) == direction.getOpposite())
return AttachmentTypes.NONE;
if (AllBlocks.ENCASED_FLUID_PIPE.has(facingState)

View file

@ -7,7 +7,6 @@ import static net.minecraft.world.entity.MoverType.SELF;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
@ -27,6 +26,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
@ -196,10 +196,10 @@ public class BeltMovementHandler {
}
public static boolean shouldIgnoreBlocking(Entity me, Entity other) {
if (other instanceof AbstractContraptionEntity)
return true;
if (other instanceof HangingEntity)
return true;
if (other.getPistonPushReaction() == PushReaction.IGNORE)
return true;
return isRidingOrBeingRiddenBy(me, other);
}

View file

@ -80,6 +80,7 @@ public class SlidingDoorMovementBehaviour implements MovementBehaviour {
if (info != null && info.state.hasProperty(DoorBlock.OPEN)) {
newState = info.state.cycle(DoorBlock.OPEN);
contraption.entity.setBlock(otherPos, new StructureBlockInfo(info.pos, newState, info.nbt));
contraption.invalidateColliders();
}
}

View file

@ -196,5 +196,10 @@ public class NixieTubeRenderer extends SafeTileEntityRenderer<NixieTubeTileEntit
ms.popPose();
}
@Override
public int getViewDistance() {
return 128;
}
}

View file

@ -263,7 +263,6 @@ public class TrackGraph {
if (train.graph != this)
continue;
train.graph = toOther;
train.syncTrackGraphChanges();
}
}
@ -341,7 +340,6 @@ public class TrackGraph {
if (!train.isTravellingOn(node))
continue;
train.graph = target;
train.syncTrackGraphChanges();
}
nodes.remove(nodeLoc);
@ -376,47 +374,39 @@ public class TrackGraph {
TrackEdge edge = new TrackEdge(node1, node2, turn);
TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null);
if (reader instanceof Level level) {
for (TrackGraph graph : Create.RAILWAYS.trackNetworks.values()) {
if (graph != this
&& !graph.getBounds(level).box.intersects(location.getLocation(), location2.getLocation()))
for (TrackGraph graph : Create.RAILWAYS.trackNetworks.values()) {
for (TrackNode otherNode1 : graph.nodes.values()) {
Map<TrackNode, TrackEdge> connections = graph.connectionsByNode.get(otherNode1);
if (connections == null)
continue;
for (Entry<TrackNode, TrackEdge> entry : connections.entrySet()) {
TrackNode otherNode2 = entry.getKey();
TrackEdge otherEdge = entry.getValue();
for (TrackNode otherNode1 : graph.nodes.values()) {
Map<TrackNode, TrackEdge> connections = graph.connectionsByNode.get(otherNode1);
if (connections == null)
if (graph == this)
if (otherNode1 == node1 || otherNode2 == node1 || otherNode1 == node2 || otherNode2 == node2)
continue;
if (edge == otherEdge)
continue;
if (!bezier && !otherEdge.isTurn())
continue;
if (otherEdge.isTurn() && otherEdge.turn.isPrimary())
continue;
for (Entry<TrackNode, TrackEdge> entry : connections.entrySet()) {
TrackNode otherNode2 = entry.getKey();
TrackEdge otherEdge = entry.getValue();
if (graph == this)
if (otherNode1 == node1 || otherNode2 == node1 || otherNode1 == node2
|| otherNode2 == node2)
continue;
Collection<double[]> intersections =
edge.getIntersection(node1, node2, otherEdge, otherNode1, otherNode2);
if (edge == otherEdge)
continue;
if (!bezier && !otherEdge.isTurn())
continue;
if (otherEdge.isTurn() && otherEdge.turn.isPrimary())
continue;
Collection<double[]> intersections =
edge.getIntersection(node1, node2, otherEdge, otherNode1, otherNode2);
UUID id = UUID.randomUUID();
for (double[] intersection : intersections) {
double s = intersection[0];
double t = intersection[1];
edge.edgeData.addIntersection(this, id, s, otherNode1, otherNode2, t);
edge2.edgeData.addIntersection(this, id, edge.getLength() - s, otherNode1, otherNode2, t);
otherEdge.edgeData.addIntersection(graph, id, t, node1, node2, s);
TrackEdge otherEdge2 = graph.getConnection(Couple.create(otherNode2, otherNode1));
if (otherEdge2 != null)
otherEdge2.edgeData.addIntersection(graph, id, otherEdge.getLength() - t, node1, node2,
s);
}
UUID id = UUID.randomUUID();
for (double[] intersection : intersections) {
double s = intersection[0];
double t = intersection[1];
edge.edgeData.addIntersection(this, id, s, otherNode1, otherNode2, t);
edge2.edgeData.addIntersection(this, id, edge.getLength() - s, otherNode1, otherNode2, t);
otherEdge.edgeData.addIntersection(graph, id, t, node1, node2, s);
TrackEdge otherEdge2 = graph.getConnection(Couple.create(otherNode2, otherNode1));
if (otherEdge2 != null)
otherEdge2.edgeData.addIntersection(graph, id, otherEdge.getLength() - t, node1, node2, s);
}
}
}

View file

@ -19,7 +19,6 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableDouble;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager;
import com.simibubi.create.content.logistics.trains.DimensionPalette;
import com.simibubi.create.content.logistics.trains.TrackGraph;
@ -778,7 +777,6 @@ public class Carriage {
entity.moveTo(positionAnchor);
this.entity = new WeakReference<>(cce);
cce.setGraph(train.graph == null ? null : train.graph.id);
cce.setCarriage(Carriage.this);
cce.syncCarriage();

View file

@ -8,8 +8,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
import com.google.common.base.Strings;
import com.simibubi.create.AllEntityDataSerializers;
import com.simibubi.create.AllEntityTypes;
@ -124,7 +122,9 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
if (!level.isClientSide)
return;
if (TRACK_GRAPH.equals(key))
bindCarriage();
if (TRACK_GRAPH.equals(key))
updateTrackGraph();
if (CARRIAGE_DATA.equals(key)) {
@ -212,21 +212,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
nonDamageTicks--;
if (!(contraption instanceof CarriageContraption cc))
return;
if (carriage == null) {
if (level.isClientSide) {
Train train = Create.RAILWAYS.sided(level).trains.get(trainId);
if (train == null || train.carriages.size() <= carriageIndex)
return;
carriage = train.carriages.get(carriageIndex);
if (carriage != null) {
DimensionalCarriageEntity dimensional = carriage.getDimensional(level);
dimensional.entity = new WeakReference<>(this);
dimensional.pivot = null;
carriage.updateContraptionAnchors();
dimensional.updateRenderedCutoff();
}
updateTrackGraph();
} else
if (level.isClientSide)
bindCarriage();
else
discard();
return;
}
@ -240,6 +230,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
if (!level.isClientSide) {
entityData.set(SCHEDULED, carriage.train.runtime.getSchedule() != null);
boolean shouldCarriageSyncThisTick =
carriage.train.shouldCarriageSyncThisTick(level.getGameTime(), getType().updateInterval());
if (shouldCarriageSyncThisTick && carriageData.isDirty()) {
@ -259,6 +250,10 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
if (arrivalSoundPlaying)
tickArrivalSound(cc);
entityData.set(TRACK_GRAPH, Optional.ofNullable(carriage.train.graph)
.map(g -> g.id));
return;
}
@ -310,6 +305,23 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
validForRender = true;
}
private void bindCarriage() {
if (carriage != null)
return;
Train train = Create.RAILWAYS.sided(level).trains.get(trainId);
if (train == null || train.carriages.size() <= carriageIndex)
return;
carriage = train.carriages.get(carriageIndex);
if (carriage != null) {
DimensionalCarriageEntity dimensional = carriage.getDimensional(level);
dimensional.entity = new WeakReference<>(this);
dimensional.pivot = null;
carriage.updateContraptionAnchors();
dimensional.updateRenderedCutoff();
}
updateTrackGraph();
}
private void tickArrivalSound(CarriageContraption cc) {
List<Carriage> carriages = carriage.train.carriages;
@ -381,7 +393,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
level.addParticle(ParticleTypes.CAMPFIRE_COSY_SMOKE, v.x, v.y, v.z, 0, .04, 0);
}
}
@Override
protected void addPassenger(Entity pPassenger) {
super.addPassenger(pPassenger);
@ -454,6 +466,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
super.readAdditional(compound, spawnPacket);
trainId = compound.getUUID("TrainId");
carriageIndex = compound.getInt("CarriageIndex");
if (spawnPacket) {
xOld = getX();
yOld = getY();
zOld = getZ();
}
}
@Override
@ -634,15 +651,15 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|| carriage.getTrailingPoint().edge != null && carriage.getTrailingPoint().edge.isTurn())
topSpeed = carriage.train.maxTurnSpeed();
if (slow)
if (slow)
topSpeed /= 4;
carriage.train.targetSpeed = Math.min(topSpeed, cappedTopSpeed) * targetSpeed;
boolean counteringAcceleration = Math.abs(Math.signum(targetSpeed) - Math.signum(carriage.train.speed)) > 1.5f;
if (slow && !counteringAcceleration)
carriage.train.backwardsDriver = player;
carriage.train.manualTick = true;
carriage.train.approachTargetSpeed(counteringAcceleration ? 2 : 1);
return true;
@ -708,11 +725,6 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
dimensional.updateRenderedCutoff();
}
public void setGraph(@Nullable UUID graphId) {
entityData.set(TRACK_GRAPH, Optional.ofNullable(graphId));
prevPosInvalid = true;
}
@Override
public boolean isReadyForRender() {
return super.isReadyForRender() && validForRender && !firstPositionUpdate;

View file

@ -6,6 +6,7 @@ import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Vector3f;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
@ -37,7 +38,7 @@ public class CarriageContraptionInstance extends EntityInstance<CarriageContrapt
public void setBogeyVisibility(boolean first, boolean visible) {
bogeyHidden.set(first, !visible);
}
@Override
public void beginFrame() {
if (bogeys == null) {
@ -54,18 +55,19 @@ public class CarriageContraptionInstance extends EntityInstance<CarriageContrapt
ms.pushPose();
Vector3f instancePosition = getInstancePosition(partialTicks);
TransformStack.cast(ms)
.translate(getInstancePosition(partialTicks));
.translate(instancePosition);
for (boolean current : Iterate.trueAndFalse) {
BogeyInstance instance = bogeys.get(current);
if (instance == null)
if (instance == null)
continue;
if (bogeyHidden.get(current)) {
instance.hiddenFrame();
continue;
}
ms.pushPose();
CarriageBogey bogey = instance.bogey;

View file

@ -402,7 +402,6 @@ public class Train {
navigation.cancelNavigation();
runtime.tick(level);
derailed = true;
syncTrackGraphChanges();
status.highStress();
} else if (speed != 0)
@ -683,7 +682,6 @@ public class Train {
speed = -Mth.clamp(speed, -.5, .5);
derailed = true;
graph = null;
syncTrackGraphChanges();
status.crash();
for (Carriage carriage : carriages)
@ -840,7 +838,6 @@ public class Train {
migrationCooldown = 40;
status.failedMigration();
derailed = true;
syncTrackGraphChanges();
return;
}
@ -859,16 +856,10 @@ public class Train {
currentStation.reserveFor(this);
updateSignalBlocks = true;
migrationCooldown = 0;
syncTrackGraphChanges();
return;
}
}
public void syncTrackGraphChanges() {
for (Carriage carriage : carriages)
carriage.forEachPresentEntity(e -> e.setGraph(graph == null ? null : graph.id));
}
public int getTotalLength() {
int length = 0;
for (int i = 0; i < carriages.size(); i++) {

View file

@ -95,7 +95,6 @@ public class TrainRelocationPacket extends SimplePacketBase {
if (TrainRelocator.relocate(train, sender.level, pos, hoveredBezier, direction, lookAngle, false)) {
sender.displayClientMessage(Lang.translate("train.relocate.success")
.withStyle(ChatFormatting.GREEN), true);
train.syncTrackGraphChanges();
train.carriages.forEach(c -> c.forEachPresentEntity(e -> e.nonDamageTicks = 10));
return;
}

View file

@ -197,11 +197,9 @@ public class FlapDisplayBlock extends HorizontalKineticBlock
MutableBlockPos currentPos = new MutableBlockPos();
Axis axis = getConnectionAxis(state);
for (Direction connection : Iterate.directions) {
if (connection.getAxis() == axis)
continue;
for (Direction connection : Iterate.directionsInAxis(Axis.Y)) {
boolean connect = true;
Move: for (Direction movement : Iterate.directionsInAxis(axis)) {
currentPos.set(pos);
for (int i = 0; i < 1000; i++) {
@ -334,8 +332,9 @@ public class FlapDisplayBlock extends HorizontalKineticBlock
.isReplaceable());
return directions.isEmpty() ? PlacementOffset.fail()
: PlacementOffset.success(pos.relative(directions.get(0)),
s -> s.setValue(HORIZONTAL_FACING, state.getValue(FlapDisplayBlock.HORIZONTAL_FACING)));
: PlacementOffset.success(pos.relative(directions.get(0)), s -> AllBlocks.DISPLAY_BOARD.get()
.updateColumn(world, pos.relative(directions.get(0)),
s.setValue(HORIZONTAL_FACING, state.getValue(FlapDisplayBlock.HORIZONTAL_FACING)), true));
}
}

View file

@ -25,6 +25,7 @@ public class FlapDisplaySection {
boolean hasGap;
boolean rightAligned;
boolean wideFlaps;
boolean sendTransition;
String cycle;
Component component;
@ -56,6 +57,7 @@ public class FlapDisplaySection {
public void setText(Component component) {
this.component = component;
sendTransition = true;
}
private void refresh(boolean transition) {
@ -73,9 +75,9 @@ public class FlapDisplaySection {
newText = rightAligned ? whitespace + newText : newText + whitespace;
if (!text.isEmpty())
for (int i = 0; i < spinning.length; i++)
spinning[i] |= text.charAt(i) != newText.charAt(i);
spinning[i] |= transition && text.charAt(i) != newText.charAt(i);
} else if (!text.isEmpty())
spinning[0] |= !newText.equals(text);
spinning[0] |= transition && !newText.equals(text);
text = newText;
spinningTicks = 0;
@ -131,6 +133,9 @@ public class FlapDisplaySection {
NBTHelper.putMarker(tag, "Wide");
if (component != null)
tag.putString("Text", Component.Serializer.toJson(component));
if (sendTransition)
NBTHelper.putMarker(tag, "Transition");
sendTransition = false;
return tag;
}
@ -149,7 +154,7 @@ public class FlapDisplaySection {
return section;
section.component = Component.Serializer.fromJson(tag.getString("Text"));
section.refresh(false);
section.refresh(tag.getBoolean("Transition"));
return section;
}
@ -157,7 +162,7 @@ public class FlapDisplaySection {
component = Component.Serializer.fromJson(tag.getString("Text"));
if (cyclingOptions == null)
cyclingOptions = getFlapCycle(cycle);
refresh(true);
refresh(tag.getBoolean("Transition"));
}
public boolean renderCharsIndividually() {

View file

@ -65,6 +65,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
@ -170,7 +171,9 @@ public class TrackBlock extends Block
.offset(new BlockPos(bestAxis.scale(neg ? -1 : 1)));
if (level.getBlockState(offset)
.isFaceSturdy(level, offset, Direction.UP)) {
.isFaceSturdy(level, offset, Direction.UP)
&& !level.getBlockState(offset.above())
.isFaceSturdy(level, offset, Direction.DOWN)) {
if (best == TrackShape.XO)
best = neg ? TrackShape.AW : TrackShape.AE;
if (best == TrackShape.ZO)
@ -186,6 +189,19 @@ public class TrackBlock extends Block
return PushReaction.BLOCK;
}
@Override
public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) {
super.playerWillDestroy(pLevel, pPos, pState, pPlayer);
if (pLevel.isClientSide())
return;
if (!pPlayer.isCreative())
return;
withTileEntityDo(pLevel, pPos, te -> {
te.cancelDrops = true;
te.removeInboundConnections();
});
}
@Override
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
if (pOldState.getBlock() == this && pState.setValue(HAS_TE, true) == pOldState.setValue(HAS_TE, true))
@ -198,6 +214,12 @@ public class TrackBlock extends Block
updateGirders(pState, pLevel, pPos, blockTicks);
}
@Override
public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) {
super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack);
withTileEntityDo(pLevel, pPos, TrackTileEntity::validateConnections);
}
@Override
public void tick(BlockState state, ServerLevel level, BlockPos pos, Random p_60465_) {
TrackPropagator.onRailAdded(level, pos, state);

View file

@ -38,6 +38,8 @@ import net.minecraft.world.level.Level;
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.level.material.Fluids;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
@ -47,7 +49,6 @@ import net.minecraftforge.fml.DistExecutor;
public class TrackTileEntity extends SmartTileEntity implements ITransformableTE, IMergeableTE {
Map<BlockPos, BezierConnection> connections;
boolean connectionsValidated;
boolean cancelDrops;
public Pair<ResourceKey<Level>, BlockPos> boundLocation;
@ -55,13 +56,10 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
public TrackTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
connections = new HashMap<>();
connectionsValidated = false;
setLazyTickRate(100);
}
public Map<BlockPos, BezierConnection> getConnections() {
if (!level.isClientSide && !connectionsValidated)
validateConnections();
return connections;
}
@ -79,7 +77,7 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
manageFakeTracksAlong(connection, false);
}
private void validateConnections() {
public void validateConnections() {
Set<BlockPos> invalid = new HashSet<>();
for (Entry<BlockPos, BezierConnection> entry : connections.entrySet()) {
@ -109,7 +107,6 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
trackTE.addConnection(bc.secondary());
}
connectionsValidated = true;
for (BlockPos blockPos : invalid)
removeConnection(blockPos);
}
@ -223,7 +220,7 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
public void accept(BlockEntity other) {
if (other instanceof TrackTileEntity track)
connections.putAll(track.connections);
connectionsValidated = false;
validateConnections();
level.scheduleTick(worldPosition, getBlockState().getBlock(), 1);
}
@ -384,6 +381,10 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
continue;
}
FluidState fluidState = stateAtPos.getFluidState();
if (!fluidState.isSourceOfType(Fluids.WATER))
continue;
if (!present && stateAtPos.getMaterial()
.isReplaceable())
level.setBlock(targetPos,

View file

@ -48,6 +48,7 @@ public class ConnectedPillarBlock extends LayeredBlock {
private BlockState updateColumn(Level level, BlockPos pos, BlockState state, boolean present) {
MutableBlockPos currentPos = new MutableBlockPos();
Axis axis = state.getValue(AXIS);
for (Direction connection : Iterate.directions) {
if (connection.getAxis() == axis)
continue;
@ -56,7 +57,7 @@ public class ConnectedPillarBlock extends LayeredBlock {
Move: for (Direction movement : Iterate.directionsInAxis(axis)) {
currentPos.set(pos);
for (int i = 0; i < 1000; i++) {
if (!level.isAreaLoaded(currentPos, 1))
if (!level.isLoaded(currentPos))
break;
BlockState other1 = currentPos.equals(pos) ? state : level.getBlockState(currentPos);

View file

@ -0,0 +1,34 @@
package com.simibubi.create.foundation.mixin;
import javax.annotation.Nullable;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.common.capabilities.CapabilityProvider;
import net.minecraftforge.common.extensions.IForgeEntity;
@Mixin(Entity.class)
@Implements(@Interface(iface = IForgeEntity.class, prefix = "iForgeEntity$"))
public abstract class ContraptionDriverInteractMixin extends CapabilityProvider<Entity> {
private ContraptionDriverInteractMixin(Class<Entity> baseClass) {
super(baseClass);
}
@Shadow
public abstract Entity getRootVehicle();
@Nullable
@Intrinsic
public boolean iForgeEntity$canRiderInteract() {
return getRootVehicle() instanceof AbstractContraptionEntity;
}
}

View file

@ -1,6 +1,5 @@
{
"credit": "Made with Blockbench",
"parent": "create:item/potato_cannon/item",
"texture_size": [32, 32],
"textures": {
"1": "create:item/potato_cannon",

View file

@ -7,6 +7,7 @@
"mixins": [
"CustomItemUseEffectsMixin",
"MapItemSavedDataMixin",
"ContraptionDriverInteractMixin",
"accessor.AbstractProjectileDispenseBehaviorAccessor",
"accessor.DispenserBlockAccessor",
"accessor.FallingBlockEntityAccessor",