mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
Collision tweaks
- Fixed pulleys/pistons crashing when collided with blocks on client - Entities moved by a colliding contraption now try to unstuck themselves when the structure disassembles
This commit is contained in:
parent
6031d9fce1
commit
8cb5dac2c9
3 changed files with 79 additions and 13 deletions
|
@ -39,6 +39,7 @@ public class ContraptionCollider {
|
||||||
Contraption contraption = contraptionEntity.getContraption();
|
Contraption contraption = contraptionEntity.getContraption();
|
||||||
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
||||||
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
|
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
|
||||||
|
contraptionEntity.collidingEntities.clear();
|
||||||
|
|
||||||
if (contraption == null)
|
if (contraption == null)
|
||||||
return;
|
return;
|
||||||
|
@ -60,7 +61,9 @@ public class ContraptionCollider {
|
||||||
Vec3d allowedMovement = Entity.getAllowedMovement(relativeMotion, entityBB, world,
|
Vec3d allowedMovement = Entity.getAllowedMovement(relativeMotion, entityBB, world,
|
||||||
ISelectionContext.forEntity(entity), potentialHits);
|
ISelectionContext.forEntity(entity), potentialHits);
|
||||||
potentialHits.createStream()
|
potentialHits.createStream()
|
||||||
.forEach(voxelShape -> pushEntityOutOfShape(entity, voxelShape, positionOffset));
|
.forEach(voxelShape -> pushEntityOutOfShape(entity, voxelShape, positionOffset, contraptionMotion));
|
||||||
|
|
||||||
|
contraptionEntity.collidingEntities.add(entity);
|
||||||
|
|
||||||
if (allowedMovement.equals(relativeMotion))
|
if (allowedMovement.equals(relativeMotion))
|
||||||
continue;
|
continue;
|
||||||
|
@ -79,7 +82,8 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void pushEntityOutOfShape(Entity entity, VoxelShape voxelShape, Vec3d positionOffset) {
|
public static void pushEntityOutOfShape(Entity entity, VoxelShape voxelShape, Vec3d positionOffset,
|
||||||
|
Vec3d shapeMotion) {
|
||||||
AxisAlignedBB entityBB = entity.getBoundingBox().offset(positionOffset);
|
AxisAlignedBB entityBB = entity.getBoundingBox().offset(positionOffset);
|
||||||
Vec3d entityMotion = entity.getMotion();
|
Vec3d entityMotion = entity.getMotion();
|
||||||
|
|
||||||
|
@ -117,18 +121,20 @@ public class ContraptionCollider {
|
||||||
double clamped;
|
double clamped;
|
||||||
switch (bestSide.getAxis()) {
|
switch (bestSide.getAxis()) {
|
||||||
case X:
|
case X:
|
||||||
clamped = positive ? Math.max(0, entityMotion.x) : Math.min(0, entityMotion.x);
|
clamped = positive ? Math.max(shapeMotion.x, entityMotion.x) : Math.min(shapeMotion.x, entityMotion.x);
|
||||||
entity.setMotion(clamped, entityMotion.y, entityMotion.z);
|
entity.setMotion(clamped, entityMotion.y, entityMotion.z);
|
||||||
break;
|
break;
|
||||||
case Y:
|
case Y:
|
||||||
clamped = positive ? Math.max(0, entityMotion.y) : Math.min(0, entityMotion.y);
|
clamped = positive ? Math.max(shapeMotion.y, entityMotion.y) : Math.min(shapeMotion.y, entityMotion.y);
|
||||||
|
if (bestSide == Direction.UP)
|
||||||
|
clamped = shapeMotion.y;
|
||||||
entity.setMotion(entityMotion.x, clamped, entityMotion.z);
|
entity.setMotion(entityMotion.x, clamped, entityMotion.z);
|
||||||
entity.fall(entity.fallDistance, 1);
|
entity.fall(entity.fallDistance, 1);
|
||||||
entity.fallDistance = 0;
|
entity.fallDistance = 0;
|
||||||
entity.onGround = true;
|
entity.onGround = true;
|
||||||
break;
|
break;
|
||||||
case Z:
|
case Z:
|
||||||
clamped = positive ? Math.max(0, entityMotion.z) : Math.min(0, entityMotion.z);
|
clamped = positive ? Math.max(shapeMotion.z, entityMotion.z) : Math.min(shapeMotion.z, entityMotion.z);
|
||||||
entity.setMotion(entityMotion.x, entityMotion.y, clamped);
|
entity.setMotion(entityMotion.x, entityMotion.y, clamped);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,13 @@ package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||||
import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp;
|
import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp;
|
||||||
import static com.simibubi.create.foundation.utility.AngleHelper.getShortestAngleDiff;
|
import static com.simibubi.create.foundation.utility.AngleHelper.getShortestAngleDiff;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
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.AllEntities;
|
import com.simibubi.create.AllEntities;
|
||||||
import com.simibubi.create.AllPackets;
|
import com.simibubi.create.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -27,9 +32,14 @@ import net.minecraft.network.datasync.DataSerializers;
|
||||||
import net.minecraft.network.datasync.EntityDataManager;
|
import net.minecraft.network.datasync.EntityDataManager;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
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.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.minecraft.world.server.ServerWorld;
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
@ -48,6 +58,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
protected Vec3d motionBeforeStall;
|
protected Vec3d motionBeforeStall;
|
||||||
protected boolean stationary;
|
protected boolean stationary;
|
||||||
|
|
||||||
|
final List<Entity> collidingEntities = new ArrayList<>();
|
||||||
|
|
||||||
private static final DataParameter<Boolean> STALLED =
|
private static final DataParameter<Boolean> STALLED =
|
||||||
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
|
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
|
||||||
|
|
||||||
|
@ -400,12 +412,61 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
|
|
||||||
public void disassemble() {
|
public void disassemble() {
|
||||||
if (getContraption() != null) {
|
if (getContraption() != null) {
|
||||||
getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)),
|
BlockPos offset = new BlockPos(getPositionVec().add(.5, .5, .5));
|
||||||
new Vec3d(getRoll(1), getYaw(1), getPitch(1)));
|
Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1));
|
||||||
|
getContraption().disassemble(world, offset, rotation);
|
||||||
|
preventMovedEntitiesFromGettingStuck();
|
||||||
}
|
}
|
||||||
remove();
|
remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preventMovedEntitiesFromGettingStuck() {
|
||||||
|
Vec3d stuckTest = new Vec3d(0, -2, 0);
|
||||||
|
for (Entity e : collidingEntities) {
|
||||||
|
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.posX + vec.x, e.posY + vec.y, e.posZ + vec.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Contraption getContraption() {
|
public Contraption getContraption() {
|
||||||
return contraption;
|
return contraption;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,8 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
boolean contraptionPresent = movedContraption != null;
|
|
||||||
|
|
||||||
if (contraptionPresent) {
|
if (movedContraption != null) {
|
||||||
movedContraption.collisionTick();
|
movedContraption.collisionTick();
|
||||||
if (!movedContraption.isAlive())
|
if (!movedContraption.isAlive())
|
||||||
movedContraption = null;
|
movedContraption = null;
|
||||||
|
@ -59,7 +58,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
|
||||||
if (world.isRemote)
|
if (world.isRemote)
|
||||||
clientOffsetDiff *= .75f;
|
clientOffsetDiff *= .75f;
|
||||||
|
|
||||||
if (waitingForSpeedChange && contraptionPresent) {
|
if (waitingForSpeedChange && movedContraption != null) {
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
float syncSpeed = clientOffsetDiff / 2f;
|
float syncSpeed = clientOffsetDiff / 2f;
|
||||||
offset += syncSpeed;
|
offset += syncSpeed;
|
||||||
|
@ -86,7 +85,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
|
||||||
if (!running)
|
if (!running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
contraptionPresent = movedContraption != null;
|
boolean contraptionPresent = movedContraption != null;
|
||||||
float movementSpeed = getMovementSpeed();
|
float movementSpeed = getMovementSpeed();
|
||||||
float newOffset = offset + movementSpeed;
|
float newOffset = offset + movementSpeed;
|
||||||
if ((int) newOffset != (int) offset)
|
if ((int) newOffset != (int) offset)
|
||||||
|
|
Loading…
Reference in a new issue