Moving Entities is fun

- Refined rotation behaviour of turntable
- Fixed Belts moving entities incosistenly
- Fixed Living entities getting stuck on belt slopes
- Improved the applied motion when entities leave fast belts
- Entities now try to stay spaced apart on belts
This commit is contained in:
simibubi 2019-08-19 12:32:04 +02:00
parent ce7356798c
commit b657c6e389
3 changed files with 84 additions and 31 deletions

View file

@ -0,0 +1,32 @@
package com.simibubi.create.foundation.utility;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
public class VecHelper {
public static Vec3d rotate(Vec3d vec, float deg, Axis axis) {
float angle = (float) (deg / 180f * Math.PI);
double sin = MathHelper.sin(angle);
double cos = MathHelper.cos(angle);
double x = vec.x;
double y = vec.y;
double z = vec.z;
if (axis == Axis.X)
return new Vec3d(x, y * cos - z * sin, z * cos + y * sin);
if (axis == Axis.Y)
return new Vec3d(x * cos + z * sin, y, z * cos - x * sin);
if (axis == Axis.Z)
return new Vec3d(x * cos - y * sin, y * cos + x * sin, z);
return vec;
}
public static Vec3d getCenterOf(Vec3i pos) {
return new Vec3d(pos).add(.5f, .5f, .5f);
}
}

View file

@ -1,5 +1,6 @@
package com.simibubi.create.modules.contraptions.receivers; package com.simibubi.create.modules.contraptions.receivers;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticBlock; import com.simibubi.create.modules.contraptions.base.KineticBlock;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
@ -13,6 +14,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.shapes.VoxelShapes;
@ -40,37 +42,51 @@ public class TurntableBlock extends KineticBlock {
} }
@Override @Override
public void onLanded(IBlockReader worldIn, Entity e) { public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity e) {
TileEntity te = worldIn.getTileEntity(e.getPosition()); TileEntity te = worldIn.getTileEntity(pos);
if (!(te instanceof KineticTileEntity)) if (!(te instanceof KineticTileEntity))
return; return;
if (!e.onGround)
return;
if (e.getMotion().y > 0)
return;
float speed = ((KineticTileEntity) te).getSpeed() / 20; float speed = ((KineticTileEntity) te).getSpeed() / 20;
World world = e.getEntityWorld(); World world = e.getEntityWorld();
if (speed == 0) { if (speed == 0)
super.onLanded(worldIn, e);
return; return;
} if (e.posY < pos.getY() + .5f)
if (world.isRemote) {
super.onLanded(worldIn, e);
return; return;
}
if ((e instanceof PlayerEntity)) { Vec3d origin = VecHelper.getCenterOf(pos);
super.onLanded(worldIn, e); Vec3d offset = e.getPositionVec().subtract(origin);
if (!world.isRemote && (e instanceof PlayerEntity))
return; return;
if (offset.length() > 1/16f) {
offset = VecHelper.rotate(offset, speed / 1f, Axis.Y);
Vec3d movement = origin.add(offset).subtract(e.getPositionVec());
e.setMotion(e.getMotion().add(movement));
e.velocityChanged = true;
} }
if (world.isRemote)
return;
if ((e instanceof PlayerEntity))
return;
if ((e instanceof LivingEntity)) { if ((e instanceof LivingEntity)) {
float offset = e.getRotationYawHead() - speed; float diff = e.getRotationYawHead() - speed;
e.setRenderYawOffset(offset); ((LivingEntity) e).setIdleTime(20);
e.setRotationYawHead(offset); e.setRenderYawOffset(diff);
super.onLanded(worldIn, e); e.setRotationYawHead(diff);
return; return;
} }
e.rotationYaw -= speed; e.rotationYaw -= speed;
super.onLanded(worldIn, e);
} }
// IRotate: // IRotate:

View file

@ -25,6 +25,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Direction.AxisDirection;
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.Vec3i; import net.minecraft.util.math.Vec3i;
@ -120,14 +121,10 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition()); TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
BlockState blockState = info.lastCollidedState; BlockState blockState = info.lastCollidedState;
boolean onEndingBelt = blockState.getBlock() instanceof BeltBlock && BeltBlock.isUpperEnd(blockState, speed);
Direction movementFacing = Direction.getFacingFromAxisDirection( Direction movementFacing = Direction.getFacingFromAxisDirection(
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(), blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
speed < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE); speed < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE);
boolean hasBeltAdjacent = onEndingBelt
&& AllBlocks.BELT.typeOf(world.getBlockState(pos.offset(movementFacing)));
boolean collidedWithBelt = te instanceof BeltTileEntity; boolean collidedWithBelt = te instanceof BeltTileEntity;
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te; boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
@ -143,7 +140,7 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
return; return;
if (entityIn instanceof LivingEntity) { if (entityIn instanceof LivingEntity) {
((LivingEntity) entityIn).setIdleTime(20); ((LivingEntity) entityIn).setIdleTime(101);
} }
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
@ -175,7 +172,7 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
movingDown = movingUp; movingDown = movingUp;
movingUp = b; movingUp = b;
} }
if (movingUp) if (movingUp)
movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0); movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
if (movingDown) if (movingDown)
@ -184,18 +181,22 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4); Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4);
movement = movement.add(centering); movement = movement.add(centering);
if (info.ticksSinceLastCollision > 0 && !betweenBelts && onEndingBelt && !hasBeltAdjacent) {
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
float verticalMultiplier = entityIn instanceof ItemEntity ? .25f : 1;
if (movementSpeed > .25f)
movement = movement.add(0, Math.abs(movementSpeed) * verticalMultiplier, 0);
entityIn.setMotion(movement);
return;
}
float step = entityIn.stepHeight; float step = entityIn.stepHeight;
entityIn.stepHeight = 1; entityIn.stepHeight = 1;
if (Math.abs(movementSpeed) < .5f) {
Vec3d checkDistance = movement.scale(2f).add(movement.normalize().scale(.5));
AxisAlignedBB bb = entityIn.getBoundingBox();
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
if (!world
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
.isEmpty()) {
entityIn.setMotion(0, 0, 0);
return;
}
}
if (movingUp) { if (movingUp) {
float minVelocity = entityIn instanceof ItemEntity ? .09f : .13f; float minVelocity = entityIn instanceof ItemEntity ? .09f : .13f;
float yMovement = (float) (Math.signum(movementSpeed) * Math.max(Math.abs(movement.y), minVelocity)); float yMovement = (float) (Math.signum(movementSpeed) * Math.max(Math.abs(movement.y), minVelocity));
@ -209,7 +210,11 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
} }
entityIn.stepHeight = step; entityIn.stepHeight = step;
if (!betweenBelts && onEndingBelt && !hasBeltAdjacent) { boolean movedPastEndingSlope = onSlope && AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition()))
|| AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition().down()));
if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > .25f) {
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
entityIn.setMotion(movement); entityIn.setMotion(movement);
} }
} }