mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-16 20:23:42 +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(),
|
.build(),
|
||||||
CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 22, 16),
|
CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 22, 16),
|
||||||
SEAT = cuboid(0, 0, 0, 16, 8, 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)
|
MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12)
|
||||||
.build(),
|
.build(),
|
||||||
TURNTABLE_SHAPE = shape(1, 4, 1, 15, 8, 15).add(5, 0, 5, 11, 4, 11)
|
TURNTABLE_SHAPE = shape(1, 4, 1, 15, 8, 15).add(5, 0, 5, 11, 4, 11)
|
||||||
|
|
|
@ -73,6 +73,12 @@ public class SeatBlock extends Block implements IPortableBlock {
|
||||||
return AllShapes.SEAT;
|
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
|
@Override
|
||||||
public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player,
|
public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player,
|
||||||
Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
|
Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
|
||||||
|
|
|
@ -1,9 +1,84 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors;
|
package com.simibubi.create.content.contraptions.components.actors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.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.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 {
|
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 CombinedInvWrapper inventory;
|
||||||
public List<TileEntity> customRenderTEs;
|
public List<TileEntity> customRenderTEs;
|
||||||
public Set<Pair<BlockPos, Direction>> superglue;
|
public Set<Pair<BlockPos, Direction>> superglue;
|
||||||
|
public ContraptionEntity entity;
|
||||||
|
|
||||||
public AxisAlignedBB bounds;
|
public AxisAlignedBB bounds;
|
||||||
public boolean stalled;
|
public boolean stalled;
|
||||||
|
@ -203,13 +204,14 @@ public abstract class Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mountPassengers(ContraptionEntity contraptionEntity) {
|
public void mountPassengers(ContraptionEntity contraptionEntity) {
|
||||||
|
this.entity = contraptionEntity;
|
||||||
if (contraptionEntity.world.isRemote)
|
if (contraptionEntity.world.isRemote)
|
||||||
return;
|
return;
|
||||||
for (BlockPos seatPos : seats) {
|
for (BlockPos seatPos : getSeats()) {
|
||||||
Entity passenger = initialPassengers.get(seatPos);
|
Entity passenger = initialPassengers.get(seatPos);
|
||||||
if (passenger == null)
|
if (passenger == null)
|
||||||
continue;
|
continue;
|
||||||
int seatIndex = seats.indexOf(seatPos);
|
int seatIndex = getSeats().indexOf(seatPos);
|
||||||
if (seatIndex == -1)
|
if (seatIndex == -1)
|
||||||
continue;
|
continue;
|
||||||
contraptionEntity.addSittingPassenger(passenger, seatIndex);
|
contraptionEntity.addSittingPassenger(passenger, seatIndex);
|
||||||
|
@ -252,7 +254,7 @@ public abstract class Contraption {
|
||||||
// Seats transfer their passenger to the contraption
|
// Seats transfer their passenger to the contraption
|
||||||
if (state.getBlock() instanceof SeatBlock) {
|
if (state.getBlock() instanceof SeatBlock) {
|
||||||
BlockPos local = toLocalPos(pos);
|
BlockPos local = toLocalPos(pos);
|
||||||
seats.add(local);
|
getSeats().add(local);
|
||||||
List<SeatEntity> seatsEntities = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
|
List<SeatEntity> seatsEntities = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
|
||||||
if (!seatsEntities.isEmpty()) {
|
if (!seatsEntities.isEmpty()) {
|
||||||
SeatEntity seat = seatsEntities.get(0);
|
SeatEntity seat = seatsEntities.get(0);
|
||||||
|
@ -516,11 +518,12 @@ public abstract class Contraption {
|
||||||
if (nbt.contains("BoundsFront"))
|
if (nbt.contains("BoundsFront"))
|
||||||
bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5));
|
bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5));
|
||||||
|
|
||||||
seats.clear();
|
getSeats().clear();
|
||||||
NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND), c -> seats.add(NBTUtil.readBlockPos(c)));
|
NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND),
|
||||||
seatMapping.clear();
|
c -> getSeats().add(NBTUtil.readBlockPos(c)));
|
||||||
|
getSeatMapping().clear();
|
||||||
NBTHelper.iterateCompoundList(nbt.getList("Passengers", NBT.TAG_COMPOUND),
|
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");
|
stalled = nbt.getBoolean("Stalled");
|
||||||
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
|
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
|
||||||
|
@ -568,8 +571,8 @@ public abstract class Contraption {
|
||||||
storageNBT.add(c);
|
storageNBT.add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
nbt.put("Seats", NBTHelper.writeCompoundList(seats, NBTUtil::writeBlockPos));
|
nbt.put("Seats", NBTHelper.writeCompoundList(getSeats(), NBTUtil::writeBlockPos));
|
||||||
nbt.put("Passengers", NBTHelper.writeCompoundList(seatMapping.entrySet(), e -> {
|
nbt.put("Passengers", NBTHelper.writeCompoundList(getSeatMapping().entrySet(), e -> {
|
||||||
CompoundNBT tag = new CompoundNBT();
|
CompoundNBT tag = new CompoundNBT();
|
||||||
tag.put("Id", NBTUtil.writeUniqueId(e.getKey()));
|
tag.put("Id", NBTUtil.writeUniqueId(e.getKey()));
|
||||||
tag.putInt("Seat", e.getValue());
|
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);
|
stop(world);
|
||||||
StructureTransform transform = new StructureTransform(offset, rotation);
|
|
||||||
|
|
||||||
for (boolean nonBrittles : Iterate.trueAndFalse) {
|
for (boolean nonBrittles : Iterate.trueAndFalse) {
|
||||||
for (BlockInfo block : blocks.values()) {
|
for (BlockInfo block : blocks.values()) {
|
||||||
if (nonBrittles == BlockMovementTraits.isBrittle(block.state))
|
if (nonBrittles == BlockMovementTraits.isBrittle(block.state))
|
||||||
|
@ -718,12 +719,14 @@ public abstract class Contraption {
|
||||||
world.addEntity(entity);
|
world.addEntity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPassengersToWorld(World world, StructureTransform transform, List<Entity> seatedEntities) {
|
||||||
for (Entity seatedEntity : seatedEntities) {
|
for (Entity seatedEntity : seatedEntities) {
|
||||||
if (seatMapping.isEmpty())
|
if (getSeatMapping().isEmpty())
|
||||||
continue;
|
continue;
|
||||||
Integer seatIndex = seatMapping.get(seatedEntity.getUniqueID());
|
Integer seatIndex = getSeatMapping().get(seatedEntity.getUniqueID());
|
||||||
BlockPos seatPos = seats.get(seatIndex);
|
BlockPos seatPos = getSeats().get(seatIndex);
|
||||||
seatPos = transform.apply(seatPos);
|
seatPos = transform.apply(seatPos);
|
||||||
if (!(world.getBlockState(seatPos)
|
if (!(world.getBlockState(seatPos)
|
||||||
.getBlock() instanceof SeatBlock))
|
.getBlock() instanceof SeatBlock))
|
||||||
|
@ -732,7 +735,6 @@ public abstract class Contraption {
|
||||||
continue;
|
continue;
|
||||||
SeatBlock.sitDown(world, seatPos, seatedEntity);
|
SeatBlock.sitDown(world, seatPos, seatedEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initActors(World world) {
|
public void initActors(World world) {
|
||||||
|
@ -796,14 +798,22 @@ public abstract class Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockPos getSeat(UUID entityId) {
|
public BlockPos getSeat(UUID entityId) {
|
||||||
if (!seatMapping.containsKey(entityId))
|
if (!getSeatMapping().containsKey(entityId))
|
||||||
return null;
|
return null;
|
||||||
int seatIndex = seatMapping.get(entityId);
|
int seatIndex = getSeatMapping().get(entityId);
|
||||||
if (seatIndex >= seats.size())
|
if (seatIndex >= getSeats().size())
|
||||||
return null;
|
return null;
|
||||||
return seats.get(seatIndex);
|
return getSeats().get(seatIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract AllContraptionTypes getType();
|
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.ContinuousOBBCollider.ContinuousSeparationManifold;
|
||||||
import com.simibubi.create.foundation.collision.Matrix3d;
|
import com.simibubi.create.foundation.collision.Matrix3d;
|
||||||
import com.simibubi.create.foundation.collision.OrientedBB;
|
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.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -143,6 +144,8 @@ public class ContraptionCollider {
|
||||||
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
||||||
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
|
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
|
||||||
Vec3d contraptionRotation = contraptionEntity.getRotationVec();
|
Vec3d contraptionRotation = contraptionEntity.getRotationVec();
|
||||||
|
Vec3d contraptionMotion = contraptionEntity.stationary ? Vec3d.ZERO
|
||||||
|
: contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
|
||||||
contraptionEntity.collidingEntities.clear();
|
contraptionEntity.collidingEntities.clear();
|
||||||
|
|
||||||
if (contraption == null)
|
if (contraption == null)
|
||||||
|
@ -154,14 +157,14 @@ public class ContraptionCollider {
|
||||||
double conRotX = contraptionRotation.x;
|
double conRotX = contraptionRotation.x;
|
||||||
double conRotY = contraptionRotation.y;
|
double conRotY = contraptionRotation.y;
|
||||||
double conRotZ = contraptionRotation.z;
|
double conRotZ = contraptionRotation.z;
|
||||||
Vec3d conMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
|
|
||||||
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
|
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
|
||||||
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
||||||
Matrix3d rotation = null;
|
Matrix3d rotation = null;
|
||||||
|
|
||||||
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(2)
|
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(2)
|
||||||
.expand(0, 32, 0), contraptionEntity::canCollideWith)) {
|
.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
|
// Init matrix
|
||||||
if (rotation == null) {
|
if (rotation == null) {
|
||||||
|
@ -199,8 +202,8 @@ public class ContraptionCollider {
|
||||||
// Prepare entity bounds
|
// Prepare entity bounds
|
||||||
OrientedBB obb = new OrientedBB(localBB);
|
OrientedBB obb = new OrientedBB(localBB);
|
||||||
obb.setRotation(rotation);
|
obb.setRotation(rotation);
|
||||||
motion = motion.subtract(conMotion);
|
|
||||||
motion = rotation.transform(motion);
|
motion = rotation.transform(motion);
|
||||||
|
motion = motion.subtract(contraptionMotion);
|
||||||
|
|
||||||
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
|
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
|
||||||
// CollisionDebugger.OBB = obb.copy();
|
// CollisionDebugger.OBB = obb.copy();
|
||||||
|
@ -268,7 +271,7 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
rotation.transpose();
|
rotation.transpose();
|
||||||
motionResponse = rotation.transform(motionResponse)
|
motionResponse = rotation.transform(motionResponse)
|
||||||
.add(conMotion);
|
.add(contraptionMotion);
|
||||||
totalResponse = rotation.transform(totalResponse);
|
totalResponse = rotation.transform(totalResponse);
|
||||||
rotation.transpose();
|
rotation.transpose();
|
||||||
|
|
||||||
|
@ -282,9 +285,9 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
Vec3d contactPointMotion = Vec3d.ZERO;
|
Vec3d contactPointMotion = Vec3d.ZERO;
|
||||||
if (surfaceCollision.isTrue()) {
|
if (surfaceCollision.isTrue()) {
|
||||||
// entity.handleFallDamage(entity.fallDistance, 1); tunnelling issue
|
|
||||||
entity.fallDistance = 0;
|
entity.fallDistance = 0;
|
||||||
entity.onGround = true;
|
entity.onGround = true;
|
||||||
|
contraptionEntity.collidingEntities.add(entity);
|
||||||
if (!serverPlayer)
|
if (!serverPlayer)
|
||||||
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
||||||
}
|
}
|
||||||
|
@ -321,6 +324,9 @@ public class ContraptionCollider {
|
||||||
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
||||||
entityPosition.z + allowedMovement.z);
|
entityPosition.z + allowedMovement.z);
|
||||||
entity.setMotion(entityMotion);
|
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.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.MutablePair;
|
import org.apache.commons.lang3.tuple.MutablePair;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.simibubi.create.AllEntityTypes;
|
import com.simibubi.create.AllEntityTypes;
|
||||||
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption;
|
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.DamageSource;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.ReuseableStream;
|
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
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.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
@ -166,9 +159,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
passenger.startRiding(this, true);
|
passenger.startRiding(this, true);
|
||||||
if (world.isRemote)
|
if (world.isRemote)
|
||||||
return;
|
return;
|
||||||
contraption.seatMapping.put(passenger.getUniqueID(), seatIndex);
|
contraption.getSeatMapping()
|
||||||
|
.put(passenger.getUniqueID(), seatIndex);
|
||||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||||
new ContraptionSeatMappingPacket(getEntityId(), contraption.seatMapping));
|
new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -185,9 +179,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
if (transformedVector != null)
|
if (transformedVector != null)
|
||||||
passenger.getPersistentData()
|
passenger.getPersistentData()
|
||||||
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
|
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
|
||||||
contraption.seatMapping.remove(passenger.getUniqueID());
|
contraption.getSeatMapping()
|
||||||
|
.remove(passenger.getUniqueID());
|
||||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||||
new ContraptionSeatMappingPacket(getEntityId(), contraption.seatMapping));
|
new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -214,18 +209,21 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean canFitPassenger(Entity p_184219_1_) {
|
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,
|
public boolean handlePlayerInteraction(PlayerEntity player, BlockPos localPos, Direction side,
|
||||||
Hand interactionHand) {
|
Hand interactionHand) {
|
||||||
int indexOfSeat = contraption.seats.indexOf(localPos);
|
int indexOfSeat = contraption.getSeats()
|
||||||
|
.indexOf(localPos);
|
||||||
if (indexOfSeat == -1)
|
if (indexOfSeat == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Eject potential existing passenger
|
// Eject potential existing passenger
|
||||||
Entity toDismount = null;
|
Entity toDismount = null;
|
||||||
for (Entry<UUID, Integer> entry : contraption.seatMapping.entrySet()) {
|
for (Entry<UUID, Integer> entry : contraption.getSeatMapping()
|
||||||
|
.entrySet()) {
|
||||||
if (entry.getValue() != indexOfSeat)
|
if (entry.getValue() != indexOfSeat)
|
||||||
continue;
|
continue;
|
||||||
for (Entity entity : getPassengers()) {
|
for (Entity entity : getPassengers()) {
|
||||||
|
@ -631,9 +629,20 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
remove();
|
remove();
|
||||||
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
|
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
|
||||||
Vec3d rotation = getRotationVec();
|
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();
|
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
|
@Override
|
||||||
protected void doWaterSplashEffect() {}
|
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")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT writeWithoutTypeId(CompoundNBT nbt) {
|
public CompoundNBT writeWithoutTypeId(CompoundNBT nbt) {
|
||||||
Vec3d vec = getPositionVec();
|
Vec3d vec = getPositionVec();
|
||||||
List<Entity> passengers = getPassengers();
|
List<Entity> passengers = getPassengers();
|
||||||
List<Vec3d> positionVecs = new ArrayList<>(passengers.size());
|
|
||||||
|
|
||||||
for (Entity entity : passengers) {
|
for (Entity entity : passengers) {
|
||||||
Vec3d prevVec = entity.getPositionVec();
|
|
||||||
positionVecs.add(prevVec);
|
|
||||||
|
|
||||||
// setPos has world accessing side-effects when removed == false
|
// setPos has world accessing side-effects when removed == false
|
||||||
entity.removed = true;
|
entity.removed = true;
|
||||||
|
|
||||||
// Gather passengers into same chunk when saving
|
// Gather passengers into same chunk when saving
|
||||||
|
Vec3d prevVec = entity.getPositionVec();
|
||||||
entity.setPos(vec.x, prevVec.y, vec.z);
|
entity.setPos(vec.x, prevVec.y, vec.z);
|
||||||
|
|
||||||
// Super requires all passengers to not be removed in order to write them to the
|
// 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.block.BlockState;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
@ -17,6 +18,7 @@ public class MovementContext {
|
||||||
public Vec3d rotation;
|
public Vec3d rotation;
|
||||||
public World world;
|
public World world;
|
||||||
public BlockState state;
|
public BlockState state;
|
||||||
|
public BlockPos localPos;
|
||||||
public CompoundNBT tileData;
|
public CompoundNBT tileData;
|
||||||
|
|
||||||
public boolean stall;
|
public boolean stall;
|
||||||
|
@ -29,6 +31,7 @@ public class MovementContext {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.state = info.state;
|
this.state = info.state;
|
||||||
this.tileData = info.nbt;
|
this.tileData = info.nbt;
|
||||||
|
localPos = info.pos;
|
||||||
|
|
||||||
firstMovement = true;
|
firstMovement = true;
|
||||||
motion = Vec3d.ZERO;
|
motion = 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) {
|
public BlockPos apply(BlockPos localPos) {
|
||||||
Vec3d vec = VecHelper.getCenterOf(localPos);
|
Vec3d vec = VecHelper.getCenterOf(localPos);
|
||||||
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
|
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
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.ContraptionInteractionPacket;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionSeatMappingPacket;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionSeatMappingPacket;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
|
||||||
|
@ -46,6 +47,7 @@ public enum AllPackets {
|
||||||
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
|
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
|
||||||
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
|
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
|
||||||
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new),
|
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new),
|
||||||
|
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new),
|
||||||
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
|
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
|
||||||
|
|
||||||
// Server to Client
|
// Server to Client
|
||||||
|
|
Loading…
Reference in a new issue