Quality of Drive

- Mounted Drills no longer attach track blocks
- Train stalling for actors no longer requires it to re-accelerate
- Fixed serverside portal cutoff not properly cleared when exiting a portal slowly
- Fixed mounted fluid tanks not showing contents when on a train
- Non-colliding blocks can no longer be used for auto track pavement
- Changed redstone link range to 256, display link range to 64
- Fixed bearings rotating their top even on contraptions that do not support stabilisation
- Train station crafting recipe now yields 2 blocks instead of 1
- Fixed some train related blocks not being breakable or wrenchable
- Lowered top speed of manually controlled trains by 25%
- Manually controlled trains now slow down to turn top speed when traversing a bezier
- Increased character limit on train names
- Fixed inconsistent deployer facing for oriented contraptions
This commit is contained in:
simibubi 2022-05-27 15:40:49 +02:00
parent a1347799af
commit cfbde0ab6c
17 changed files with 105 additions and 43 deletions

View file

@ -1465,7 +1465,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.color(MaterialColor.PODZOL)) .properties(p -> p.color(MaterialColor.PODZOL))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(axeOrPickaxe()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p))) .blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(assignDataBehaviour(new StationSummaryDisplaySource(), "station_summary")) .onRegister(assignDataBehaviour(new StationSummaryDisplaySource(), "station_summary"))
.lang("Train Station") .lang("Train Station")
@ -1505,6 +1505,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly())
.blockstate((c, p) -> p.horizontalBlock(c.get(), .blockstate((c, p) -> p.horizontalBlock(c.get(),
s -> AssetLookup.partialBaseModel(c, p, s.getValue(ControlsBlock.OPEN) ? "open" : "closed"))) s -> AssetLookup.partialBaseModel(c, p, s.getValue(ControlsBlock.OPEN) ? "open" : "closed")))
.onRegister(addMovementBehaviour(new ControlsMovementBehaviour())) .onRegister(addMovementBehaviour(new ControlsMovementBehaviour()))

View file

@ -5,6 +5,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
@ -60,7 +61,7 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) { public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) {
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos) return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos)
.isEmpty(); .isEmpty() && !AllBlocks.TRACK.has(state);
} }
} }

View file

@ -17,6 +17,7 @@ import com.simibubi.create.content.contraptions.components.deployer.DeployerTile
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.logistics.item.filter.FilterItem;
@ -28,10 +29,12 @@ import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
@ -85,8 +88,12 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
Vec3 vec = context.position.subtract(facingVec.scale(2)); Vec3 vec = context.position.subtract(facingVec.scale(2));
float xRot = AbstractContraptionEntity.pitchFromVector(facingVec) - 90; float xRot = AbstractContraptionEntity.pitchFromVector(facingVec) - 90;
if (Math.abs(xRot) > 89) if (Math.abs(xRot) > 89) {
facingVec = context.rotation.apply(new Vec3(0, 0, 1)); Vec3 initial = new Vec3(0, 0, 1);
if (context.contraption.entity instanceof OrientedContraptionEntity oce)
initial = VecHelper.rotate(initial, oce.getInitialYaw(), Axis.Y);
facingVec = context.rotation.apply(initial);
}
player.setYRot(AbstractContraptionEntity.yawFromVector(facingVec)); player.setYRot(AbstractContraptionEntity.yawFromVector(facingVec));
player.setXRot(xRot); player.setXRot(xRot);

View file

@ -327,7 +327,7 @@ public abstract class Contraption {
} }
// Bogeys tend to have sticky sides // Bogeys tend to have sticky sides
if (state.getBlock()instanceof IBogeyBlock bogey) if (state.getBlock() instanceof IBogeyBlock bogey)
for (Direction d : bogey.getStickySurfaces(world, pos, state)) for (Direction d : bogey.getStickySurfaces(world, pos, state))
if (!visited.contains(pos.relative(d))) if (!visited.contains(pos.relative(d)))
frontier.add(pos.relative(d)); frontier.add(pos.relative(d));
@ -735,7 +735,7 @@ public abstract class Contraption {
} }
} }
storage.write(nbt, spawnPacket); (spawnPacket ? getStorageForSpawnPacket() : storage).write(nbt, spawnPacket);
ListTag interactorNBT = new ListTag(); ListTag interactorNBT = new ListTag();
for (BlockPos pos : interactors.keySet()) { for (BlockPos pos : interactors.keySet()) {
@ -776,6 +776,10 @@ public abstract class Contraption {
return nbt; return nbt;
} }
protected MountedStorageManager getStorageForSpawnPacket() {
return storage;
}
private CompoundTag writeBlocksCompound() { private CompoundTag writeBlocksCompound() {
CompoundTag compound = new CompoundTag(); CompoundTag compound = new CompoundTag();
HashMapPalette<BlockState> palette = new HashMapPalette<>(GameData.getBlockStateIDMap(), 16, (i, s) -> { HashMapPalette<BlockState> palette = new HashMapPalette<>(GameData.getBlockStateIDMap(), 16, (i, s) -> {
@ -1043,7 +1047,7 @@ public abstract class Contraption {
transform.apply(tileEntity); transform.apply(tileEntity);
} }
} }
for (StructureBlockInfo block : blocks.values()) { for (StructureBlockInfo block : blocks.values()) {
if (!shouldUpdateAfterMovement(block)) if (!shouldUpdateAfterMovement(block))
continue; continue;
@ -1051,7 +1055,7 @@ public abstract class Contraption {
world.markAndNotifyBlock(targetPos, world.getChunkAt(targetPos), block.state, block.state, world.markAndNotifyBlock(targetPos, world.getChunkAt(targetPos), block.state, block.state,
Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_ALL, 512); Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_ALL, 512);
} }
for (AABB box : superglue) { for (AABB box : superglue) {
box = new AABB(transform.apply(new Vec3(box.minX, box.minY, box.minZ)), box = new AABB(transform.apply(new Vec3(box.minX, box.minY, box.minZ)),
transform.apply(new Vec3(box.maxX, box.maxY, box.maxZ))); transform.apply(new Vec3(box.maxX, box.maxY, box.maxZ)));
@ -1241,15 +1245,15 @@ public abstract class Contraption {
public IItemHandlerModifiable getSharedInventory() { public IItemHandlerModifiable getSharedInventory() {
return storage.getItems(); return storage.getItems();
} }
public IItemHandlerModifiable getSharedFuelInventory() { public IItemHandlerModifiable getSharedFuelInventory() {
return storage.getFuelItems(); return storage.getFuelItems();
} }
public IFluidHandler getSharedFluidTanks() { public IFluidHandler getSharedFluidTanks() {
return storage.getFluids(); return storage.getFluids();
} }
public Collection<StructureBlockInfo> getRenderedBlocks() { public Collection<StructureBlockInfo> getRenderedBlocks() {
return blocks.values(); return blocks.values();
} }
@ -1265,7 +1269,7 @@ public abstract class Contraption {
public Optional<List<AABB>> getSimplifiedEntityColliders() { public Optional<List<AABB>> getSimplifiedEntityColliders() {
return simplifiedEntityColliders; return simplifiedEntityColliders;
} }
public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) { public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) {
storage.updateContainedFluid(localPos, containedFluid); storage.updateContainedFluid(localPos, containedFluid);
} }

View file

@ -34,7 +34,8 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) { ContraptionMatrices matrices, MultiBufferSource buffer) {
if (Backend.isOn()) return; if (Backend.isOn())
return;
Direction facing = context.state.getValue(BlockStateProperties.FACING); Direction facing = context.state.getValue(BlockStateProperties.FACING);
PartialModel top = AllBlockPartials.BEARING_TOP; PartialModel top = AllBlockPartials.BEARING_TOP;
@ -45,9 +46,11 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
Quaternion orientation = BearingInstance.getBlockStateOrientation(facing); Quaternion orientation = BearingInstance.getBlockStateOrientation(facing);
// rotate against parent // rotate against parent
float angle = getCounterRotationAngle(context, facing, renderPartialTicks) * facing.getAxisDirection().getStep(); float angle = getCounterRotationAngle(context, facing, renderPartialTicks) * facing.getAxisDirection()
.getStep();
Quaternion rotation = facing.step().rotationDegrees(angle); Quaternion rotation = facing.step()
.rotationDegrees(angle);
rotation.mul(orientation); rotation.mul(orientation);
@ -58,8 +61,7 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
// render // render
superBuffer superBuffer
.light(matrices.getWorld(), .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid()));
} }
@ -70,16 +72,19 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
@Nullable @Nullable
@Override @Override
public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, MovementContext context) { public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld,
MovementContext context) {
return new StabilizedBearingInstance(materialManager, simulationWorld, context); return new StabilizedBearingInstance(materialManager, simulationWorld, context);
} }
static float getCounterRotationAngle(MovementContext context, Direction facing, float renderPartialTicks) { static float getCounterRotationAngle(MovementContext context, Direction facing, float renderPartialTicks) {
if (!context.contraption.canBeStabilized(facing, context.localPos))
return 0;
float offset = 0; float offset = 0;
Axis axis = facing.getAxis(); Axis axis = facing.getAxis();
AbstractContraptionEntity entity = context.contraption.entity; AbstractContraptionEntity entity = context.contraption.entity;
if (entity instanceof ControlledContraptionEntity) { if (entity instanceof ControlledContraptionEntity) {
ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity; ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity;
if (context.contraption.canBeStabilized(facing, context.localPos)) if (context.contraption.canBeStabilized(facing, context.localPos))
@ -91,12 +96,11 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
offset = -orientedCE.getViewYRot(renderPartialTicks); offset = -orientedCE.getViewYRot(renderPartialTicks);
else { else {
if (orientedCE.isInitialOrientationPresent() && orientedCE.getInitialOrientation() if (orientedCE.isInitialOrientationPresent() && orientedCE.getInitialOrientation()
.getAxis() == axis) .getAxis() == axis)
offset = -orientedCE.getViewXRot(renderPartialTicks); offset = -orientedCE.getViewXRot(renderPartialTicks);
} }
} }
return offset; return offset;
} }
} }

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.in
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionWorld; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionWorld;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -17,7 +18,7 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
public class ControlsBlock extends HorizontalDirectionalBlock { public class ControlsBlock extends HorizontalDirectionalBlock implements IWrenchable {
public static final BooleanProperty OPEN = BooleanProperty.create("open"); public static final BooleanProperty OPEN = BooleanProperty.create("open");

View file

@ -504,10 +504,14 @@ public class Carriage {
} }
public void discardPivot() { public void discardPivot() {
float prevCutoff = cutoff; int prevmin = minAllowedLocalCoord();
int prevmax = maxAllowedLocalCoord();
cutoff = 0; cutoff = 0;
pivot = null; pivot = null;
if (!serialisedPassengers.isEmpty() || !Mth.equal(prevCutoff, cutoff)) {
if ((!serialisedPassengers.isEmpty() && entity.get() != null) || prevmin != minAllowedLocalCoord()
|| prevmax != maxAllowedLocalCoord()) {
updatePassengerLoadout(); updatePassengerLoadout();
updateRenderedCutoff(); updateRenderedCutoff();
} }
@ -749,7 +753,7 @@ public class Carriage {
return; return;
cc.portalCutoffMin = minAllowedLocalCoord(); cc.portalCutoffMin = minAllowedLocalCoord();
cc.portalCutoffMax = maxAllowedLocalCoord(); cc.portalCutoffMax = maxAllowedLocalCoord();
if (!entity.level.isClientSide()) if (!entity.level.isClientSide())
return; return;
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(cce)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(cce));
} }
@ -775,7 +779,7 @@ public class Carriage {
cce.setGraph(train.graph == null ? null : train.graph.id); cce.setGraph(train.graph == null ? null : train.graph.id);
cce.setCarriage(Carriage.this); cce.setCarriage(Carriage.this);
cce.syncCarriage(); cce.syncCarriage();
if (level instanceof ServerLevel sl) if (level instanceof ServerLevel sl)
sl.addFreshEntity(entity); sl.addFreshEntity(entity);

View file

@ -226,6 +226,11 @@ public class CarriageContraption extends Contraption {
return false; return false;
} }
@Override
protected MountedStorageManager getStorageForSpawnPacket() {
return storageProxy;
}
@Override @Override
protected ContraptionType getType() { protected ContraptionType getType() {
return ContraptionType.CARRIAGE; return ContraptionType.CARRIAGE;

View file

@ -25,6 +25,7 @@ import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity; import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Color;
import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
@ -186,8 +187,6 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
dimensional.pivot = null; dimensional.pivot = null;
carriage.updateContraptionAnchors(); carriage.updateContraptionAnchors();
dimensional.updateRenderedCutoff(); dimensional.updateRenderedCutoff();
carriage.storage.bindTanks(contraption.presentTileEntities);
} }
updateTrackGraph(); updateTrackGraph();
} else } else
@ -318,8 +317,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
@Override @Override
protected boolean isActorActive(MovementContext context, MovementBehaviour actor) { protected boolean isActorActive(MovementContext context, MovementBehaviour actor) {
return (contraption instanceof CarriageContraption cc) && (cc.notInPortal() || level.isClientSide()) if (!(contraption instanceof CarriageContraption cc))
&& super.isActorActive(context, actor); return false;
if (!super.isActorActive(context, actor))
return false;
return cc.notInPortal() || level.isClientSide();
} }
@Override @Override
@ -555,10 +557,17 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
carriage.train.manualSteer = carriage.train.manualSteer =
targetSteer < 0 ? SteerDirection.RIGHT : targetSteer > 0 ? SteerDirection.LEFT : SteerDirection.NONE; targetSteer < 0 ? SteerDirection.RIGHT : targetSteer > 0 ? SteerDirection.LEFT : SteerDirection.NONE;
double topSpeed = carriage.train.maxSpeed();
double topSpeed = carriage.train.maxSpeed() * AllConfigs.SERVER.trains.manualTrainSpeedModifier.getF();
if (carriage.getLeadingPoint().edge != null && carriage.getLeadingPoint().edge.isTurn()
|| carriage.getTrailingPoint().edge != null && carriage.getTrailingPoint().edge.isTurn())
topSpeed = carriage.train.maxTurnSpeed();
carriage.train.targetSpeed = topSpeed * targetSpeed; carriage.train.targetSpeed = topSpeed * targetSpeed;
if (slow) if (slow)
carriage.train.targetSpeed /= 8; carriage.train.targetSpeed /= 6;
boolean counteringAcceleration = Math.abs(Math.signum(targetSpeed) - Math.signum(carriage.train.speed)) > 1.5f; boolean counteringAcceleration = Math.abs(Math.signum(targetSpeed) - Math.signum(carriage.train.speed)) > 1.5f;
carriage.train.manualTick = true; carriage.train.manualTick = true;
carriage.train.approachTargetSpeed(counteringAcceleration ? 2 : 1); carriage.train.approachTargetSpeed(counteringAcceleration ? 2 : 1);

View file

@ -69,6 +69,7 @@ public class Train {
public double speed = 0; public double speed = 0;
public double targetSpeed = 0; public double targetSpeed = 0;
public Double speedBeforeStall = null;
public UUID id; public UUID id;
public UUID owner; public UUID owner;
@ -184,6 +185,7 @@ public class Train {
double distance = speed; double distance = speed;
Carriage previousCarriage = null; Carriage previousCarriage = null;
int carriageCount = carriages.size(); int carriageCount = carriages.size();
boolean stalled = false;
for (int i = 0; i < carriageCount; i++) { for (int i = 0; i < carriageCount; i++) {
Carriage carriage = carriages.get(i); Carriage carriage = carriages.get(i);
@ -225,13 +227,23 @@ public class Train {
stress[i - 1] = target - actual; stress[i - 1] = target - actual;
} }
previousCarriage = carriage; previousCarriage = carriage;
if (carriage.stalled) { if (carriage.stalled) {
if (speedBeforeStall == null)
speedBeforeStall = speed;
distance = 0; distance = 0;
speed = 0; speed = 0;
stalled = true;
} }
} }
if (!stalled && speedBeforeStall != null) {
speed = Mth.clamp(speedBeforeStall, -1, 1);
speedBeforeStall = null;
}
// positive stress: carriages should move apart // positive stress: carriages should move apart
// negative stress: carriages should move closer // negative stress: carriages should move closer
@ -918,6 +930,8 @@ public class Train {
tag.putIntArray("CarriageSpacing", carriageSpacing); tag.putIntArray("CarriageSpacing", carriageSpacing);
tag.putBoolean("DoubleEnded", doubleEnded); tag.putBoolean("DoubleEnded", doubleEnded);
tag.putDouble("Speed", speed); tag.putDouble("Speed", speed);
if (speedBeforeStall != null)
tag.putDouble("SpeedBeforeStall", speedBeforeStall);
tag.putInt("Fuel", fuelTicks); tag.putInt("Fuel", fuelTicks);
tag.putDouble("TargetSpeed", targetSpeed); tag.putDouble("TargetSpeed", targetSpeed);
tag.putString("IconType", icon.id.toString()); tag.putString("IconType", icon.id.toString());
@ -964,6 +978,8 @@ public class Train {
Train train = new Train(id, owner, graph, carriages, carriageSpacing, doubleEnded); Train train = new Train(id, owner, graph, carriages, carriageSpacing, doubleEnded);
train.speed = tag.getDouble("Speed"); train.speed = tag.getDouble("Speed");
if (tag.contains("SpeedBeforeStall"))
train.speedBeforeStall = tag.getDouble("SpeedBeforeStall");
train.targetSpeed = tag.getDouble("TargetSpeed"); train.targetSpeed = tag.getDouble("TargetSpeed");
train.icon = TrainIconType.byId(new ResourceLocation(tag.getString("IconType"))); train.icon = TrainIconType.byId(new ResourceLocation(tag.getString("IconType")));
train.name = Component.Serializer.fromJson(tag.getString("Name")); train.name = Component.Serializer.fromJson(tag.getString("Name"));

View file

@ -4,6 +4,7 @@ import com.simibubi.create.AllItems;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.content.logistics.block.depot.SharedDepotBlockMethods; import com.simibubi.create.content.logistics.block.depot.SharedDepotBlockMethods;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.ScreenOpener;
@ -32,7 +33,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
public class StationBlock extends Block implements ITE<StationTileEntity> { public class StationBlock extends Block implements ITE<StationTileEntity>, IWrenchable {
public static final BooleanProperty ASSEMBLING = BooleanProperty.create("assembling"); public static final BooleanProperty ASSEMBLING = BooleanProperty.create("assembling");

View file

@ -91,9 +91,9 @@ public class StationScreen extends AbstractStationScreen {
addRenderableWidget(dropScheduleButton); addRenderableWidget(dropScheduleButton);
onTextChanged = s -> trainNameBox.x = nameBoxX(s, trainNameBox); onTextChanged = s -> trainNameBox.x = nameBoxX(s, trainNameBox);
trainNameBox = new EditBox(font, x + 23, y + 47, background.width - 20, 10, new TextComponent("")); trainNameBox = new EditBox(font, x + 23, y + 47, background.width - 75, 10, new TextComponent(""));
trainNameBox.setBordered(false); trainNameBox.setBordered(false);
trainNameBox.setMaxLength(15); trainNameBox.setMaxLength(35);
trainNameBox.setTextColor(0xC6C6C6); trainNameBox.setTextColor(0xC6C6C6);
trainNameBox.changeFocus(false); trainNameBox.changeFocus(false);
trainNameBox.mouseClicked(0, 0, 0); trainNameBox.mouseClicked(0, 0, 0);
@ -281,9 +281,12 @@ public class StationScreen extends AbstractStationScreen {
ms.popPose(); ms.popPose();
text = trainNameBox.getValue(); text = trainNameBox.getValue();
if (!trainNameBox.isFocused()) if (!trainNameBox.isFocused()) {
AllGuiTextures.STATION_EDIT_TRAIN_NAME.render(ms, nameBoxX(text, trainNameBox) + font.width(text) + 5, int buttonX = nameBoxX(text, trainNameBox) + font.width(text) + 5;
y + 44); AllGuiTextures.STATION_EDIT_TRAIN_NAME.render(ms, Math.min(buttonX, guiLeft + 156), y + 44);
if (font.width(text) > trainNameBox.getWidth())
font.drawShadow(ms, "...", guiLeft + 26, guiTop + 47, 0xa6a6a6);
}
} }
@Override @Override

View file

@ -443,7 +443,9 @@ public class TrackPlacement {
private static void paveTracks(Level level, PlacementInfo info, BlockItem blockItem, boolean simulate) { private static void paveTracks(Level level, PlacementInfo info, BlockItem blockItem, boolean simulate) {
Block block = blockItem.getBlock(); Block block = blockItem.getBlock();
info.requiredPavement = 0; info.requiredPavement = 0;
if (block == null || block instanceof EntityBlock) if (block == null || block instanceof EntityBlock || block.defaultBlockState()
.getCollisionShape(level, info.pos1)
.isEmpty())
return; return;
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
@ -496,7 +498,7 @@ public class TrackPlacement {
if (simulate) if (simulate)
continue; continue;
if (stateAtPos.getBlock()instanceof ITrackBlock trackAtPos) { if (stateAtPos.getBlock() instanceof ITrackBlock trackAtPos) {
toPlace = trackAtPos.overlay(level, offsetPos, stateAtPos, toPlace); toPlace = trackAtPos.overlay(level, offsetPos, stateAtPos, toPlace);
canPlace = true; canPlace = true;
} }

View file

@ -7,8 +7,8 @@ public class CLogistics extends ConfigBase {
public final ConfigInt defaultExtractionTimer = i(8, 1, "defaultExtractionTimer", Comments.defaultExtractionTimer); public final ConfigInt defaultExtractionTimer = i(8, 1, "defaultExtractionTimer", Comments.defaultExtractionTimer);
public final ConfigInt psiTimeout = i(20, 1, "psiTimeout", Comments.psiTimeout); public final ConfigInt psiTimeout = i(20, 1, "psiTimeout", Comments.psiTimeout);
public final ConfigInt mechanicalArmRange = i(5, 1, "mechanicalArmRange", Comments.mechanicalArmRange); public final ConfigInt mechanicalArmRange = i(5, 1, "mechanicalArmRange", Comments.mechanicalArmRange);
public final ConfigInt linkRange = i(128, 1, "linkRange", Comments.linkRange); public final ConfigInt linkRange = i(256, 1, "linkRange", Comments.linkRange);
public final ConfigInt displayLinkRange = i(32, 1, "displayLinkRange", Comments.displayLinkRange); public final ConfigInt displayLinkRange = i(64, 1, "displayLinkRange", Comments.displayLinkRange);
public final ConfigInt vaultCapacity = i(20, 1, "vaultCapacity", Comments.vaultCapacity); public final ConfigInt vaultCapacity = i(20, 1, "vaultCapacity", Comments.vaultCapacity);
@Override @Override

View file

@ -5,6 +5,7 @@ public class CTrains extends ConfigBase {
public final ConfigBool trainsCauseDamage = b(true, "trainsCauseDamage", Comments.trainsCauseDamage); public final ConfigBool trainsCauseDamage = b(true, "trainsCauseDamage", Comments.trainsCauseDamage);
public final ConfigInt maxAssemblyLength = i(128, 5, "maxAssemblyLength", Comments.maxAssemblyLength); public final ConfigInt maxAssemblyLength = i(128, 5, "maxAssemblyLength", Comments.maxAssemblyLength);
public final ConfigInt maxBogeyCount = i(20, 1, "maxBogeyCount", Comments.maxBogeyCount); public final ConfigInt maxBogeyCount = i(20, 1, "maxBogeyCount", Comments.maxBogeyCount);
public final ConfigFloat manualTrainSpeedModifier = f(.75f, 0, "manualTrainSpeedModifier", Comments.manualTrainSpeedModifier);
public final ConfigGroup trainStats = group(1, "trainStats", "Standard Trains"); public final ConfigGroup trainStats = group(1, "trainStats", "Standard Trains");
public final ConfigFloat trainTopSpeed = f(28, 0, "trainTopSpeed", Comments.mps, Comments.trainTopSpeed); public final ConfigFloat trainTopSpeed = f(28, 0, "trainTopSpeed", Comments.mps, Comments.trainTopSpeed);
@ -34,6 +35,7 @@ public class CTrains extends ConfigBase {
static String trainsCauseDamage = "Whether moving Trains can hurt colliding mobs and players."; static String trainsCauseDamage = "Whether moving Trains can hurt colliding mobs and players.";
static String maxAssemblyLength = "Maximum length of a Train Stations' assembly track."; static String maxAssemblyLength = "Maximum length of a Train Stations' assembly track.";
static String maxBogeyCount = "Maximum amount of bogeys assembled as a single Train."; static String maxBogeyCount = "Maximum amount of bogeys assembled as a single Train.";
static String manualTrainSpeedModifier = "Relative speed of a manually controlled Train compared to a Scheduled one.";
} }
} }

View file

@ -70,6 +70,7 @@ public class BuilderTransformers {
return b -> b.initialProperties(SharedProperties::softMetal) return b -> b.initialProperties(SharedProperties::softMetal)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.noOcclusion()) .properties(p -> p.noOcclusion())
.transform(pickaxeOnly())
.blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models() .blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models()
.getExistingFile(p.modLoc("block/track/bogey/top")))) .getExistingFile(p.modLoc("block/track/bogey/top"))))
.loot((p, l) -> p.dropOther(l, AllBlocks.RAILWAY_CASING.get())) .loot((p, l) -> p.dropOther(l, AllBlocks.RAILWAY_CASING.get()))

View file

@ -527,6 +527,7 @@ public class StandardRecipeGen extends CreateRecipeProvider {
.requires(Items.PAPER)), .requires(Items.PAPER)),
TRAIN_STATION = create(AllBlocks.TRACK_STATION).unlockedBy(I::railwayCasing) TRAIN_STATION = create(AllBlocks.TRACK_STATION).unlockedBy(I::railwayCasing)
.returns(2)
.viaShapeless(b -> b.requires(I.railwayCasing()) .viaShapeless(b -> b.requires(I.railwayCasing())
.requires(Items.COMPASS)), .requires(Items.COMPASS)),