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

View file

@ -5,6 +5,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.backend.Backend;
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.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
@ -60,7 +61,7 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) {
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.MovementBehaviour;
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.ContraptionMatrices;
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.NBTHelper;
import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
@ -85,8 +88,12 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
Vec3 vec = context.position.subtract(facingVec.scale(2));
float xRot = AbstractContraptionEntity.pitchFromVector(facingVec) - 90;
if (Math.abs(xRot) > 89)
facingVec = context.rotation.apply(new Vec3(0, 0, 1));
if (Math.abs(xRot) > 89) {
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.setXRot(xRot);

View file

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

View file

@ -34,7 +34,8 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
@OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) {
if (Backend.isOn()) return;
if (Backend.isOn())
return;
Direction facing = context.state.getValue(BlockStateProperties.FACING);
PartialModel top = AllBlockPartials.BEARING_TOP;
@ -45,9 +46,11 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
Quaternion orientation = BearingInstance.getBlockStateOrientation(facing);
// 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);
@ -58,8 +61,7 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
// render
superBuffer
.light(matrices.getWorld(),
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid()));
}
@ -70,16 +72,19 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
@Nullable
@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);
}
static float getCounterRotationAngle(MovementContext context, Direction facing, float renderPartialTicks) {
if (!context.contraption.canBeStabilized(facing, context.localPos))
return 0;
float offset = 0;
Axis axis = facing.getAxis();
AbstractContraptionEntity entity = context.contraption.entity;
if (entity instanceof ControlledContraptionEntity) {
ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity;
if (context.contraption.canBeStabilized(facing, context.localPos))
@ -91,12 +96,11 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
offset = -orientedCE.getViewYRot(renderPartialTicks);
else {
if (orientedCE.isInitialOrientationPresent() && orientedCE.getInitialOrientation()
.getAxis() == axis)
.getAxis() == axis)
offset = -orientedCE.getViewXRot(renderPartialTicks);
}
}
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.content.contraptions.components.structureMovement.ContraptionWorld;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import net.minecraft.core.BlockPos;
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.VoxelShape;
public class ControlsBlock extends HorizontalDirectionalBlock {
public class ControlsBlock extends HorizontalDirectionalBlock implements IWrenchable {
public static final BooleanProperty OPEN = BooleanProperty.create("open");

View file

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

View file

@ -226,6 +226,11 @@ public class CarriageContraption extends Contraption {
return false;
}
@Override
protected MountedStorageManager getStorageForSpawnPacket() {
return storageProxy;
}
@Override
protected ContraptionType getType() {
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.TravellingPoint.SteerDirection;
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.Couple;
import com.simibubi.create.foundation.utility.Lang;
@ -186,8 +187,6 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
dimensional.pivot = null;
carriage.updateContraptionAnchors();
dimensional.updateRenderedCutoff();
carriage.storage.bindTanks(contraption.presentTileEntities);
}
updateTrackGraph();
} else
@ -318,8 +317,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
@Override
protected boolean isActorActive(MovementContext context, MovementBehaviour actor) {
return (contraption instanceof CarriageContraption cc) && (cc.notInPortal() || level.isClientSide())
&& super.isActorActive(context, actor);
if (!(contraption instanceof CarriageContraption cc))
return false;
if (!super.isActorActive(context, actor))
return false;
return cc.notInPortal() || level.isClientSide();
}
@Override
@ -555,10 +557,17 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
carriage.train.manualSteer =
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;
if (slow)
carriage.train.targetSpeed /= 8;
carriage.train.targetSpeed /= 6;
boolean counteringAcceleration = Math.abs(Math.signum(targetSpeed) - Math.signum(carriage.train.speed)) > 1.5f;
carriage.train.manualTick = true;
carriage.train.approachTargetSpeed(counteringAcceleration ? 2 : 1);

View file

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

View file

@ -91,9 +91,9 @@ public class StationScreen extends AbstractStationScreen {
addRenderableWidget(dropScheduleButton);
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.setMaxLength(15);
trainNameBox.setMaxLength(35);
trainNameBox.setTextColor(0xC6C6C6);
trainNameBox.changeFocus(false);
trainNameBox.mouseClicked(0, 0, 0);
@ -281,9 +281,12 @@ public class StationScreen extends AbstractStationScreen {
ms.popPose();
text = trainNameBox.getValue();
if (!trainNameBox.isFocused())
AllGuiTextures.STATION_EDIT_TRAIN_NAME.render(ms, nameBoxX(text, trainNameBox) + font.width(text) + 5,
y + 44);
if (!trainNameBox.isFocused()) {
int buttonX = nameBoxX(text, trainNameBox) + font.width(text) + 5;
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

View file

@ -443,7 +443,9 @@ public class TrackPlacement {
private static void paveTracks(Level level, PlacementInfo info, BlockItem blockItem, boolean simulate) {
Block block = blockItem.getBlock();
info.requiredPavement = 0;
if (block == null || block instanceof EntityBlock)
if (block == null || block instanceof EntityBlock || block.defaultBlockState()
.getCollisionShape(level, info.pos1)
.isEmpty())
return;
Set<BlockPos> visited = new HashSet<>();
@ -496,7 +498,7 @@ public class TrackPlacement {
if (simulate)
continue;
if (stateAtPos.getBlock()instanceof ITrackBlock trackAtPos) {
if (stateAtPos.getBlock() instanceof ITrackBlock trackAtPos) {
toPlace = trackAtPos.overlay(level, offsetPos, stateAtPos, toPlace);
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 psiTimeout = i(20, 1, "psiTimeout", Comments.psiTimeout);
public final ConfigInt mechanicalArmRange = i(5, 1, "mechanicalArmRange", Comments.mechanicalArmRange);
public final ConfigInt linkRange = i(128, 1, "linkRange", Comments.linkRange);
public final ConfigInt displayLinkRange = i(32, 1, "displayLinkRange", Comments.displayLinkRange);
public final ConfigInt linkRange = i(256, 1, "linkRange", Comments.linkRange);
public final ConfigInt displayLinkRange = i(64, 1, "displayLinkRange", Comments.displayLinkRange);
public final ConfigInt vaultCapacity = i(20, 1, "vaultCapacity", Comments.vaultCapacity);
@Override

View file

@ -5,6 +5,7 @@ public class CTrains extends ConfigBase {
public final ConfigBool trainsCauseDamage = b(true, "trainsCauseDamage", Comments.trainsCauseDamage);
public final ConfigInt maxAssemblyLength = i(128, 5, "maxAssemblyLength", Comments.maxAssemblyLength);
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 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 maxAssemblyLength = "Maximum length of a Train Stations' assembly track.";
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)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.noOcclusion())
.transform(pickaxeOnly())
.blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models()
.getExistingFile(p.modLoc("block/track/bogey/top"))))
.loot((p, l) -> p.dropOther(l, AllBlocks.RAILWAY_CASING.get()))

View file

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