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;
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<SeatBlock> 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();

View file

@ -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 <B extends Block> NonNullConsumer<? super B> 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)) {

View file

@ -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());

View file

@ -16,7 +16,7 @@ import net.minecraftforge.items.ItemStackHandler;
public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTileEntity {
protected LazyOptional<IItemHandlerModifiable> capability;
public PortableItemInterfaceTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
capability = createEmptyHandler();

View file

@ -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

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.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<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) {
@ -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<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
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;
}
}

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.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<PortableStorageInterfaceTileEntity> {
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<Por
public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) {
BlockState blockState = context.state;
PortableStorageInterfaceTileEntity te = getTargetPSI(context);
VertexConsumer vb = buffer.getBuffer(RenderType.solid());
float renderPartialTicks = AnimationTickHolder.getPartialTicks();
float progress = 0;
boolean lit = false;
if (te != null) {
progress = te.getExtensionDistance(renderPartialTicks);
lit = te.isConnected();
}
render(blockState, lit, progress, matrices.getModel(), sbb -> 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<SuperByteBuffer> drawCallback) {
private static void render(BlockState blockState, boolean lit, float progress, PoseStack local,
Consumer<SuperByteBuffer> 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<Por
static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) {
String _workingPos_ = PortableStorageInterfaceMovement._workingPos_;
if (!context.contraption.stalled || !context.data.contains(_workingPos_))
if (!context.data.contains(_workingPos_))
return null;
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 static final int ANIMATION = 4;
protected int transferTimer;
protected float distance;
protected LerpedFloat connectionAnimation;
protected boolean powered;
protected Entity connectedEntity;
public int keepAlive = 0;
public PortableStorageInterfaceTileEntity(BlockEntityType<?> 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();
}

View file

@ -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<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) {
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;
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<UUID, Integer> 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<UUID, Integer> entry : seatMapping.entrySet()) {
if (entry.getValue() != index)
if (!seatMapping.containsValue(index))
return;
if (!solid)
return;
Entity toDismount = null;
for (Map.Entry<UUID, Integer> 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<Entity> 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");
}
}

View file

@ -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<UUID, Integer> 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);

View file

@ -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)

View file

@ -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);
}

View file

@ -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

View file

@ -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) {}
}

View file

@ -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;
}

View file

@ -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<StructureBlockInfo, MovementContext> pair : contraption.getActors()) {
MovementContext context = pair.right;
context.stall = false;
}
if (!level.isClientSide)
return;

View file

@ -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<TrackTileEntity> {
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<TrackTileEntity> {
.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,