mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-29 08:26:37 +01:00
Pick me up
- Seats now pick up non-player entities when touching them while being moved - Seats now drop off entities when being moved into a solid block - Previously colliding entities now get moved to match their position on the placed structure on disassembly - Contraption motion no longer gets fed into the collision response for non-minecart contraptions - The server now gets frequent updates about client players riding a contraption, fixes instabilities with projectiles, damage and anti-fly detection - Players can now take fall damage when colliding with contraptions
This commit is contained in:
parent
9a04c51418
commit
f48d1f7b1c
10 changed files with 221 additions and 102 deletions
|
@ -116,6 +116,7 @@ public class AllShapes {
|
|||
.build(),
|
||||
CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 22, 16),
|
||||
SEAT = cuboid(0, 0, 0, 16, 8, 16),
|
||||
SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16),
|
||||
MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12)
|
||||
.build(),
|
||||
TURNTABLE_SHAPE = shape(1, 4, 1, 15, 8, 15).add(5, 0, 5, 11, 4, 11)
|
||||
|
|
|
@ -72,6 +72,12 @@ public class SeatBlock extends Block implements IPortableBlock {
|
|||
ISelectionContext p_220053_4_) {
|
||||
return AllShapes.SEAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState p_220071_1_, IBlockReader p_220071_2_, BlockPos p_220071_3_,
|
||||
ISelectionContext p_220071_4_) {
|
||||
return AllShapes.SEAT_COLLISION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player,
|
||||
|
|
|
@ -1,9 +1,84 @@
|
|||
package com.simibubi.create.content.contraptions.components.actors;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.SlabBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.state.properties.SlabType;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class SeatMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void startMoving(MovementContext context) {
|
||||
super.startMoving(context);
|
||||
int indexOf = context.contraption.getSeats()
|
||||
.indexOf(context.localPos);
|
||||
context.data.putInt("SeatIndex", indexOf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
super.visitNewPosition(context, pos);
|
||||
ContraptionEntity contraptionEntity = context.contraption.entity;
|
||||
if (contraptionEntity == null)
|
||||
return;
|
||||
int index = context.data.getInt("SeatIndex");
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
Map<UUID, Integer> seatMapping = context.contraption.getSeatMapping();
|
||||
BlockState blockState = context.world.getBlockState(pos);
|
||||
boolean slab = blockState.getBlock() instanceof SlabBlock && blockState.get(SlabBlock.TYPE) == SlabType.BOTTOM;
|
||||
boolean solid = blockState.isSolid() || slab;
|
||||
|
||||
// Occupied
|
||||
if (seatMapping.containsValue(index)) {
|
||||
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.getUniqueID()))
|
||||
continue;
|
||||
toDismount = entity;
|
||||
}
|
||||
}
|
||||
if (toDismount != null) {
|
||||
toDismount.stopRiding();
|
||||
Vec3d position = VecHelper.getCenterOf(pos)
|
||||
.add(0, slab ? .5f : 1f, 0);
|
||||
toDismount.setPositionAndUpdate(position.x, position.y, position.z);
|
||||
toDismount.getPersistentData()
|
||||
.remove("ContraptionDismountLocation");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (solid)
|
||||
return;
|
||||
|
||||
List<LivingEntity> entitiesWithinAABB = context.world.getEntitiesWithinAABB(LivingEntity.class,
|
||||
new AxisAlignedBB(pos).shrink(1 / 16f), e -> !(e instanceof PlayerEntity));
|
||||
if (entitiesWithinAABB.isEmpty())
|
||||
return;
|
||||
LivingEntity passenger = entitiesWithinAABB.get(0);
|
||||
contraptionEntity.addSittingPassenger(passenger, index);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||
|
||||
public class ClientMotionPacket extends SimplePacketBase {
|
||||
|
||||
private Vec3d motion;
|
||||
private boolean onGround;
|
||||
|
||||
public ClientMotionPacket(Vec3d motion, boolean onGround) {
|
||||
this.motion = motion;
|
||||
this.onGround = onGround;
|
||||
}
|
||||
|
||||
public ClientMotionPacket(PacketBuffer buffer) {
|
||||
motion = new Vec3d(buffer.readFloat(), buffer.readFloat(), buffer.readFloat());
|
||||
onGround = buffer.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketBuffer buffer) {
|
||||
buffer.writeFloat((float) motion.x);
|
||||
buffer.writeFloat((float) motion.y);
|
||||
buffer.writeFloat((float) motion.z);
|
||||
buffer.writeBoolean(onGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get()
|
||||
.enqueueWork(() -> {
|
||||
ServerPlayerEntity sender = context.get()
|
||||
.getSender();
|
||||
if (sender == null)
|
||||
return;
|
||||
sender.setMotion(motion);
|
||||
sender.onGround = onGround;
|
||||
if (onGround) {
|
||||
sender.handleFallDamage(sender.fallDistance, 1);
|
||||
sender.fallDistance = 0;
|
||||
sender.connection.floatingTickCount = 0;
|
||||
}
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -89,6 +89,7 @@ public abstract class Contraption {
|
|||
public CombinedInvWrapper inventory;
|
||||
public List<TileEntity> customRenderTEs;
|
||||
public Set<Pair<BlockPos, Direction>> superglue;
|
||||
public ContraptionEntity entity;
|
||||
|
||||
public AxisAlignedBB bounds;
|
||||
public boolean stalled;
|
||||
|
@ -203,13 +204,14 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
public void mountPassengers(ContraptionEntity contraptionEntity) {
|
||||
this.entity = contraptionEntity;
|
||||
if (contraptionEntity.world.isRemote)
|
||||
return;
|
||||
for (BlockPos seatPos : seats) {
|
||||
for (BlockPos seatPos : getSeats()) {
|
||||
Entity passenger = initialPassengers.get(seatPos);
|
||||
if (passenger == null)
|
||||
continue;
|
||||
int seatIndex = seats.indexOf(seatPos);
|
||||
int seatIndex = getSeats().indexOf(seatPos);
|
||||
if (seatIndex == -1)
|
||||
continue;
|
||||
contraptionEntity.addSittingPassenger(passenger, seatIndex);
|
||||
|
@ -252,7 +254,7 @@ public abstract class Contraption {
|
|||
// Seats transfer their passenger to the contraption
|
||||
if (state.getBlock() instanceof SeatBlock) {
|
||||
BlockPos local = toLocalPos(pos);
|
||||
seats.add(local);
|
||||
getSeats().add(local);
|
||||
List<SeatEntity> seatsEntities = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
|
||||
if (!seatsEntities.isEmpty()) {
|
||||
SeatEntity seat = seatsEntities.get(0);
|
||||
|
@ -516,11 +518,12 @@ public abstract class Contraption {
|
|||
if (nbt.contains("BoundsFront"))
|
||||
bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5));
|
||||
|
||||
seats.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND), c -> seats.add(NBTUtil.readBlockPos(c)));
|
||||
seatMapping.clear();
|
||||
getSeats().clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND),
|
||||
c -> getSeats().add(NBTUtil.readBlockPos(c)));
|
||||
getSeatMapping().clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Passengers", NBT.TAG_COMPOUND),
|
||||
c -> seatMapping.put(NBTUtil.readUniqueId(c.getCompound("Id")), c.getInt("Seat")));
|
||||
c -> getSeatMapping().put(NBTUtil.readUniqueId(c.getCompound("Id")), c.getInt("Seat")));
|
||||
|
||||
stalled = nbt.getBoolean("Stalled");
|
||||
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
|
||||
|
@ -568,8 +571,8 @@ public abstract class Contraption {
|
|||
storageNBT.add(c);
|
||||
}
|
||||
|
||||
nbt.put("Seats", NBTHelper.writeCompoundList(seats, NBTUtil::writeBlockPos));
|
||||
nbt.put("Passengers", NBTHelper.writeCompoundList(seatMapping.entrySet(), e -> {
|
||||
nbt.put("Seats", NBTHelper.writeCompoundList(getSeats(), NBTUtil::writeBlockPos));
|
||||
nbt.put("Passengers", NBTHelper.writeCompoundList(getSeatMapping().entrySet(), e -> {
|
||||
CompoundNBT tag = new CompoundNBT();
|
||||
tag.put("Id", NBTUtil.writeUniqueId(e.getKey()));
|
||||
tag.putInt("Seat", e.getValue());
|
||||
|
@ -635,10 +638,8 @@ public abstract class Contraption {
|
|||
}
|
||||
}
|
||||
|
||||
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation, List<Entity> seatedEntities) {
|
||||
public void addBlocksToWorld(World world, StructureTransform transform) {
|
||||
stop(world);
|
||||
StructureTransform transform = new StructureTransform(offset, rotation);
|
||||
|
||||
for (boolean nonBrittles : Iterate.trueAndFalse) {
|
||||
for (BlockInfo block : blocks.values()) {
|
||||
if (nonBrittles == BlockMovementTraits.isBrittle(block.state))
|
||||
|
@ -718,12 +719,14 @@ public abstract class Contraption {
|
|||
world.addEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addPassengersToWorld(World world, StructureTransform transform, List<Entity> seatedEntities) {
|
||||
for (Entity seatedEntity : seatedEntities) {
|
||||
if (seatMapping.isEmpty())
|
||||
if (getSeatMapping().isEmpty())
|
||||
continue;
|
||||
Integer seatIndex = seatMapping.get(seatedEntity.getUniqueID());
|
||||
BlockPos seatPos = seats.get(seatIndex);
|
||||
Integer seatIndex = getSeatMapping().get(seatedEntity.getUniqueID());
|
||||
BlockPos seatPos = getSeats().get(seatIndex);
|
||||
seatPos = transform.apply(seatPos);
|
||||
if (!(world.getBlockState(seatPos)
|
||||
.getBlock() instanceof SeatBlock))
|
||||
|
@ -732,7 +735,6 @@ public abstract class Contraption {
|
|||
continue;
|
||||
SeatBlock.sitDown(world, seatPos, seatedEntity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void initActors(World world) {
|
||||
|
@ -796,14 +798,22 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
public BlockPos getSeat(UUID entityId) {
|
||||
if (!seatMapping.containsKey(entityId))
|
||||
if (!getSeatMapping().containsKey(entityId))
|
||||
return null;
|
||||
int seatIndex = seatMapping.get(entityId);
|
||||
if (seatIndex >= seats.size())
|
||||
int seatIndex = getSeatMapping().get(entityId);
|
||||
if (seatIndex >= getSeats().size())
|
||||
return null;
|
||||
return seats.get(seatIndex);
|
||||
return getSeats().get(seatIndex);
|
||||
}
|
||||
|
||||
protected abstract AllContraptionTypes getType();
|
||||
|
||||
public Map<UUID, Integer> getSeatMapping() {
|
||||
return seatMapping;
|
||||
}
|
||||
|
||||
public List<BlockPos> getSeats() {
|
||||
return seats;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ import com.simibubi.create.content.contraptions.components.actors.BlockBreakingM
|
|||
import com.simibubi.create.foundation.collision.ContinuousOBBCollider.ContinuousSeparationManifold;
|
||||
import com.simibubi.create.foundation.collision.Matrix3d;
|
||||
import com.simibubi.create.foundation.collision.OrientedBB;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
@ -143,6 +144,8 @@ public class ContraptionCollider {
|
|||
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
||||
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
|
||||
Vec3d contraptionRotation = contraptionEntity.getRotationVec();
|
||||
Vec3d contraptionMotion = contraptionEntity.stationary ? Vec3d.ZERO
|
||||
: contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
|
||||
contraptionEntity.collidingEntities.clear();
|
||||
|
||||
if (contraption == null)
|
||||
|
@ -154,14 +157,14 @@ public class ContraptionCollider {
|
|||
double conRotX = contraptionRotation.x;
|
||||
double conRotY = contraptionRotation.y;
|
||||
double conRotZ = contraptionRotation.z;
|
||||
Vec3d conMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
|
||||
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
|
||||
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
||||
Matrix3d rotation = null;
|
||||
|
||||
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(2)
|
||||
.expand(0, 32, 0), contraptionEntity::canCollideWith)) {
|
||||
boolean serverPlayer = entity instanceof PlayerEntity && !world.isRemote;
|
||||
boolean player = entity instanceof PlayerEntity;
|
||||
boolean serverPlayer = player && !world.isRemote;
|
||||
|
||||
// Init matrix
|
||||
if (rotation == null) {
|
||||
|
@ -199,8 +202,8 @@ public class ContraptionCollider {
|
|||
// Prepare entity bounds
|
||||
OrientedBB obb = new OrientedBB(localBB);
|
||||
obb.setRotation(rotation);
|
||||
motion = motion.subtract(conMotion);
|
||||
motion = rotation.transform(motion);
|
||||
motion = motion.subtract(contraptionMotion);
|
||||
|
||||
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
|
||||
// CollisionDebugger.OBB = obb.copy();
|
||||
|
@ -268,7 +271,7 @@ public class ContraptionCollider {
|
|||
|
||||
rotation.transpose();
|
||||
motionResponse = rotation.transform(motionResponse)
|
||||
.add(conMotion);
|
||||
.add(contraptionMotion);
|
||||
totalResponse = rotation.transform(totalResponse);
|
||||
rotation.transpose();
|
||||
|
||||
|
@ -282,10 +285,10 @@ public class ContraptionCollider {
|
|||
|
||||
Vec3d contactPointMotion = Vec3d.ZERO;
|
||||
if (surfaceCollision.isTrue()) {
|
||||
// entity.handleFallDamage(entity.fallDistance, 1); tunnelling issue
|
||||
entity.fallDistance = 0;
|
||||
entity.onGround = true;
|
||||
if (!serverPlayer)
|
||||
contraptionEntity.collidingEntities.add(entity);
|
||||
if (!serverPlayer)
|
||||
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
||||
}
|
||||
|
||||
|
@ -321,6 +324,9 @@ public class ContraptionCollider {
|
|||
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
||||
entityPosition.z + allowedMovement.z);
|
||||
entity.setMotion(entityMotion);
|
||||
|
||||
if (!serverPlayer && player)
|
||||
AllPackets.channel.sendToServer(new ClientMotionPacket(entityMotion, true));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,11 +7,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.simibubi.create.AllEntityTypes;
|
||||
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption;
|
||||
|
@ -49,15 +47,10 @@ import net.minecraft.tileentity.TileEntity;
|
|||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.ReuseableStream;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.IBooleanFunction;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
@ -166,9 +159,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
|||
passenger.startRiding(this, true);
|
||||
if (world.isRemote)
|
||||
return;
|
||||
contraption.seatMapping.put(passenger.getUniqueID(), seatIndex);
|
||||
contraption.getSeatMapping()
|
||||
.put(passenger.getUniqueID(), seatIndex);
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||
new ContraptionSeatMappingPacket(getEntityId(), contraption.seatMapping));
|
||||
new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -185,9 +179,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
|||
if (transformedVector != null)
|
||||
passenger.getPersistentData()
|
||||
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
|
||||
contraption.seatMapping.remove(passenger.getUniqueID());
|
||||
contraption.getSeatMapping()
|
||||
.remove(passenger.getUniqueID());
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||
new ContraptionSeatMappingPacket(getEntityId(), contraption.seatMapping));
|
||||
new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -199,7 +194,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
|||
return;
|
||||
callback.accept(passenger, transformedVector.x, transformedVector.y, transformedVector.z);
|
||||
}
|
||||
|
||||
|
||||
protected Vec3d getPassengerPosition(Entity passenger) {
|
||||
AxisAlignedBB bb = passenger.getBoundingBox();
|
||||
double ySize = bb.getYSize();
|
||||
|
@ -214,18 +209,21 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
|||
|
||||
@Override
|
||||
protected boolean canFitPassenger(Entity p_184219_1_) {
|
||||
return getPassengers().size() < contraption.seats.size();
|
||||
return getPassengers().size() < contraption.getSeats()
|
||||
.size();
|
||||
}
|
||||
|
||||
public boolean handlePlayerInteraction(PlayerEntity player, BlockPos localPos, Direction side,
|
||||
Hand interactionHand) {
|
||||
int indexOfSeat = contraption.seats.indexOf(localPos);
|
||||
int indexOfSeat = contraption.getSeats()
|
||||
.indexOf(localPos);
|
||||
if (indexOfSeat == -1)
|
||||
return false;
|
||||
|
||||
// Eject potential existing passenger
|
||||
Entity toDismount = null;
|
||||
for (Entry<UUID, Integer> entry : contraption.seatMapping.entrySet()) {
|
||||
for (Entry<UUID, Integer> entry : contraption.getSeatMapping()
|
||||
.entrySet()) {
|
||||
if (entry.getValue() != indexOfSeat)
|
||||
continue;
|
||||
for (Entity entity : getPassengers()) {
|
||||
|
@ -631,9 +629,20 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
|||
remove();
|
||||
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
|
||||
Vec3d rotation = getRotationVec();
|
||||
contraption.addBlocksToWorld(world, offset, rotation, getPassengers());
|
||||
StructureTransform transform = new StructureTransform(offset, rotation);
|
||||
contraption.addBlocksToWorld(world, transform);
|
||||
contraption.addPassengersToWorld(world, transform, getPassengers());
|
||||
removePassengers();
|
||||
// preventMovedEntitiesFromGettingStuck();
|
||||
|
||||
for (Entity entity : collidingEntities) {
|
||||
Vec3d positionVec = getPositionVec();
|
||||
Vec3d localVec = entity.getPositionVec()
|
||||
.subtract(positionVec);
|
||||
localVec = VecHelper.rotate(localVec, getRotationVec().scale(-1));
|
||||
Vec3d transformed = transform.apply(localVec);
|
||||
entity.setPositionAndUpdate(transformed.x, transformed.y, transformed.z);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -660,73 +669,18 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
|||
@Override
|
||||
protected void doWaterSplashEffect() {}
|
||||
|
||||
public void preventMovedEntitiesFromGettingStuck() {
|
||||
Vec3d stuckTest = new Vec3d(0, -2, 0);
|
||||
for (Entity e : collidingEntities) {
|
||||
e.fallDistance = 0;
|
||||
e.onGround = true;
|
||||
|
||||
Vec3d vec = stuckTest;
|
||||
AxisAlignedBB axisalignedbb = e.getBoundingBox()
|
||||
.offset(0, 2, 0);
|
||||
ISelectionContext iselectioncontext = ISelectionContext.forEntity(this);
|
||||
VoxelShape voxelshape = e.world.getWorldBorder()
|
||||
.getShape();
|
||||
Stream<VoxelShape> stream =
|
||||
VoxelShapes.compare(voxelshape, VoxelShapes.create(axisalignedbb.shrink(1.0E-7D)), IBooleanFunction.AND)
|
||||
? Stream.empty()
|
||||
: Stream.of(voxelshape);
|
||||
Stream<VoxelShape> stream1 =
|
||||
this.world.getEmptyCollisionShapes(e, axisalignedbb.expand(vec), ImmutableSet.of());
|
||||
ReuseableStream<VoxelShape> reuseablestream = new ReuseableStream<>(Stream.concat(stream1, stream));
|
||||
Vec3d vec3d = vec.lengthSquared() == 0.0D ? vec
|
||||
: collideBoundingBoxHeuristically(this, vec, axisalignedbb, e.world, iselectioncontext,
|
||||
reuseablestream);
|
||||
boolean flag = vec.x != vec3d.x;
|
||||
boolean flag1 = vec.y != vec3d.y;
|
||||
boolean flag2 = vec.z != vec3d.z;
|
||||
boolean flag3 = e.onGround || flag1 && vec.y < 0.0D;
|
||||
if (this.stepHeight > 0.0F && flag3 && (flag || flag2)) {
|
||||
Vec3d vec3d1 = collideBoundingBoxHeuristically(e, new Vec3d(vec.x, (double) e.stepHeight, vec.z),
|
||||
axisalignedbb, e.world, iselectioncontext, reuseablestream);
|
||||
Vec3d vec3d2 = collideBoundingBoxHeuristically(e, new Vec3d(0.0D, (double) e.stepHeight, 0.0D),
|
||||
axisalignedbb.expand(vec.x, 0.0D, vec.z), e.world, iselectioncontext, reuseablestream);
|
||||
if (vec3d2.y < (double) e.stepHeight) {
|
||||
Vec3d vec3d3 = collideBoundingBoxHeuristically(e, new Vec3d(vec.x, 0.0D, vec.z),
|
||||
axisalignedbb.offset(vec3d2), e.world, iselectioncontext, reuseablestream).add(vec3d2);
|
||||
if (horizontalMag(vec3d3) > horizontalMag(vec3d1)) {
|
||||
vec3d1 = vec3d3;
|
||||
}
|
||||
}
|
||||
|
||||
if (horizontalMag(vec3d1) > horizontalMag(vec3d)) {
|
||||
vec3d = vec3d1.add(collideBoundingBoxHeuristically(e, new Vec3d(0.0D, -vec3d1.y + vec.y, 0.0D),
|
||||
axisalignedbb.offset(vec3d1), e.world, iselectioncontext, reuseablestream));
|
||||
}
|
||||
}
|
||||
|
||||
vec = vec3d.subtract(stuckTest);
|
||||
if (vec.equals(Vec3d.ZERO))
|
||||
continue;
|
||||
e.setPosition(e.getX() + vec.x, e.getY() + vec.y, e.getZ() + vec.z);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public CompoundNBT writeWithoutTypeId(CompoundNBT nbt) {
|
||||
Vec3d vec = getPositionVec();
|
||||
List<Entity> passengers = getPassengers();
|
||||
List<Vec3d> positionVecs = new ArrayList<>(passengers.size());
|
||||
|
||||
for (Entity entity : passengers) {
|
||||
Vec3d prevVec = entity.getPositionVec();
|
||||
positionVecs.add(prevVec);
|
||||
|
||||
// setPos has world accessing side-effects when removed == false
|
||||
entity.removed = true;
|
||||
|
||||
// Gather passengers into same chunk when saving
|
||||
Vec3d prevVec = entity.getPositionVec();
|
||||
entity.setPos(vec.x, prevVec.y, vec.z);
|
||||
|
||||
// Super requires all passengers to not be removed in order to write them to the
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
|
|||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||
|
@ -17,6 +18,7 @@ public class MovementContext {
|
|||
public Vec3d rotation;
|
||||
public World world;
|
||||
public BlockState state;
|
||||
public BlockPos localPos;
|
||||
public CompoundNBT tileData;
|
||||
|
||||
public boolean stall;
|
||||
|
@ -29,7 +31,8 @@ public class MovementContext {
|
|||
this.world = world;
|
||||
this.state = info.state;
|
||||
this.tileData = info.nbt;
|
||||
|
||||
localPos = info.pos;
|
||||
|
||||
firstMovement = true;
|
||||
motion = Vec3d.ZERO;
|
||||
relativeMotion = Vec3d.ZERO;
|
||||
|
|
|
@ -69,6 +69,13 @@ public class StructureTransform {
|
|||
|
||||
}
|
||||
|
||||
public Vec3d apply(Vec3d localVec) {
|
||||
Vec3d vec = localVec;
|
||||
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
|
||||
vec = vec.add(new Vec3d(offset));
|
||||
return vec;
|
||||
}
|
||||
|
||||
public BlockPos apply(BlockPos localPos) {
|
||||
Vec3d vec = VecHelper.getCenterOf(localPos);
|
||||
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.function.Function;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ClientMotionPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionInteractionPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionSeatMappingPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
|
||||
|
@ -46,6 +47,7 @@ public enum AllPackets {
|
|||
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
|
||||
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
|
||||
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new),
|
||||
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new),
|
||||
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
|
||||
|
||||
// Server to Client
|
||||
|
|
Loading…
Reference in a new issue