2020-04-24 03:25:58 +02:00
|
|
|
package net.minestom.server.entity;
|
2019-08-10 08:44:35 +02:00
|
|
|
|
2020-04-24 03:25:58 +02:00
|
|
|
import net.minestom.server.collision.CollisionUtils;
|
|
|
|
import net.minestom.server.entity.pathfinding.EntityPathFinder;
|
|
|
|
import net.minestom.server.entity.property.Attribute;
|
|
|
|
import net.minestom.server.network.packet.server.play.*;
|
|
|
|
import net.minestom.server.network.player.PlayerConnection;
|
|
|
|
import net.minestom.server.utils.BlockPosition;
|
|
|
|
import net.minestom.server.utils.ChunkUtils;
|
|
|
|
import net.minestom.server.utils.Position;
|
|
|
|
import net.minestom.server.utils.Vector;
|
2019-08-10 08:44:35 +02:00
|
|
|
|
2020-04-09 14:25:42 +02:00
|
|
|
import java.util.LinkedList;
|
2020-04-25 23:51:45 +02:00
|
|
|
import java.util.function.Consumer;
|
2019-08-10 08:44:35 +02:00
|
|
|
|
2020-04-09 14:25:42 +02:00
|
|
|
public abstract class EntityCreature extends LivingEntity {
|
2020-03-29 20:58:30 +02:00
|
|
|
|
2020-04-09 14:25:42 +02:00
|
|
|
private EntityPathFinder pathFinder = new EntityPathFinder(this);
|
|
|
|
private LinkedList<BlockPosition> blockPositions;
|
|
|
|
private Position targetPosition;
|
2020-03-29 20:58:30 +02:00
|
|
|
|
2020-04-09 14:25:42 +02:00
|
|
|
public EntityCreature(EntityType entityType, Position spawnPosition) {
|
|
|
|
super(entityType.getId(), spawnPosition);
|
2019-08-10 08:44:35 +02:00
|
|
|
}
|
|
|
|
|
2019-08-24 20:34:01 +02:00
|
|
|
@Override
|
|
|
|
public void update() {
|
|
|
|
super.update();
|
2020-04-09 14:25:42 +02:00
|
|
|
|
|
|
|
// Path finding
|
|
|
|
if (blockPositions != null) {
|
|
|
|
if (targetPosition != null) {
|
|
|
|
float distance = getPosition().getDistance(targetPosition);
|
2020-04-23 01:26:45 +02:00
|
|
|
//System.out.println("test: "+distance);
|
|
|
|
if (distance < 0.7f) {
|
2020-04-09 14:25:42 +02:00
|
|
|
setNextPathPosition();
|
|
|
|
//System.out.println("END TARGET");
|
|
|
|
} else {
|
|
|
|
moveTowards(targetPosition, getAttributeValue(Attribute.MOVEMENT_SPEED));
|
|
|
|
//System.out.println("MOVE TOWARD " + targetPosition);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-24 20:34:01 +02:00
|
|
|
}
|
|
|
|
|
2019-08-30 01:17:46 +02:00
|
|
|
public void move(float x, float y, float z, boolean updateView) {
|
2019-08-21 16:50:52 +02:00
|
|
|
Position position = getPosition();
|
|
|
|
float newX = position.getX() + x;
|
|
|
|
float newY = position.getY() + y;
|
|
|
|
float newZ = position.getZ() + z;
|
2020-05-02 23:34:09 +02:00
|
|
|
Position newPosition = new Position();
|
2020-04-22 19:09:57 +02:00
|
|
|
// Calculate collisions boxes
|
2020-05-02 23:34:09 +02:00
|
|
|
onGround = CollisionUtils.handlePhysics(this, new Vector(x, y, z), newPosition, new Vector());
|
2020-04-22 19:09:57 +02:00
|
|
|
// Refresh target position
|
|
|
|
newX = newPosition.getX();
|
|
|
|
newY = newPosition.getY();
|
|
|
|
newZ = newPosition.getZ();
|
2019-08-11 13:57:23 +02:00
|
|
|
|
2020-02-11 16:48:06 +01:00
|
|
|
// Creatures cannot move in unload chunk
|
2019-08-27 20:49:11 +02:00
|
|
|
if (ChunkUtils.isChunkUnloaded(getInstance(), newX, newZ))
|
2019-08-11 13:57:23 +02:00
|
|
|
return;
|
|
|
|
|
2019-08-29 02:15:52 +02:00
|
|
|
float lastYaw = position.getYaw();
|
|
|
|
float radians = (float) Math.atan2(newZ - position.getZ(), newX - position.getX());
|
|
|
|
|
|
|
|
float yaw = (float) (radians * (180.0 / Math.PI)) - 90;
|
|
|
|
float pitch = position.getPitch(); // TODO
|
|
|
|
|
2020-02-11 16:48:06 +01:00
|
|
|
short deltaX = (short) ((newX * 32 - position.getX() * 32) * 128);
|
|
|
|
short deltaY = (short) ((newY * 32 - position.getY() * 32) * 128);
|
|
|
|
short deltaZ = (short) ((newZ * 32 - position.getZ() * 32) * 128);
|
|
|
|
|
2019-08-30 01:17:46 +02:00
|
|
|
if (updateView) {
|
2020-02-11 16:48:06 +01:00
|
|
|
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
|
|
|
|
entityPositionAndRotationPacket.entityId = getEntityId();
|
|
|
|
entityPositionAndRotationPacket.deltaX = deltaX;
|
|
|
|
entityPositionAndRotationPacket.deltaY = deltaY;
|
|
|
|
entityPositionAndRotationPacket.deltaZ = deltaZ;
|
|
|
|
entityPositionAndRotationPacket.yaw = yaw;
|
|
|
|
entityPositionAndRotationPacket.pitch = pitch;
|
|
|
|
entityPositionAndRotationPacket.onGround = isOnGround();
|
|
|
|
sendPacketToViewers(entityPositionAndRotationPacket);
|
2019-08-30 01:17:46 +02:00
|
|
|
} else {
|
2020-02-11 16:48:06 +01:00
|
|
|
EntityPositionPacket entityPositionPacket = new EntityPositionPacket();
|
|
|
|
entityPositionPacket.entityId = getEntityId();
|
|
|
|
entityPositionPacket.deltaX = deltaX;
|
|
|
|
entityPositionPacket.deltaY = deltaY;
|
|
|
|
entityPositionPacket.deltaZ = deltaZ;
|
|
|
|
entityPositionPacket.onGround = isOnGround();
|
|
|
|
sendPacketToViewers(entityPositionPacket);
|
2019-08-30 01:17:46 +02:00
|
|
|
}
|
2019-08-29 02:15:52 +02:00
|
|
|
|
|
|
|
if (lastYaw != yaw) {
|
|
|
|
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
|
|
|
|
entityHeadLookPacket.entityId = getEntityId();
|
|
|
|
entityHeadLookPacket.yaw = yaw;
|
|
|
|
sendPacketToViewers(entityHeadLookPacket);
|
2019-08-30 01:17:46 +02:00
|
|
|
refreshView(yaw, pitch);
|
2019-08-29 02:15:52 +02:00
|
|
|
}
|
2019-08-11 13:57:23 +02:00
|
|
|
|
|
|
|
refreshPosition(newX, newY, newZ);
|
2019-08-29 02:15:52 +02:00
|
|
|
}
|
|
|
|
|
2019-08-24 20:34:01 +02:00
|
|
|
@Override
|
2019-08-21 16:50:52 +02:00
|
|
|
public void kill() {
|
2020-04-05 10:15:21 +02:00
|
|
|
super.kill();
|
|
|
|
|
|
|
|
// Needed for proper death animation (wait for it to finish before destroying the entity)
|
|
|
|
scheduleRemove(1000);
|
2019-08-11 13:57:23 +02:00
|
|
|
}
|
|
|
|
|
2019-08-19 17:04:19 +02:00
|
|
|
@Override
|
2019-08-10 08:44:35 +02:00
|
|
|
public void addViewer(Player player) {
|
2019-08-20 17:41:07 +02:00
|
|
|
super.addViewer(player);
|
2019-08-10 08:44:35 +02:00
|
|
|
PlayerConnection playerConnection = player.getPlayerConnection();
|
|
|
|
|
|
|
|
EntityPacket entityPacket = new EntityPacket();
|
|
|
|
entityPacket.entityId = getEntityId();
|
2020-02-09 15:34:09 +01:00
|
|
|
|
2020-03-29 20:58:30 +02:00
|
|
|
SpawnLivingEntityPacket spawnLivingEntityPacket = new SpawnLivingEntityPacket();
|
|
|
|
spawnLivingEntityPacket.entityId = getEntityId();
|
|
|
|
spawnLivingEntityPacket.entityUuid = getUuid();
|
|
|
|
spawnLivingEntityPacket.entityType = getEntityType();
|
|
|
|
spawnLivingEntityPacket.position = getPosition();
|
|
|
|
spawnLivingEntityPacket.headPitch = 0;
|
2020-02-09 15:34:09 +01:00
|
|
|
|
2019-08-10 08:44:35 +02:00
|
|
|
playerConnection.sendPacket(entityPacket);
|
2020-03-29 20:58:30 +02:00
|
|
|
playerConnection.sendPacket(spawnLivingEntityPacket);
|
2020-02-11 16:48:06 +01:00
|
|
|
playerConnection.sendPacket(getMetadataPacket());
|
2019-08-10 08:44:35 +02:00
|
|
|
}
|
2020-04-09 14:25:42 +02:00
|
|
|
|
|
|
|
public void jump(float height) {
|
|
|
|
// FIXME magic value
|
2020-04-25 23:06:16 +02:00
|
|
|
Vector velocity = new Vector(0, height * 10, 0);
|
2020-05-02 23:34:09 +02:00
|
|
|
setVelocity(velocity);
|
2020-04-09 14:25:42 +02:00
|
|
|
}
|
|
|
|
|
2020-04-25 23:58:17 +02:00
|
|
|
public void setPathTo(Position position, int maxCheck, Consumer<Boolean> resultConsumer) {
|
|
|
|
pathFinder.getPath(position, maxCheck, blockPositions -> {
|
2020-04-25 23:06:16 +02:00
|
|
|
if (blockPositions == null || blockPositions.isEmpty()) {
|
2020-04-23 01:26:45 +02:00
|
|
|
// Didn't find path
|
2020-04-25 23:51:45 +02:00
|
|
|
if (resultConsumer != null)
|
|
|
|
resultConsumer.accept(false);
|
2020-04-23 01:26:45 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-04-25 23:51:45 +02:00
|
|
|
blockPositions.pollFirst(); // Remove first entry (where the entity is)
|
|
|
|
|
2020-04-09 14:25:42 +02:00
|
|
|
this.blockPositions = blockPositions;
|
|
|
|
setNextPathPosition();
|
2020-04-25 23:51:45 +02:00
|
|
|
|
|
|
|
if (resultConsumer != null)
|
|
|
|
resultConsumer.accept(true);
|
2020-04-09 14:25:42 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-04-25 23:58:17 +02:00
|
|
|
public void setPathTo(Position position, int maxCheck) {
|
|
|
|
setPathTo(position, maxCheck, null);
|
|
|
|
}
|
|
|
|
|
2020-04-25 23:51:45 +02:00
|
|
|
public void setPathTo(Position position) {
|
2020-04-25 23:58:17 +02:00
|
|
|
setPathTo(position, 1000, null);
|
2020-04-25 23:51:45 +02:00
|
|
|
}
|
|
|
|
|
2020-04-09 14:25:42 +02:00
|
|
|
public void moveTowards(Position direction, float speed) {
|
|
|
|
float radians = (float) Math.atan2(direction.getZ() - position.getZ(), direction.getX() - position.getX());
|
|
|
|
float speedX = (float) (Math.cos(radians) * speed);
|
|
|
|
float speedZ = (float) (Math.sin(radians) * speed);
|
|
|
|
move(speedX, 0, speedZ, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setNextPathPosition() {
|
|
|
|
BlockPosition blockPosition = blockPositions.pollFirst();
|
|
|
|
|
|
|
|
if (blockPosition == null) {
|
|
|
|
this.blockPositions = null;
|
|
|
|
this.targetPosition = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-23 01:26:45 +02:00
|
|
|
this.targetPosition = blockPosition.toPosition();//.add(0.5f, 0, 0.5f);
|
2020-04-22 02:42:58 +02:00
|
|
|
// FIXME: jump support
|
2020-04-23 01:26:45 +02:00
|
|
|
if (blockPosition.getY() > getPosition().getY())
|
|
|
|
jump(1);
|
2020-04-09 14:25:42 +02:00
|
|
|
}
|
2019-08-10 08:44:35 +02:00
|
|
|
}
|