diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 4f2398d62..ca3373fd9 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -1,5 +1,6 @@ package com.simibubi.create; +import static com.simibubi.create.AllInteractionBehaviours.addInteractionBehaviour; import static com.simibubi.create.AllMovementBehaviours.addMovementBehaviour; import static com.simibubi.create.AllTags.axeOnly; 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.SawMovementBehaviour; 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.clock.CuckooClockBlock; 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.deployer.DeployerBlock; 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.NozzleBlock; 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.gantry.GantryCarriageBlock; 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.mounted.CartAssemblerBlock; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.MinecartAnchorBlock; @@ -1036,6 +1040,7 @@ public class AllBlocks { .blockstate(BlockStateGen.directionalAxisBlockProvider()) .transform(BlockStressDefaults.setImpact(4.0)) .onRegister(addMovementBehaviour(new DeployerMovementBehaviour())) + .onRegister(addInteractionBehaviour(new DeployerMovingInteraction())) .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); @@ -1083,10 +1088,12 @@ public class AllBlocks { public static final DyedBlockList SEATS = new DyedBlockList<>(colour -> { String colourName = colour.getSerializedName(); SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour(); + SeatInteractionBehaviour interactionBehaviour = new SeatInteractionBehaviour(); return REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour, colour == DyeColor.RED)) .initialProperties(SharedProperties::wooden) .transform(axeOnly()) .onRegister(addMovementBehaviour(movementBehaviour)) + .onRegister(addInteractionBehaviour(interactionBehaviour)) .blockstate((c, p) -> { p.simpleBlock(c.get(), p.models() .withExistingParent(colourName + "_seat", p.modLoc("block/seat")) @@ -1292,6 +1299,7 @@ public class AllBlocks { .blockstate((c, p) -> p.horizontalBlock(c.get(), s -> AssetLookup.partialBaseModel(c, p, s.getValue(ControlsBlock.OPEN) ? "open" : "closed"))) .onRegister(addMovementBehaviour(new ControlsMovementBehaviour())) + .onRegister(addInteractionBehaviour(new ControlsInteractionBehaviour())) .item() .transform(customItemModel()) .register(); diff --git a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java index 7d61dcb09..46c916a41 100644 --- a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java +++ b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java @@ -6,12 +6,11 @@ import java.util.function.Supplier; import javax.annotation.Nullable; 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.interaction.DoorMovingInteraction; 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.controls.ControlsInteractionBehaviour; +import com.tterrag.registrate.util.nullness.NonNullConsumer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; @@ -31,6 +30,11 @@ public class AllInteractionBehaviours { addInteractionBehaviour(block.getRegistryName(), behaviour); } + public static NonNullConsumer addInteractionBehaviour( + MovingInteractionBehaviour movementBehaviour) { + return b -> addInteractionBehaviour(b.getRegistryName(), () -> movementBehaviour); + } + @Nullable public static MovingInteractionBehaviour of(ResourceLocation loc) { return (INTERACT_BEHAVIOURS.get(loc) == null) ? null @@ -49,11 +53,9 @@ public class AllInteractionBehaviours { static void register() { 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) - + for (Block trapdoor : ImmutableList.of(Blocks.ACACIA_TRAPDOOR, Blocks.OAK_TRAPDOOR, Blocks.DARK_OAK_TRAPDOOR, Blocks.SPRUCE_TRAPDOOR, Blocks.JUNGLE_TRAPDOOR, Blocks.BIRCH_TRAPDOOR, Blocks.WARPED_TRAPDOOR, Blocks.CRIMSON_TRAPDOOR)) { diff --git a/src/main/java/com/simibubi/create/AllMovementBehaviours.java b/src/main/java/com/simibubi/create/AllMovementBehaviours.java index 03cd553c3..a829f4c34 100644 --- a/src/main/java/com/simibubi/create/AllMovementBehaviours.java +++ b/src/main/java/com/simibubi/create/AllMovementBehaviours.java @@ -52,7 +52,7 @@ public class AllMovementBehaviours { MovementBehaviour movementBehaviour) { return b -> addMovementBehaviour(b.getRegistryName(), movementBehaviour); } - + static void register() { addMovementBehaviour(Blocks.BELL, new BellMovementBehaviour()); addMovementBehaviour(Blocks.CAMPFIRE, new CampfireMovementBehaviour()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java index fc406f542..7007680ef 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java @@ -16,7 +16,7 @@ import net.minecraftforge.items.ItemStackHandler; public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTileEntity { protected LazyOptional capability; - + public PortableItemInterfaceTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); capability = createEmptyHandler(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java index 20917348d..954381dbb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java @@ -9,6 +9,7 @@ import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; @@ -46,8 +47,11 @@ public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock @Override public BlockState getStateForPlacement(BlockPlaceContext context) { - return defaultBlockState().setValue(FACING, context.getNearestLookingDirection() - .getOpposite()); + Direction direction = context.getNearestLookingDirection(); + if (context.getPlayer() != null && context.getPlayer() + .isSteppingCarefully()) + direction = direction.getOpposite(); + return defaultBlockState().setValue(FACING, direction.getOpposite()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java index 647f5bf37..c87113a50 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java @@ -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.render.ActorInstance; 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.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.BlockPos; @@ -32,7 +35,8 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { @Override public Vec3 getActiveAreaOffset(MovementContext context) { return Vec3.atLowerCornerOf(context.state.getValue(PortableStorageInterfaceBlock.FACING) - .getNormal()).scale(1.85f); + .getNormal()) + .scale(1.85f); } @Override @@ -42,7 +46,8 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { @Nullable @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); } @@ -56,9 +61,56 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { @Override public void visitNewPosition(MovementContext context, BlockPos pos) { - context.data.remove(_workingPos_); - if (findInterface(context, pos)) + if (!findInterface(context, pos)) + context.data.remove(_workingPos_); +// 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; + + Optional 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) { @@ -71,9 +123,9 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { findStationaryInterface(context.world, pos, context.state, currentFacing); if (psi == null) return false; - if ((psi.isTransferring() || psi.isPowered()) && !context.world.isClientSide) return false; + context.data.put(_workingPos_, NbtUtils.writeBlockPos(psi.getBlockPos())); if (!context.world.isClientSide) { Vec3 diff = VecHelper.getCenterOf(psi.getBlockPos()) @@ -83,51 +135,24 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { psi.startTransferringTo(context.contraption, distance); } else { 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; } - @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 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 public void stopMoving(MovementContext context) { - reset(context); +// reset(context); } public void reset(MovementContext context) { context.data.remove(_clientPrevPos_); context.data.remove(_workingPos_); context.stall = false; + getAnimation(context).chase(0, 0.25f, Chaser.LINEAR); } private PortableStorageInterfaceTileEntity findStationaryInterface(Level world, BlockPos pos, BlockState state, @@ -165,4 +190,13 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { 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; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java index 39ff32874..fef8d442e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java @@ -16,6 +16,7 @@ import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; 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.RenderType; @@ -28,8 +29,7 @@ import net.minecraft.world.level.block.state.BlockState; public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer { - public PortableStorageInterfaceRenderer(BlockEntityRendererProvider.Context context) { - } + public PortableStorageInterfaceRenderer(BlockEntityRendererProvider.Context context) {} @Override protected void renderSafe(PortableStorageInterfaceTileEntity te, float partialTicks, PoseStack ms, @@ -44,24 +44,20 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer sbb.light(matrices.getWorld(), - ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), vb)); + LerpedFloat animation = PortableStorageInterfaceMovement.getAnimation(context); + float progress = animation.getValue(renderPartialTicks); + boolean lit = animation.settled(); + render(blockState, lit, progress, matrices.getModel(), + sbb -> sbb + .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), vb)); } - private static void render(BlockState blockState, boolean lit, float progress, - PoseStack local, Consumer drawCallback) { + private static void render(BlockState blockState, boolean lit, float progress, PoseStack local, + Consumer drawCallback) { SuperByteBuffer middle = CachedBufferer.partial(getMiddleForState(blockState, lit), blockState); SuperByteBuffer top = CachedBufferer.partial(getTopForState(blockState), blockState); @@ -88,7 +84,7 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer type, BlockPos pos, BlockState state) { super(type, pos, state); transferTimer = 0; @@ -57,11 +60,29 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity public void tick() { super.tick(); 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--; - if (transferTimer == 0 || powered) + if (transferTimer == ANIMATION - 1) + sendData(); + if (transferTimer <= 0 || powered) stopTransferring(); } @@ -72,10 +93,10 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity float progress = 0; if (isConnected) progress = 1; - else if (transferTimer >= timeUnit * 3) - progress = Mth.lerp((transferTimer - timeUnit * 3) / (float) timeUnit, 1, 0); - else if (transferTimer < timeUnit) - progress = Mth.lerp(transferTimer / (float) timeUnit, 0, 1); + else if (transferTimer >= timeUnit + animation) + progress = Mth.lerp((transferTimer - timeUnit - animation) / (float) animation, 1, 0); + else if (transferTimer < animation) + progress = Mth.lerp(transferTimer / (float) animation, 0, 1); connectionAnimation.setValue(progress); } @@ -125,16 +146,16 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity } public boolean isTransferring() { - return transferTimer != 0; + return transferTimer > ANIMATION; } boolean isConnected() { - int timeUnit = getTransferTimeout() / 2; - return transferTimer >= timeUnit && transferTimer <= timeUnit * 3; + int timeUnit = getTransferTimeout(); + return transferTimer >= ANIMATION && transferTimer <= timeUnit + ANIMATION; } float getExtensionDistance(float partialTicks) { - return connectionAnimation.getValue(partialTicks) * distance / 2; + return (float) (Math.pow(connectionAnimation.getValue(partialTicks), 2) * distance / 2); } float getConnectionDistance() { @@ -142,12 +163,12 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity } public void startConnecting() { - transferTimer = getTransferTimeout() * 2; + transferTimer = getTransferTimeout() + ANIMATION * 2; } public void onContentTransferred() { - int timeUnit = getTransferTimeout() / 2; - transferTimer = timeUnit * 3; + int timeUnit = getTransferTimeout(); + transferTimer = timeUnit + ANIMATION; sendData(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java index 27eafc7a6..880f3a1a0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java @@ -5,6 +5,7 @@ import java.util.List; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import com.google.common.base.Optional; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.foundation.utility.BlockHelper; @@ -131,7 +132,7 @@ public class SeatBlock extends Block { if (world.isClientSide) return InteractionResult.SUCCESS; - sitDown(world, pos, player); + sitDown(world, pos, getLeashed(world, player).or(player)); return InteractionResult.SUCCESS; } @@ -140,6 +141,15 @@ public class SeatBlock extends Block { .isEmpty(); } + public static Optional getLeashed(Level level, Player player) { + List 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) { return !(passenger instanceof Player) && (passenger instanceof LivingEntity); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatInteractionBehaviour.java new file mode 100644 index 000000000..ea831c89f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatInteractionBehaviour.java @@ -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); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java index 9e1c4b40e..08b670f49 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java @@ -1,6 +1,5 @@ package com.simibubi.create.content.contraptions.components.actors; -import java.util.List; import java.util.Map; 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.state.BlockState; import net.minecraft.world.level.block.state.properties.SlabType; -import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; public class SeatMovementBehaviour extends MovementBehaviour { @@ -30,7 +28,7 @@ public class SeatMovementBehaviour extends MovementBehaviour { @Override public void visitNewPosition(MovementContext context, BlockPos pos) { super.visitNewPosition(context, pos); - + AbstractContraptionEntity contraptionEntity = context.contraption.entity; if (contraptionEntity == null) return; @@ -40,42 +38,34 @@ public class SeatMovementBehaviour extends MovementBehaviour { Map seatMapping = context.contraption.getSeatMapping(); 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; // Occupied - if (seatMapping.containsValue(index)) { - if (!solid) - return; - Entity toDismount = null; - for (Map.Entry entry : seatMapping.entrySet()) { - if (entry.getValue() != index) + if (!seatMapping.containsValue(index)) + return; + if (!solid) + return; + Entity toDismount = null; + for (Map.Entry entry : seatMapping.entrySet()) { + if (entry.getValue() != index) + continue; + for (Entity entity : contraptionEntity.getPassengers()) { + if (!entry.getKey() + .equals(entity.getUUID())) continue; - for (Entity entity : contraptionEntity.getPassengers()) { - if (!entry.getKey() - .equals(entity.getUUID())) - continue; - toDismount = entity; - } + toDismount = entity; } - if (toDismount != null) { - toDismount.stopRiding(); - Vec3 position = VecHelper.getCenterOf(pos) - .add(0, slab ? .5f : 1f, 0); - toDismount.teleportTo(position.x, position.y, position.z); - toDismount.getPersistentData() - .remove("ContraptionDismountLocation"); - } - return; } - - if (solid) + if (toDismount == null) return; - - List nearbyEntities = context.world.getEntitiesOfClass(Entity.class, - new AABB(pos).deflate(1 / 16f), SeatBlock::canBePickedUp); - if (!nearbyEntities.isEmpty()) - contraptionEntity.addSittingPassenger(nearbyEntities.get(0), index); + toDismount.stopRiding(); + Vec3 position = VecHelper.getCenterOf(pos) + .add(0, slab ? .5f : 1f, 0); + toDismount.teleportTo(position.x, position.y, position.z); + toDismount.getPersistentData() + .remove("ContraptionDismountLocation"); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index ed3279d5a..40b75f65e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -17,6 +17,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllSoundEvents; 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.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; @@ -186,7 +187,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit .handlePlayerInteraction(player, interactionHand, localPos, this); if (player.isPassenger()) return false; - + // Eject potential existing passenger Entity toDismount = null; for (Entry entry : contraption.getSeatMapping() @@ -212,7 +213,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit if (level.isClientSide) return true; - addSittingPassenger(player, indexOfSeat); + addSittingPassenger(SeatBlock.getLeashed(level, player) + .or(player), indexOfSeat); return true; } @@ -466,11 +468,9 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionDisassemblyPacket(this.getId(), transform)); - discard(); - contraption.addBlocksToWorld(level, transform); contraption.addPassengersToWorld(level, transform, getPassengers()); - + for (Entity entity : getPassengers()) { if (!(entity instanceof OrientedContraptionEntity)) continue; @@ -482,6 +482,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit entity.setPos(transformed.getX(), transformed.getY(), transformed.getZ()); ((AbstractContraptionEntity) entity).disassemble(); } + + discard(); ejectPassengers(); moveCollidedEntitiesOnDisassembly(transform); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index 080b4b266..aae58d324 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -348,7 +348,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)); @@ -882,7 +882,7 @@ public abstract class Contraption { } ListTag paletteNBT = new ListTag(); - for(int i = 0; i < palette.getSize(); ++i) + for (int i = 0; i < palette.getSize(); ++i) paletteNBT.add(NbtUtils.writeBlockState(palette.values.byId(i))); compound.put("Palette", paletteNBT); @@ -1139,6 +1139,8 @@ public abstract class Contraption { if (getSeatMapping().isEmpty()) continue; Integer seatIndex = getSeatMapping().get(seatedEntity.getUUID()); + if (seatIndex == null) + continue; BlockPos seatPos = getSeats().get(seatIndex); seatPos = transform.apply(seatPos); if (!(world.getBlockState(seatPos) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index 759677bfd..95dde8b12 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -235,6 +235,11 @@ public class ContraptionCollider { .containsKey(pos)) { BlockState blockState = contraption.getBlocks() .get(pos).state; + + MovingInteractionBehaviour movingInteractionBehaviour = contraption.interactors.get(pos); + if (movingInteractionBehaviour != null) + movingInteractionBehaviour.handleEntityCollision(entity, pos, contraptionEntity); + bounce = BlockHelper.getBounceMultiplier(blockState.getBlock()); slide = Math.max(0, blockState.getFriction(contraption.world, pos, entity) - .6f); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java index 9aabc58a5..f9dcae6ca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java @@ -216,7 +216,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { @Override protected void handleStallInformation(float x, float y, float z, float angle) { setPosRaw(x, y, z); - this.angle = angle; + this.angle = this.prevAngle = angle; } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java index 19da364a5..557b2ad8a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java @@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ren import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraftforge.api.distmarker.Dist; @@ -16,15 +17,16 @@ public abstract class MovingInteractionBehaviour { public MovingInteractionBehaviour() {} - protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, StructureBlockInfo info, - MovementContext ctx) { + protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, + StructureBlockInfo info, MovementContext ctx) { contraptionEntity.contraption.actors.remove(index); contraptionEntity.contraption.actors.add(index, MutablePair.of(info, ctx)); if (contraptionEntity.level.isClientSide) 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); if (contraptionEntity.level.isClientSide) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(contraptionEntity.contraption)); @@ -40,4 +42,6 @@ public abstract class MovingInteractionBehaviour { return true; } + public void handleEntityCollision(Entity entity, BlockPos localPos, AbstractContraptionEntity contraptionEntity) {} + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java index 1f659aecd..8618c2d62 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java @@ -92,8 +92,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity if (!clientPacket) return; if (running) { - clientAngleDiff = AngleHelper.getShortestAngleDiff(angleBefore, angle); - angle = angleBefore; + if (movedContraption == null || !movedContraption.isStalled()) { + clientAngleDiff = AngleHelper.getShortestAngleDiff(angleBefore, angle); + angle = angleBefore; + } } else movedContraption = null; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java index e6e28c434..b03eb9269 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java @@ -2,9 +2,12 @@ package com.simibubi.create.content.logistics.trains.entity; import java.util.Collection; +import org.apache.commons.lang3.tuple.MutablePair; + import com.google.common.base.Strings; import com.simibubi.create.AllEntityTypes; 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.interaction.controls.ControlsBlock; import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; @@ -201,6 +204,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { } tickActors(); + contraption.stalled = false; + for (MutablePair pair : contraption.getActors()) { + MovementContext context = pair.right; + context.stall = false; + } if (!level.isClientSide) return; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackRenderer.java index 4f4f7b03e..367acb5b7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackRenderer.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.logistics.trains.track; 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.VertexConsumer; import com.simibubi.create.AllBlockPartials; @@ -40,6 +41,8 @@ public class TrackRenderer extends SafeTileEntityRenderer { return; ms.pushPose(); + new MatrixTransformStack(ms).nudge((int) bc.tePositions.getFirst() + .asLong()); BlockPos tePosition = bc.tePositions.getFirst(); Vec3 end1 = bc.starts.getFirst() @@ -122,7 +125,7 @@ public class TrackRenderer extends SafeTileEntityRenderer { .rotateYRadians(angles.y) .rotateXRadians(angles.x) .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); sbb.light(LevelRenderer.getLightColor(Minecraft.getInstance().level,