Rise of the Jank

- address some bezier track z fighting
- portable storage interfaces now stay connected until a contraption departs
- seats can now collect entities when collided with on a contraption
- clicking on seats now tries to mount any leashed mobs first
- fixed seated entities not staying on seats on disassembly. this probably also fixed issues with sub-contraptions (oops)
- fixed portable storage interface not working on train contraptions
This commit is contained in:
simibubi 2022-02-06 04:17:18 +01:00
parent 66b6304fd3
commit a6e86520f5
19 changed files with 247 additions and 124 deletions

View file

@ -1,5 +1,6 @@
package com.simibubi.create; package com.simibubi.create;
import static com.simibubi.create.AllInteractionBehaviours.addInteractionBehaviour;
import static com.simibubi.create.AllMovementBehaviours.addMovementBehaviour; import static com.simibubi.create.AllMovementBehaviours.addMovementBehaviour;
import static com.simibubi.create.AllTags.axeOnly; import static com.simibubi.create.AllTags.axeOnly;
import static com.simibubi.create.AllTags.axeOrPickaxe; import static com.simibubi.create.AllTags.axeOrPickaxe;
@ -26,6 +27,7 @@ import com.simibubi.create.content.contraptions.components.actors.PortableStorag
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement; import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement;
import com.simibubi.create.content.contraptions.components.actors.SawMovementBehaviour; import com.simibubi.create.content.contraptions.components.actors.SawMovementBehaviour;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock; import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
import com.simibubi.create.content.contraptions.components.actors.SeatInteractionBehaviour;
import com.simibubi.create.content.contraptions.components.actors.SeatMovementBehaviour; import com.simibubi.create.content.contraptions.components.actors.SeatMovementBehaviour;
import com.simibubi.create.content.contraptions.components.clock.CuckooClockBlock; import com.simibubi.create.content.contraptions.components.clock.CuckooClockBlock;
import com.simibubi.create.content.contraptions.components.crafter.CrafterCTBehaviour; import com.simibubi.create.content.contraptions.components.crafter.CrafterCTBehaviour;
@ -36,6 +38,7 @@ import com.simibubi.create.content.contraptions.components.crusher.CrushingWheel
import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock; import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock;
import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock; import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock;
import com.simibubi.create.content.contraptions.components.deployer.DeployerMovementBehaviour; import com.simibubi.create.content.contraptions.components.deployer.DeployerMovementBehaviour;
import com.simibubi.create.content.contraptions.components.deployer.DeployerMovingInteraction;
import com.simibubi.create.content.contraptions.components.fan.EncasedFanBlock; import com.simibubi.create.content.contraptions.components.fan.EncasedFanBlock;
import com.simibubi.create.content.contraptions.components.fan.NozzleBlock; import com.simibubi.create.content.contraptions.components.fan.NozzleBlock;
import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock;
@ -59,6 +62,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.cha
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock; import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsInteractionBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsMovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsMovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.MinecartAnchorBlock; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.MinecartAnchorBlock;
@ -1036,6 +1040,7 @@ public class AllBlocks {
.blockstate(BlockStateGen.directionalAxisBlockProvider()) .blockstate(BlockStateGen.directionalAxisBlockProvider())
.transform(BlockStressDefaults.setImpact(4.0)) .transform(BlockStressDefaults.setImpact(4.0))
.onRegister(addMovementBehaviour(new DeployerMovementBehaviour())) .onRegister(addMovementBehaviour(new DeployerMovementBehaviour()))
.onRegister(addInteractionBehaviour(new DeployerMovingInteraction()))
.item(AssemblyOperatorBlockItem::new) .item(AssemblyOperatorBlockItem::new)
.transform(customItemModel()) .transform(customItemModel())
.register(); .register();
@ -1083,10 +1088,12 @@ public class AllBlocks {
public static final DyedBlockList<SeatBlock> SEATS = new DyedBlockList<>(colour -> { public static final DyedBlockList<SeatBlock> SEATS = new DyedBlockList<>(colour -> {
String colourName = colour.getSerializedName(); String colourName = colour.getSerializedName();
SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour(); SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour();
SeatInteractionBehaviour interactionBehaviour = new SeatInteractionBehaviour();
return REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour, colour == DyeColor.RED)) return REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour, colour == DyeColor.RED))
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.transform(axeOnly()) .transform(axeOnly())
.onRegister(addMovementBehaviour(movementBehaviour)) .onRegister(addMovementBehaviour(movementBehaviour))
.onRegister(addInteractionBehaviour(interactionBehaviour))
.blockstate((c, p) -> { .blockstate((c, p) -> {
p.simpleBlock(c.get(), p.models() p.simpleBlock(c.get(), p.models()
.withExistingParent(colourName + "_seat", p.modLoc("block/seat")) .withExistingParent(colourName + "_seat", p.modLoc("block/seat"))
@ -1292,6 +1299,7 @@ public class AllBlocks {
.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()))
.onRegister(addInteractionBehaviour(new ControlsInteractionBehaviour()))
.item() .item()
.transform(customItemModel()) .transform(customItemModel())
.register(); .register();

View file

@ -6,12 +6,11 @@ import java.util.function.Supplier;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.contraptions.components.deployer.DeployerMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.DoorMovingInteraction; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.DoorMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.LeverMovingInteraction; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.LeverMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.TrapdoorMovingInteraction; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.TrapdoorMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsInteractionBehaviour; import com.tterrag.registrate.util.nullness.NonNullConsumer;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@ -31,6 +30,11 @@ public class AllInteractionBehaviours {
addInteractionBehaviour(block.getRegistryName(), behaviour); addInteractionBehaviour(block.getRegistryName(), behaviour);
} }
public static <B extends Block> NonNullConsumer<? super B> addInteractionBehaviour(
MovingInteractionBehaviour movementBehaviour) {
return b -> addInteractionBehaviour(b.getRegistryName(), () -> movementBehaviour);
}
@Nullable @Nullable
public static MovingInteractionBehaviour of(ResourceLocation loc) { public static MovingInteractionBehaviour of(ResourceLocation loc) {
return (INTERACT_BEHAVIOURS.get(loc) == null) ? null return (INTERACT_BEHAVIOURS.get(loc) == null) ? null
@ -49,8 +53,6 @@ public class AllInteractionBehaviours {
static void register() { static void register() {
addInteractionBehaviour(Blocks.LEVER.getRegistryName(), LeverMovingInteraction::new); addInteractionBehaviour(Blocks.LEVER.getRegistryName(), LeverMovingInteraction::new);
addInteractionBehaviour(AllBlocks.DEPLOYER.getId(), DeployerMovingInteraction::new);
addInteractionBehaviour(AllBlocks.CONTROLS.getId(), ControlsInteractionBehaviour::new);
// TODO: Scan registry for instanceof (-> modded door support) // TODO: Scan registry for instanceof (-> modded door support)

View file

@ -9,6 +9,7 @@ import com.simibubi.create.foundation.block.WrenchableDirectionalBlock;
import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@ -46,8 +47,11 @@ public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock
@Override @Override
public BlockState getStateForPlacement(BlockPlaceContext context) { public BlockState getStateForPlacement(BlockPlaceContext context) {
return defaultBlockState().setValue(FACING, context.getNearestLookingDirection() Direction direction = context.getNearestLookingDirection();
.getOpposite()); if (context.getPlayer() != null && context.getPlayer()
.isSteppingCarefully())
direction = direction.getOpposite();
return defaultBlockState().setValue(FACING, direction.getOpposite());
} }
@Override @Override

View file

@ -11,7 +11,10 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
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;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -32,7 +35,8 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
@Override @Override
public Vec3 getActiveAreaOffset(MovementContext context) { public Vec3 getActiveAreaOffset(MovementContext context) {
return Vec3.atLowerCornerOf(context.state.getValue(PortableStorageInterfaceBlock.FACING) return Vec3.atLowerCornerOf(context.state.getValue(PortableStorageInterfaceBlock.FACING)
.getNormal()).scale(1.85f); .getNormal())
.scale(1.85f);
} }
@Override @Override
@ -42,7 +46,8 @@ public class PortableStorageInterfaceMovement extends 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 PSIActorInstance(materialManager, simulationWorld, context); return new PSIActorInstance(materialManager, simulationWorld, context);
} }
@ -56,9 +61,56 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
@Override @Override
public void visitNewPosition(MovementContext context, BlockPos pos) { public void visitNewPosition(MovementContext context, BlockPos pos) {
if (!findInterface(context, pos))
context.data.remove(_workingPos_); context.data.remove(_workingPos_);
if (findInterface(context, pos)) // if (findInterface(context, pos))
// context.stall = true;
}
@Override
public void tick(MovementContext context) {
if (context.world.isClientSide) {
getAnimation(context).tickChaser();
BlockPos pos = new BlockPos(context.position);
findInterface(context, pos);
if (!context.data.contains(_clientPrevPos_)
|| !NbtUtils.readBlockPos(context.data.getCompound(_clientPrevPos_))
.equals(pos)) {
if (!findInterface(context, pos))
reset(context);
}
return;
}
if (!context.data.contains(_workingPos_))
return;
BlockPos pos = NbtUtils.readBlockPos(context.data.getCompound(_workingPos_));
Vec3 target = VecHelper.getCenterOf(pos);
if (!context.stall
&& context.position.closerThan(target, target.distanceTo(context.position.add(context.motion))))
context.stall = true; context.stall = true;
Optional<Direction> currentFacingIfValid = getCurrentFacingIfValid(context);
if (!currentFacingIfValid.isPresent())
return;
PortableStorageInterfaceTileEntity stationaryInterface =
getStationaryInterfaceAt(context.world, pos, context.state, currentFacingIfValid.get());
if (stationaryInterface == null) {
reset(context);
return;
}
if (stationaryInterface.connectedEntity == null)
stationaryInterface.startTransferringTo(context.contraption, stationaryInterface.distance);
boolean timerBelow = stationaryInterface.transferTimer <= PortableStorageInterfaceTileEntity.ANIMATION;
stationaryInterface.keepAlive = 2;
if (context.stall && timerBelow) {
context.stall = false;
}
} }
protected boolean findInterface(MovementContext context, BlockPos pos) { protected boolean findInterface(MovementContext context, BlockPos pos) {
@ -71,9 +123,9 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
findStationaryInterface(context.world, pos, context.state, currentFacing); findStationaryInterface(context.world, pos, context.state, currentFacing);
if (psi == null) if (psi == null)
return false; return false;
if ((psi.isTransferring() || psi.isPowered()) && !context.world.isClientSide) if ((psi.isTransferring() || psi.isPowered()) && !context.world.isClientSide)
return false; return false;
context.data.put(_workingPos_, NbtUtils.writeBlockPos(psi.getBlockPos())); context.data.put(_workingPos_, NbtUtils.writeBlockPos(psi.getBlockPos()));
if (!context.world.isClientSide) { if (!context.world.isClientSide) {
Vec3 diff = VecHelper.getCenterOf(psi.getBlockPos()) Vec3 diff = VecHelper.getCenterOf(psi.getBlockPos())
@ -83,51 +135,24 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
psi.startTransferringTo(context.contraption, distance); psi.startTransferringTo(context.contraption, distance);
} else { } else {
context.data.put(_clientPrevPos_, NbtUtils.writeBlockPos(pos)); context.data.put(_clientPrevPos_, NbtUtils.writeBlockPos(pos));
if (context.contraption instanceof CarriageContraption || context.contraption.entity.isStalled()
|| context.motion.lengthSqr() == 0)
getAnimation(context).chase(psi.getConnectionDistance() / 2, 0.25f, Chaser.LINEAR);
} }
return true; return true;
} }
@Override
public void tick(MovementContext context) {
if (context.world.isClientSide) {
boolean stalled = context.contraption.stalled;
if (stalled && !context.data.contains(_workingPos_)) {
BlockPos pos = new BlockPos(context.position);
if (!context.data.contains(_clientPrevPos_)
|| !NbtUtils.readBlockPos(context.data.getCompound(_clientPrevPos_))
.equals(pos))
findInterface(context, pos);
}
if (!stalled)
reset(context);
return;
}
if (!context.data.contains(_workingPos_))
return;
BlockPos pos = NbtUtils.readBlockPos(context.data.getCompound(_workingPos_));
Optional<Direction> currentFacingIfValid = getCurrentFacingIfValid(context);
if (!currentFacingIfValid.isPresent())
return;
PortableStorageInterfaceTileEntity stationaryInterface =
getStationaryInterfaceAt(context.world, pos, context.state, currentFacingIfValid.get());
if (stationaryInterface == null || !stationaryInterface.isTransferring()) {
reset(context);
return;
}
}
@Override @Override
public void stopMoving(MovementContext context) { public void stopMoving(MovementContext context) {
reset(context); // reset(context);
} }
public void reset(MovementContext context) { public void reset(MovementContext context) {
context.data.remove(_clientPrevPos_); context.data.remove(_clientPrevPos_);
context.data.remove(_workingPos_); context.data.remove(_workingPos_);
context.stall = false; context.stall = false;
getAnimation(context).chase(0, 0.25f, Chaser.LINEAR);
} }
private PortableStorageInterfaceTileEntity findStationaryInterface(Level world, BlockPos pos, BlockState state, private PortableStorageInterfaceTileEntity findStationaryInterface(Level world, BlockPos pos, BlockState state,
@ -165,4 +190,13 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
return Optional.of(facingFromVector); return Optional.of(facingFromVector);
} }
public static LerpedFloat getAnimation(MovementContext context) {
if (!(context.temporaryData instanceof LerpedFloat lf)) {
LerpedFloat nlf = LerpedFloat.linear();
context.temporaryData = nlf;
return nlf;
}
return lf;
}
} }

View file

@ -16,6 +16,7 @@ import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
@ -28,8 +29,7 @@ import net.minecraft.world.level.block.state.BlockState;
public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<PortableStorageInterfaceTileEntity> { public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<PortableStorageInterfaceTileEntity> {
public PortableStorageInterfaceRenderer(BlockEntityRendererProvider.Context context) { public PortableStorageInterfaceRenderer(BlockEntityRendererProvider.Context context) {}
}
@Override @Override
protected void renderSafe(PortableStorageInterfaceTileEntity te, float partialTicks, PoseStack ms, protected void renderSafe(PortableStorageInterfaceTileEntity te, float partialTicks, PoseStack ms,
@ -44,24 +44,20 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) { ContraptionMatrices matrices, MultiBufferSource buffer) {
BlockState blockState = context.state; BlockState blockState = context.state;
PortableStorageInterfaceTileEntity te = getTargetPSI(context);
VertexConsumer vb = buffer.getBuffer(RenderType.solid()); VertexConsumer vb = buffer.getBuffer(RenderType.solid());
float renderPartialTicks = AnimationTickHolder.getPartialTicks(); float renderPartialTicks = AnimationTickHolder.getPartialTicks();
float progress = 0; LerpedFloat animation = PortableStorageInterfaceMovement.getAnimation(context);
boolean lit = false; float progress = animation.getValue(renderPartialTicks);
if (te != null) { boolean lit = animation.settled();
progress = te.getExtensionDistance(renderPartialTicks); render(blockState, lit, progress, matrices.getModel(),
lit = te.isConnected(); sbb -> sbb
} .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
render(blockState, lit, progress, matrices.getModel(), sbb -> sbb.light(matrices.getWorld(),
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(matrices.getViewProjection(), vb)); .renderInto(matrices.getViewProjection(), vb));
} }
private static void render(BlockState blockState, boolean lit, float progress, private static void render(BlockState blockState, boolean lit, float progress, PoseStack local,
PoseStack local, Consumer<SuperByteBuffer> drawCallback) { Consumer<SuperByteBuffer> drawCallback) {
SuperByteBuffer middle = CachedBufferer.partial(getMiddleForState(blockState, lit), blockState); SuperByteBuffer middle = CachedBufferer.partial(getMiddleForState(blockState, lit), blockState);
SuperByteBuffer top = CachedBufferer.partial(getTopForState(blockState), blockState); SuperByteBuffer top = CachedBufferer.partial(getTopForState(blockState), blockState);
@ -88,7 +84,7 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) { static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) {
String _workingPos_ = PortableStorageInterfaceMovement._workingPos_; String _workingPos_ = PortableStorageInterfaceMovement._workingPos_;
if (!context.contraption.stalled || !context.data.contains(_workingPos_)) if (!context.data.contains(_workingPos_))
return null; return null;
BlockPos pos = NbtUtils.readBlockPos(context.data.getCompound(_workingPos_)); BlockPos pos = NbtUtils.readBlockPos(context.data.getCompound(_workingPos_));

View file

@ -20,12 +20,15 @@ import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity { public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity {
public static final int ANIMATION = 4;
protected int transferTimer; protected int transferTimer;
protected float distance; protected float distance;
protected LerpedFloat connectionAnimation; protected LerpedFloat connectionAnimation;
protected boolean powered; protected boolean powered;
protected Entity connectedEntity; protected Entity connectedEntity;
public int keepAlive = 0;
public PortableStorageInterfaceTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { public PortableStorageInterfaceTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); super(type, pos, state);
transferTimer = 0; transferTimer = 0;
@ -57,11 +60,29 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
public void tick() { public void tick() {
super.tick(); super.tick();
boolean wasConnected = isConnected(); boolean wasConnected = isConnected();
int timeUnit = getTransferTimeout() / 2; int timeUnit = getTransferTimeout();
int animation = ANIMATION;
if (transferTimer > 0 && (!isVirtual() || transferTimer != timeUnit)) { if (keepAlive > 0) {
keepAlive--;
if (keepAlive == 0 && !level.isClientSide) {
stopTransferring();
transferTimer = ANIMATION - 1;
sendData();
return;
}
}
transferTimer = Math.min(transferTimer, ANIMATION * 2 + getTransferTimeout());
boolean timerCanDecrement = transferTimer > ANIMATION || transferTimer > 0 && keepAlive == 0
&& (isVirtual() || !level.isClientSide || transferTimer != ANIMATION);
if (timerCanDecrement && (!isVirtual() || transferTimer != timeUnit)) {
transferTimer--; transferTimer--;
if (transferTimer == 0 || powered) if (transferTimer == ANIMATION - 1)
sendData();
if (transferTimer <= 0 || powered)
stopTransferring(); stopTransferring();
} }
@ -72,10 +93,10 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
float progress = 0; float progress = 0;
if (isConnected) if (isConnected)
progress = 1; progress = 1;
else if (transferTimer >= timeUnit * 3) else if (transferTimer >= timeUnit + animation)
progress = Mth.lerp((transferTimer - timeUnit * 3) / (float) timeUnit, 1, 0); progress = Mth.lerp((transferTimer - timeUnit - animation) / (float) animation, 1, 0);
else if (transferTimer < timeUnit) else if (transferTimer < animation)
progress = Mth.lerp(transferTimer / (float) timeUnit, 0, 1); progress = Mth.lerp(transferTimer / (float) animation, 0, 1);
connectionAnimation.setValue(progress); connectionAnimation.setValue(progress);
} }
@ -125,16 +146,16 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
} }
public boolean isTransferring() { public boolean isTransferring() {
return transferTimer != 0; return transferTimer > ANIMATION;
} }
boolean isConnected() { boolean isConnected() {
int timeUnit = getTransferTimeout() / 2; int timeUnit = getTransferTimeout();
return transferTimer >= timeUnit && transferTimer <= timeUnit * 3; return transferTimer >= ANIMATION && transferTimer <= timeUnit + ANIMATION;
} }
float getExtensionDistance(float partialTicks) { float getExtensionDistance(float partialTicks) {
return connectionAnimation.getValue(partialTicks) * distance / 2; return (float) (Math.pow(connectionAnimation.getValue(partialTicks), 2) * distance / 2);
} }
float getConnectionDistance() { float getConnectionDistance() {
@ -142,12 +163,12 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
} }
public void startConnecting() { public void startConnecting() {
transferTimer = getTransferTimeout() * 2; transferTimer = getTransferTimeout() + ANIMATION * 2;
} }
public void onContentTransferred() { public void onContentTransferred() {
int timeUnit = getTransferTimeout() / 2; int timeUnit = getTransferTimeout();
transferTimer = timeUnit * 3; transferTimer = timeUnit + ANIMATION;
sendData(); sendData();
} }

View file

@ -5,6 +5,7 @@ import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import com.google.common.base.Optional;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
@ -131,7 +132,7 @@ public class SeatBlock extends Block {
if (world.isClientSide) if (world.isClientSide)
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
sitDown(world, pos, player); sitDown(world, pos, getLeashed(world, player).or(player));
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
@ -140,6 +141,15 @@ public class SeatBlock extends Block {
.isEmpty(); .isEmpty();
} }
public static Optional<Entity> getLeashed(Level level, Player player) {
List<Entity> entities = player.level.getEntities((Entity) null, player.getBoundingBox()
.inflate(10), e -> true);
for (Entity e : entities)
if (e instanceof Mob mob && mob.getLeashHolder() == player && SeatBlock.canBePickedUp(e))
return Optional.of(mob);
return Optional.absent();
}
public static boolean canBePickedUp(Entity passenger) { public static boolean canBePickedUp(Entity passenger) {
return !(passenger instanceof Player) && (passenger instanceof LivingEntity); return !(passenger instanceof Player) && (passenger instanceof LivingEntity);
} }

View file

@ -0,0 +1,32 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
public class SeatInteractionBehaviour extends MovingInteractionBehaviour {
@Override
public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos,
AbstractContraptionEntity contraptionEntity) {
return true;
}
@Override
public void handleEntityCollision(Entity entity, BlockPos localPos, AbstractContraptionEntity contraptionEntity) {
Contraption contraption = contraptionEntity.getContraption();
int index = contraption.getSeats()
.indexOf(localPos);
if (index == -1)
return;
if (!SeatBlock.canBePickedUp(entity))
return;
contraptionEntity.addSittingPassenger(entity, index);
}
}

View file

@ -1,6 +1,5 @@
package com.simibubi.create.content.contraptions.components.actors; package com.simibubi.create.content.contraptions.components.actors;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -14,7 +13,6 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.SlabBlock; import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public class SeatMovementBehaviour extends MovementBehaviour { public class SeatMovementBehaviour extends MovementBehaviour {
@ -40,11 +38,13 @@ public class SeatMovementBehaviour extends MovementBehaviour {
Map<UUID, Integer> seatMapping = context.contraption.getSeatMapping(); Map<UUID, Integer> seatMapping = context.contraption.getSeatMapping();
BlockState blockState = context.world.getBlockState(pos); BlockState blockState = context.world.getBlockState(pos);
boolean slab = blockState.getBlock() instanceof SlabBlock && blockState.getValue(SlabBlock.TYPE) == SlabType.BOTTOM; boolean slab =
blockState.getBlock() instanceof SlabBlock && blockState.getValue(SlabBlock.TYPE) == SlabType.BOTTOM;
boolean solid = blockState.canOcclude() || slab; boolean solid = blockState.canOcclude() || slab;
// Occupied // Occupied
if (seatMapping.containsValue(index)) { if (!seatMapping.containsValue(index))
return;
if (!solid) if (!solid)
return; return;
Entity toDismount = null; Entity toDismount = null;
@ -58,7 +58,8 @@ public class SeatMovementBehaviour extends MovementBehaviour {
toDismount = entity; toDismount = entity;
} }
} }
if (toDismount != null) { if (toDismount == null)
return;
toDismount.stopRiding(); toDismount.stopRiding();
Vec3 position = VecHelper.getCenterOf(pos) Vec3 position = VecHelper.getCenterOf(pos)
.add(0, slab ? .5f : 1f, 0); .add(0, slab ? .5f : 1f, 0);
@ -66,16 +67,5 @@ public class SeatMovementBehaviour extends MovementBehaviour {
toDismount.getPersistentData() toDismount.getPersistentData()
.remove("ContraptionDismountLocation"); .remove("ContraptionDismountLocation");
} }
return;
}
if (solid)
return;
List<Entity> nearbyEntities = context.world.getEntitiesOfClass(Entity.class,
new AABB(pos).deflate(1 / 16f), SeatBlock::canBePickedUp);
if (!nearbyEntities.isEmpty())
contraptionEntity.addSittingPassenger(nearbyEntities.get(0), index);
}
} }

View file

@ -17,6 +17,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
import com.simibubi.create.content.contraptions.components.actors.SeatEntity; import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption;
@ -212,7 +213,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
if (level.isClientSide) if (level.isClientSide)
return true; return true;
addSittingPassenger(player, indexOfSeat); addSittingPassenger(SeatBlock.getLeashed(level, player)
.or(player), indexOfSeat);
return true; return true;
} }
@ -466,8 +468,6 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new ContraptionDisassemblyPacket(this.getId(), transform)); new ContraptionDisassemblyPacket(this.getId(), transform));
discard();
contraption.addBlocksToWorld(level, transform); contraption.addBlocksToWorld(level, transform);
contraption.addPassengersToWorld(level, transform, getPassengers()); contraption.addPassengersToWorld(level, transform, getPassengers());
@ -483,6 +483,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
((AbstractContraptionEntity) entity).disassemble(); ((AbstractContraptionEntity) entity).disassemble();
} }
discard();
ejectPassengers(); ejectPassengers();
moveCollidedEntitiesOnDisassembly(transform); moveCollidedEntitiesOnDisassembly(transform);
AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, blockPosition()); AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, blockPosition());

View file

@ -1139,6 +1139,8 @@ public abstract class Contraption {
if (getSeatMapping().isEmpty()) if (getSeatMapping().isEmpty())
continue; continue;
Integer seatIndex = getSeatMapping().get(seatedEntity.getUUID()); Integer seatIndex = getSeatMapping().get(seatedEntity.getUUID());
if (seatIndex == null)
continue;
BlockPos seatPos = getSeats().get(seatIndex); BlockPos seatPos = getSeats().get(seatIndex);
seatPos = transform.apply(seatPos); seatPos = transform.apply(seatPos);
if (!(world.getBlockState(seatPos) if (!(world.getBlockState(seatPos)

View file

@ -235,6 +235,11 @@ public class ContraptionCollider {
.containsKey(pos)) { .containsKey(pos)) {
BlockState blockState = contraption.getBlocks() BlockState blockState = contraption.getBlocks()
.get(pos).state; .get(pos).state;
MovingInteractionBehaviour movingInteractionBehaviour = contraption.interactors.get(pos);
if (movingInteractionBehaviour != null)
movingInteractionBehaviour.handleEntityCollision(entity, pos, contraptionEntity);
bounce = BlockHelper.getBounceMultiplier(blockState.getBlock()); bounce = BlockHelper.getBounceMultiplier(blockState.getBlock());
slide = Math.max(0, blockState.getFriction(contraption.world, pos, entity) - .6f); slide = Math.max(0, blockState.getFriction(contraption.world, pos, entity) - .6f);
} }

View file

@ -216,7 +216,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity {
@Override @Override
protected void handleStallInformation(float x, float y, float z, float angle) { protected void handleStallInformation(float x, float y, float z, float angle) {
setPosRaw(x, y, z); setPosRaw(x, y, z);
this.angle = angle; this.angle = this.prevAngle = angle;
} }
@Override @Override

View file

@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ren
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
@ -16,15 +17,16 @@ public abstract class MovingInteractionBehaviour {
public MovingInteractionBehaviour() {} public MovingInteractionBehaviour() {}
protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, StructureBlockInfo info, protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index,
MovementContext ctx) { StructureBlockInfo info, MovementContext ctx) {
contraptionEntity.contraption.actors.remove(index); contraptionEntity.contraption.actors.remove(index);
contraptionEntity.contraption.actors.add(index, MutablePair.of(info, ctx)); contraptionEntity.contraption.actors.add(index, MutablePair.of(info, ctx));
if (contraptionEntity.level.isClientSide) if (contraptionEntity.level.isClientSide)
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(contraptionEntity.contraption)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(contraptionEntity.contraption));
} }
protected void setContraptionBlockData(AbstractContraptionEntity contraptionEntity, BlockPos pos, StructureBlockInfo info) { protected void setContraptionBlockData(AbstractContraptionEntity contraptionEntity, BlockPos pos,
StructureBlockInfo info) {
contraptionEntity.contraption.blocks.put(pos, info); contraptionEntity.contraption.blocks.put(pos, info);
if (contraptionEntity.level.isClientSide) if (contraptionEntity.level.isClientSide)
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(contraptionEntity.contraption)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(contraptionEntity.contraption));
@ -40,4 +42,6 @@ public abstract class MovingInteractionBehaviour {
return true; return true;
} }
public void handleEntityCollision(Entity entity, BlockPos localPos, AbstractContraptionEntity contraptionEntity) {}
} }

View file

@ -92,8 +92,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
if (!clientPacket) if (!clientPacket)
return; return;
if (running) { if (running) {
if (movedContraption == null || !movedContraption.isStalled()) {
clientAngleDiff = AngleHelper.getShortestAngleDiff(angleBefore, angle); clientAngleDiff = AngleHelper.getShortestAngleDiff(angleBefore, angle);
angle = angleBefore; angle = angleBefore;
}
} else } else
movedContraption = null; movedContraption = null;
} }

View file

@ -2,9 +2,12 @@ package com.simibubi.create.content.logistics.trains.entity;
import java.util.Collection; import java.util.Collection;
import org.apache.commons.lang3.tuple.MutablePair;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.Create; import com.simibubi.create.Create;
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.OrientedContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection;
@ -201,6 +204,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
} }
tickActors(); tickActors();
contraption.stalled = false;
for (MutablePair<StructureBlockInfo, MovementContext> pair : contraption.getActors()) {
MovementContext context = pair.right;
context.stall = false;
}
if (!level.isClientSide) if (!level.isClientSide)
return; return;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.trains.track; package com.simibubi.create.content.logistics.trains.track;
import com.jozufozu.flywheel.repack.joml.Math; import com.jozufozu.flywheel.repack.joml.Math;
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
@ -40,6 +41,8 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
return; return;
ms.pushPose(); ms.pushPose();
new MatrixTransformStack(ms).nudge((int) bc.tePositions.getFirst()
.asLong());
BlockPos tePosition = bc.tePositions.getFirst(); BlockPos tePosition = bc.tePositions.getFirst();
Vec3 end1 = bc.starts.getFirst() Vec3 end1 = bc.starts.getFirst()
@ -122,7 +125,7 @@ public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
.rotateYRadians(angles.y) .rotateYRadians(angles.y)
.rotateXRadians(angles.x) .rotateXRadians(angles.x)
.rotateZRadians(angles.z) .rotateZRadians(angles.z)
.translate(0, -2 / 16f + 1 / 1024f, 0) .translate(0, -2 / 16f + (i % 2 == 0 ? 1 : -1) / 2048f - 1 / 1024f, 0)
.scale(1, 1, (float) diff.length() * 2.1f); .scale(1, 1, (float) diff.length() * 2.1f);
sbb.light(LevelRenderer.getLightColor(Minecraft.getInstance().level, sbb.light(LevelRenderer.getLightColor(Minecraft.getInstance().level,