Initial position api implementation

This commit is contained in:
TheMode 2021-07-06 20:44:24 +02:00
parent 6275154997
commit 28dca16b29
51 changed files with 541 additions and 737 deletions

View File

@ -15,7 +15,6 @@ import net.minestom.server.network.packet.server.play.SoundEffectPacket;
import net.minestom.server.network.packet.server.play.StopSoundPacket;
import net.minestom.server.registry.Registries;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.utils.Position;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@ -25,6 +24,7 @@ import java.util.Collection;
*/
public class AdventurePacketConvertor {
private static final Object2IntMap<NamedTextColor> NAMED_TEXT_COLOR_ID_MAP = new Object2IntArrayMap<>(16);
static {
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.BLACK, 0);
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.DARK_BLUE, 1);
@ -102,9 +102,9 @@ public class AdventurePacketConvertor {
* Creates a sound packet from a sound and a location.
*
* @param sound the sound
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return the sound packet
*/
public static @NotNull ServerPacket createSoundPacket(@NotNull Sound sound, double x, double y, double z) {
@ -136,7 +136,7 @@ public class AdventurePacketConvertor {
/**
* Creates a sound effect packet from a sound and an emitter.
*
* @param sound the sound
* @param sound the sound
* @param emitter the emitter, must be an {@link Entity}
* @return the sound packet
*/
@ -158,14 +158,13 @@ public class AdventurePacketConvertor {
packet.pitch = sound.pitch();
return packet;
} else {
final Position pos = entity.getPosition();
final var pos = entity.getPosition();
final NamedSoundEffectPacket packet = new NamedSoundEffectPacket();
packet.soundName = sound.name().asString();
packet.soundSource = sound.source();
packet.x = (int) pos.getX();
packet.y = (int) pos.getY();
packet.z = (int) pos.getX();
packet.x = (int) pos.x();
packet.y = (int) pos.y();
packet.z = (int) pos.z();
packet.volume = sound.volume();
packet.pitch = sound.pitch();
return packet;
@ -175,7 +174,7 @@ public class AdventurePacketConvertor {
/**
* Creates an entity sound packet from an Adventure sound.
*
* @param sound the sound
* @param sound the sound
* @param entity the entity the sound is coming from
* @return the packet
* @deprecated Use {@link #createSoundPacket(Sound, Sound.Emitter)}

View File

@ -150,7 +150,7 @@ public class BoundingBox {
* @return the min X
*/
public double getMinX() {
return entity.getPosition().getX() - (x / 2);
return entity.getPosition().x() - (x / 2);
}
/**
@ -159,7 +159,7 @@ public class BoundingBox {
* @return the max X
*/
public double getMaxX() {
return entity.getPosition().getX() + (x / 2);
return entity.getPosition().x() + (x / 2);
}
/**
@ -168,7 +168,7 @@ public class BoundingBox {
* @return the min Y
*/
public double getMinY() {
return entity.getPosition().getY();
return entity.getPosition().y();
}
/**
@ -177,7 +177,7 @@ public class BoundingBox {
* @return the max Y
*/
public double getMaxY() {
return entity.getPosition().getY() + y;
return entity.getPosition().y() + y;
}
/**
@ -186,7 +186,7 @@ public class BoundingBox {
* @return the min Z
*/
public double getMinZ() {
return entity.getPosition().getZ() - (z / 2);
return entity.getPosition().z() - (z / 2);
}
/**
@ -195,7 +195,7 @@ public class BoundingBox {
* @return the max Z
*/
public double getMaxZ() {
return entity.getPosition().getZ() + (z / 2);
return entity.getPosition().z() + (z / 2);
}
/**

View File

@ -9,6 +9,8 @@ import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
public class CollisionUtils {
@ -190,8 +192,8 @@ public class CollisionUtils {
* @return the position with the world border collision applied (can be {@code newPosition} if not changed)
*/
@NotNull
public static Position applyWorldBorder(@NotNull Instance instance,
@NotNull Position currentPosition, @NotNull Position newPosition) {
public static Point applyWorldBorder(@NotNull Instance instance,
@NotNull Point currentPosition, @NotNull Point newPosition) {
final WorldBorder worldBorder = instance.getWorldBorder();
final WorldBorder.CollisionAxis collisionAxis = worldBorder.getCollisionAxis(newPosition);
switch (collisionAxis) {
@ -200,13 +202,13 @@ public class CollisionUtils {
return newPosition;
case BOTH:
// Apply Y velocity/gravity
return new Position(currentPosition.getX(), newPosition.getY(), currentPosition.getZ());
return new Vec(currentPosition.x(), newPosition.y(), currentPosition.z());
case X:
// Apply Y/Z velocity/gravity
return new Position(currentPosition.getX(), newPosition.getY(), newPosition.getZ());
return new Vec(currentPosition.x(), newPosition.y(), newPosition.z());
case Z:
// Apply X/Y velocity/gravity
return new Position(newPosition.getX(), newPosition.getY(), currentPosition.getZ());
return new Vec(newPosition.x(), newPosition.y(), currentPosition.z());
}
throw new IllegalStateException("Something weird happened...");
}

View File

@ -42,6 +42,8 @@ import net.minestom.server.utils.Vector;
import net.minestom.server.utils.callback.OptionalCallback;
import net.minestom.server.utils.chunk.ChunkCallback;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Pos;
import net.minestom.server.utils.coordinate.Vec;
import net.minestom.server.utils.entity.EntityUtils;
import net.minestom.server.utils.player.PlayerUtils;
@ -77,16 +79,8 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
protected Instance instance;
protected Chunk currentChunk;
protected final Position position;
/**
* Used to calculate delta movement
*/
protected final Position lastPosition;
/**
* Used to check if any change made to the {@link Entity#position} field since
* the last packets sent
*/
protected final Position lastSyncedPosition;
protected Pos position;
protected Pos lastSyncedPosition;
protected boolean onGround;
private BoundingBox boundingBox;
@ -94,7 +88,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
protected Entity vehicle;
// Velocity
protected Vector velocity = new Vector(); // Movement in block per second
protected Vec velocity = Vec.ZERO; // Movement in block per second
protected boolean hasPhysics = true;
/**
@ -159,9 +153,8 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
this.id = generateId();
this.entityType = entityType;
this.uuid = uuid;
this.position = new Position();
this.lastPosition = new Position();
this.lastSyncedPosition = new Position();
this.position = Pos.ZERO;
this.lastSyncedPosition = Pos.ZERO;
setBoundingBox(entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
@ -181,18 +174,6 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
this(entityType, UUID.randomUUID());
}
@Deprecated
public Entity(@NotNull EntityType entityType, @NotNull UUID uuid, @NotNull Position spawnPosition) {
this(entityType, uuid);
this.position.set(spawnPosition);
this.lastPosition.set(spawnPosition);
}
@Deprecated
public Entity(@NotNull EntityType entityType, @NotNull Position spawnPosition) {
this(entityType, UUID.randomUUID(), spawnPosition);
}
/**
* Schedules a task to be run during the next entity tick.
* It ensures that the task will be executed in the same thread as the entity (depending of the {@link ThreadProvider}).
@ -281,31 +262,26 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* @param callback the optional callback executed, even if auto chunk is not enabled
* @throws IllegalStateException if you try to teleport an entity before settings its instance
*/
public void teleport(@NotNull Position position, @Nullable long[] chunks, @Nullable Runnable callback) {
public void teleport(@NotNull Pos position, @Nullable long[] chunks, @Nullable Runnable callback) {
Check.stateCondition(instance == null, "You need to use Entity#setInstance before teleporting an entity!");
final Position teleportPosition = position.clone(); // Prevent synchronization issue
final ChunkCallback endCallback = (chunk) -> {
refreshPosition(teleportPosition);
refreshPosition(position);
synchronizePosition(true);
OptionalCallback.execute(callback);
};
if (chunks == null || chunks.length == 0) {
instance.loadOptionalChunk(teleportPosition, endCallback);
instance.loadOptionalChunk(position, endCallback);
} else {
ChunkUtils.optionalLoadAll(instance, chunks, null, endCallback);
}
}
public void teleport(@NotNull Position position, @Nullable Runnable callback) {
public void teleport(@NotNull Pos position, @Nullable Runnable callback) {
teleport(position, null, callback);
}
public void teleport(@NotNull Position position) {
public void teleport(@NotNull Pos position) {
teleport(position, null);
}
@ -316,7 +292,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* @param pitch the new pitch
*/
public void setView(float yaw, float pitch) {
refreshView(yaw, pitch);
this.position = position.withView(yaw, pitch);
EntityRotationPacket entityRotationPacket = new EntityRotationPacket();
entityRotationPacket.entityId = getEntityId();
@ -396,7 +372,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
{
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
entityHeadLookPacket.entityId = getEntityId();
entityHeadLookPacket.yaw = position.getYaw();
entityHeadLookPacket.yaw = position.yaw();
playerConnection.sendPacket(entityHeadLookPacket);
}
@ -532,9 +508,9 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
if (applyVelocity) {
final float tps = MinecraftServer.TICK_PER_SECOND;
final double newX = position.getX() + velocity.getX() / tps;
final double newY = position.getY() + velocity.getY() / tps;
final double newZ = position.getZ() + velocity.getZ() / tps;
final double newX = position.x() + velocity.x() / tps;
final double newY = position.y() + velocity.y() / tps;
final double newZ = position.z() + velocity.z() / tps;
Position newPosition = new Position(newX, newY, newZ);
Vector newVelocityOut = new Vector();
@ -555,7 +531,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
}
// World border collision
final Position finalVelocityPosition = CollisionUtils.applyWorldBorder(instance, position, newPosition);
final Point finalVelocityPosition = CollisionUtils.applyWorldBorder(instance, position, newPosition);
final Chunk finalChunk = ChunkUtils.retrieve(instance, currentChunk, finalVelocityPosition);
if (!ChunkUtils.isLoaded(finalChunk)) {
// Entity shouldn't be updated when moving in an unloaded chunk
@ -563,20 +539,17 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
}
// Apply the position if changed
if (!finalVelocityPosition.isSimilar(position)) {
refreshPosition(finalVelocityPosition.getX(),
finalVelocityPosition.getY(),
finalVelocityPosition.getZ());
if (!finalVelocityPosition.samePoint(position)) {
refreshCoordinate(finalVelocityPosition);
sendPositionUpdate(true);
}
// Update velocity
if (hasVelocity() || !newVelocityOut.isZero()) {
this.velocity.copy(newVelocityOut);
this.velocity.multiply(tps);
final Block block = finalChunk.getBlock(position.toBlockPosition());
final Block block = finalChunk.getBlock(position);
final double drag = block.registry().friction();
if (onGround) {
// Stop player velocity
@ -686,10 +659,10 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* @param clientSide {@code true} if the client triggered this action
*/
protected void sendPositionUpdate(final boolean clientSide) {
final boolean viewChange = !position.hasSimilarView(lastSyncedPosition);
final double distanceX = Math.abs(position.getX() - lastSyncedPosition.getX());
final double distanceY = Math.abs(position.getY() - lastSyncedPosition.getY());
final double distanceZ = Math.abs(position.getZ() - lastSyncedPosition.getZ());
final boolean viewChange = !position.sameView(lastSyncedPosition);
final double distanceX = Math.abs(position.x() - lastSyncedPosition.x());
final double distanceY = Math.abs(position.y() - lastSyncedPosition.y());
final double distanceZ = Math.abs(position.z() - lastSyncedPosition.z());
final boolean positionChange = (distanceX + distanceY + distanceZ) > 0;
if (distanceX > 8 || distanceY > 8 || distanceZ > 8) {
@ -704,7 +677,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
// Fix head rotation
final EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
entityHeadLookPacket.entityId = getEntityId();
entityHeadLookPacket.yaw = position.getYaw();
entityHeadLookPacket.yaw = position.yaw();
sendPacketToViewersAndSelf(entityHeadLookPacket);
} else if (positionChange) {
final EntityPositionPacket entityPositionPacket = EntityPositionPacket
@ -713,13 +686,13 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
} else if (viewChange) {
final EntityRotationPacket entityRotationPacket = new EntityRotationPacket();
entityRotationPacket.entityId = getEntityId();
entityRotationPacket.yaw = position.getYaw();
entityRotationPacket.pitch = position.getPitch();
entityRotationPacket.yaw = position.yaw();
entityRotationPacket.pitch = position.pitch();
entityRotationPacket.onGround = onGround;
final EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
entityHeadLookPacket.entityId = getEntityId();
entityHeadLookPacket.yaw = position.getYaw();
entityHeadLookPacket.yaw = position.yaw();
if (clientSide) {
sendPacketToViewers(entityHeadLookPacket);
@ -736,12 +709,12 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
if (PlayerUtils.isNettyClient(this) && !clientSide) {
final PlayerPositionAndLookPacket playerPositionAndLookPacket = new PlayerPositionAndLookPacket();
playerPositionAndLookPacket.flags = 0b111;
playerPositionAndLookPacket.position = position.clone().subtract(lastSyncedPosition.getX(), lastSyncedPosition.getY(), lastSyncedPosition.getZ());
playerPositionAndLookPacket.position = position.sub(lastSyncedPosition);
playerPositionAndLookPacket.teleportId = ((Player) this).getNextTeleportId();
((Player) this).getPlayerConnection().sendPacket(playerPositionAndLookPacket);
}
lastSyncedPosition.set(position);
this.lastSyncedPosition = position;
}
/**
@ -893,25 +866,25 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* @param spawnPosition the spawn position for the entity.
* @throws IllegalStateException if {@code instance} has not been registered in {@link InstanceManager}
*/
public void setInstance(@NotNull Instance instance, @NotNull Position spawnPosition) {
public void setInstance(@NotNull Instance instance, @NotNull Pos spawnPosition) {
Check.stateCondition(!instance.isRegistered(),
"Instances need to be registered, please use InstanceManager#registerInstance or InstanceManager#registerSharedInstance");
if (this.instance != null) {
this.instance.UNSAFE_removeEntity(this);
}
this.position.set(spawnPosition);
this.lastPosition.set(position);
this.position = spawnPosition;
this.isActive = true;
this.instance = instance;
refreshCurrentChunk(instance.getChunkAt(position.getX(), position.getZ()));
refreshCurrentChunk(instance.getChunkAt(position));
instance.UNSAFE_addEntity(this);
spawn();
EventDispatcher.call(new EntitySpawnEvent(this, instance));
}
public void setInstance(@NotNull Instance instance, @NotNull Position spawnPosition) {
setInstance(instance, Pos.fromPosition(spawnPosition));
}
/**
* Changes the entity instance.
*
@ -928,8 +901,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
*
* @return the entity current velocity
*/
@NotNull
public Vector getVelocity() {
public @NotNull Vec getVelocity() {
return velocity;
}
@ -940,10 +912,10 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
*
* @param velocity the new entity velocity
*/
public void setVelocity(@NotNull Vector velocity) {
public void setVelocity(@NotNull Vec velocity) {
EntityVelocityEvent entityVelocityEvent = new EntityVelocityEvent(this, velocity);
EventDispatcher.callCancellable(entityVelocityEvent, () -> {
this.velocity.copy(entityVelocityEvent.getVelocity());
this.velocity = entityVelocityEvent.getVelocity();
sendPacketToViewersAndSelf(getVelocityPacket());
});
}
@ -954,7 +926,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* @return true if velocity is not set to 0
*/
public boolean hasVelocity() {
return !velocity.isZero();
return !velocity.samePoint(Vec.ZERO);
}
/**
@ -1003,7 +975,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* @return the distance between this and {@code entity}
*/
public double getDistance(@NotNull Entity entity) {
return getPosition().getDistance(entity.getPosition());
return getPosition().distance(entity.getPosition());
}
/**
@ -1013,7 +985,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* @return the distance squared between this and {@code entity}
*/
public double getDistanceSquared(@NotNull Entity entity) {
return getPosition().getDistanceSquared(entity.getPosition());
return getPosition().distanceSquared(entity.getPosition());
}
/**
@ -1321,42 +1293,57 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
this.entityMeta.setHasNoGravity(noGravity);
}
/**
* Updates internal fields and sends updates
*
* @param position the new position
* @see #refreshCoordinate(Pos)
* @see #sendPositionUpdate(boolean)
*/
@ApiStatus.Internal
public void refreshPosition(@NotNull final Pos position, boolean ignoreView) {
if (!ignoreView) {
this.position = position;
} else {
this.position = this.position.withCoord(position);
}
if (!position.samePoint(this.position)) {
refreshCoordinate(position);
}
sendPositionUpdate(true);
}
@ApiStatus.Internal
public void refreshPosition(@NotNull final Pos position) {
refreshPosition(position, false);
}
/**
* Used to refresh the entity and its passengers position
* - put the entity in the right instance chunk
* - update the viewable chunks (load and unload)
* - add/remove players from the viewers list if {@link #isAutoViewable()} is enabled
* <p>
* WARNING: unsafe, should only be used internally in Minestom. Use {@link #teleport(Position)} instead.
* WARNING: unsafe, should only be used internally in Minestom. Use {@link #teleport(Pos)} instead.
*
* @param x new position X
* @param y new position Y
* @param z new position Z
* @param newPosition the new position
*/
private void refreshPosition(double x, double y, double z) {
position.setX(x);
position.setY(y);
position.setZ(z);
private void refreshCoordinate(Point newPosition) {
if (hasPassenger()) {
for (Entity passenger : getPassengers()) {
passenger.refreshPosition(x, y, z);
passenger.refreshCoordinate(newPosition);
}
}
final Instance instance = getInstance();
if (instance != null) {
final int lastChunkX = currentChunk.getChunkX();
final int lastChunkZ = currentChunk.getChunkZ();
final int newChunkX = ChunkUtils.getChunkCoordinate(x);
final int newChunkZ = ChunkUtils.getChunkCoordinate(z);
final int newChunkX = ChunkUtils.getChunkCoordinate(newPosition.x());
final int newChunkZ = ChunkUtils.getChunkCoordinate(newPosition.z());
if (lastChunkX != newChunkX || lastChunkZ != newChunkZ) {
// Entity moved in a new chunk
final Chunk newChunk = instance.getChunk(newChunkX, newChunkZ);
Check.notNull(newChunk, "The entity {0} tried to move in an unloaded chunk at {1};{2}", getEntityId(), x, z);
Check.notNull(newChunk, "The entity {0} tried to move in an unloaded chunk at {1}", getEntityId(), newPosition);
instance.UNSAFE_switchEntityChunk(this, currentChunk, newChunk);
if (this instanceof Player) {
// Refresh player view
@ -1364,45 +1351,10 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
player.refreshVisibleChunks(newChunk);
player.refreshVisibleEntities(newChunk);
}
refreshCurrentChunk(newChunk);
}
}
this.lastPosition.setX(position.getX());
this.lastPosition.setY(position.getY());
this.lastPosition.setZ(position.getZ());
}
/**
* Updates internal fields and sends updates
*
* @param position the new position
* @see #refreshPosition(double, double, double)
* @see #refreshView(float, float)
* @see #sendPositionUpdate(boolean)
*/
@ApiStatus.Internal
public void refreshPosition(@NotNull final Position position) {
if (!position.isSimilar(this.position))
refreshPosition(position.getX(), position.getY(), position.getZ());
refreshView(position.getYaw(), position.getPitch());
sendPositionUpdate(true);
}
/**
* Updates the entity view internally.
* <p>
* Warning: you probably want to use {@link #setView(float, float)}.
*
* @param yaw the yaw
* @param pitch the pitch
*/
private void refreshView(final float yaw, final float pitch) {
lastPosition.setYaw(position.getYaw());
lastPosition.setPitch(position.getPitch());
position.setYaw(yaw);
position.setPitch(pitch);
this.lastPosition = position;
}
/**
@ -1410,8 +1362,7 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
*
* @return the current position of the entity
*/
@NotNull
public Position getPosition() {
public @NotNull Pos getPosition() {
return position;
}
@ -1536,19 +1487,17 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
return scheduledRemoveTime != 0;
}
@NotNull
protected Vector getVelocityForPacket() {
return this.velocity.clone().multiply(8000f / MinecraftServer.TICK_PER_SECOND);
protected @NotNull Vec getVelocityForPacket() {
return this.velocity.mul(8000f / MinecraftServer.TICK_PER_SECOND);
}
@NotNull
protected EntityVelocityPacket getVelocityPacket() {
protected @NotNull EntityVelocityPacket getVelocityPacket() {
EntityVelocityPacket velocityPacket = new EntityVelocityPacket();
velocityPacket.entityId = getEntityId();
Vector velocity = getVelocityForPacket();
velocityPacket.velocityX = (short) velocity.getX();
velocityPacket.velocityY = (short) velocity.getY();
velocityPacket.velocityZ = (short) velocity.getZ();
Vec velocity = getVelocityForPacket();
velocityPacket.velocityX = (short) velocity.x();
velocityPacket.velocityY = (short) velocity.y();
velocityPacket.velocityZ = (short) velocity.z();
return velocityPacket;
}
@ -1576,15 +1525,14 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
*/
@ApiStatus.Internal
protected void synchronizePosition(boolean includeSelf) {
final Position pos = position.clone();
final EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
entityTeleportPacket.entityId = getEntityId();
entityTeleportPacket.position = pos;
entityTeleportPacket.position = position;
entityTeleportPacket.onGround = isOnGround();
sendPacketToViewers(entityTeleportPacket);
this.lastAbsoluteSynchronizationTime = System.currentTimeMillis();
this.lastSyncedPosition.set(pos);
this.lastSyncedPosition = position;
}
/**
@ -1738,10 +1686,13 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
public void takeKnockback(final float strength, final double x, final double z) {
if (strength > 0) {
//TODO check possible side effects of unnatural TPS (other than 20TPS)
final Vector velocityModifier = new Vector(x, 0d, z).normalize().multiply(strength * MinecraftServer.TICK_PER_SECOND / 2);
this.velocity.setX(velocity.getX() / 2d - velocityModifier.getX());
this.velocity.setY(onGround ? Math.min(.4d, velocity.getY() / 2d + strength) * MinecraftServer.TICK_PER_SECOND : velocity.getY());
this.velocity.setZ(velocity.getZ() / 2d - velocityModifier.getZ());
final Vec velocityModifier = new Vec(x, z)
.normalize()
.mul(strength * MinecraftServer.TICK_PER_SECOND / 2);
setVelocity(new Vec(velocity.x() / 2d - velocityModifier.x(),
onGround ? Math.min(.4d, velocity.y() / 2d + strength) * MinecraftServer.TICK_PER_SECOND : velocity.y(),
velocity.z() / 2d - velocityModifier.z()
));
}
}

View File

@ -42,20 +42,6 @@ public class EntityCreature extends LivingEntity implements NavigableEntity, Ent
this(entityType, UUID.randomUUID());
}
@Deprecated
public EntityCreature(@NotNull EntityType entityType, @NotNull Position spawnPosition) {
super(entityType, spawnPosition);
heal();
}
@Deprecated
public EntityCreature(@NotNull EntityType entityType, @NotNull Position spawnPosition, @Nullable Instance instance) {
this(entityType, spawnPosition);
if (instance != null) {
setInstance(instance);
}
}
@Override
public void update(long time) {
// AI

View File

@ -1,8 +1,5 @@
package net.minestom.server.entity;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.LivingEntity;
import net.minestom.server.entity.metadata.ProjectileMeta;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityAttackEvent;
@ -13,6 +10,8 @@ import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -35,13 +34,6 @@ public class EntityProjectile extends Entity {
setup();
}
@Deprecated
public EntityProjectile(@Nullable Entity shooter, @NotNull EntityType entityType, @NotNull Position spawnPosition) {
super(entityType, spawnPosition);
this.shooter = shooter;
setup();
}
private void setup() {
super.hasPhysics = false;
if (getEntityMeta() instanceof ProjectileMeta) {
@ -70,21 +62,21 @@ public class EntityProjectile extends Entity {
}
public void shoot(Position to, double power, double spread) {
public void shoot(Point to, double power, double spread) {
EntityShootEvent shootEvent = new EntityShootEvent(this.shooter, this, to, power, spread);
EventDispatcher.call(shootEvent);
if (shootEvent.isCancelled()) {
remove();
return;
}
Position from = this.shooter.getPosition().clone().add(0D, this.shooter.getEyeHeight(), 0D);
final var from = this.shooter.getPosition().add(0D, this.shooter.getEyeHeight(), 0D);
shoot(from, to, shootEvent.getPower(), shootEvent.getSpread());
}
private void shoot(@NotNull Position from, @NotNull Position to, double power, double spread) {
double dx = to.getX() - from.getX();
double dy = to.getY() - from.getY();
double dz = to.getZ() - from.getZ();
private void shoot(@NotNull Point from, @NotNull Point to, double power, double spread) {
double dx = to.x() - from.x();
double dy = to.y() - from.y();
double dz = to.z() - from.z();
double xzLength = Math.sqrt(dx * dx + dz * dz);
dy += xzLength * 0.20000000298023224D;
@ -97,10 +89,9 @@ public class EntityProjectile extends Entity {
dx += random.nextGaussian() * spread;
dy += random.nextGaussian() * spread;
dz += random.nextGaussian() * spread;
super.velocity.setX(dx);
super.velocity.setY(dy);
super.velocity.setZ(dz);
super.velocity.multiply(20 * power);
final double mul = 20 * power;
this.velocity = new Vec(dx * mul, dy * mul, dz * mul);
setView(
(float) Math.toDegrees(Math.atan2(dx, dz)),
(float) Math.toDegrees(Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)))
@ -109,15 +100,15 @@ public class EntityProjectile extends Entity {
@Override
public void tick(long time) {
Position posBefore = getPosition().clone();
final var posBefore = getPosition();
super.tick(time);
Position posNow = getPosition().clone();
final var posNow = getPosition();
if (isStuck(posBefore, posNow)) {
if (super.onGround) {
return;
}
super.onGround = true;
getVelocity().zero();
this.velocity = Vec.ZERO;
sendPacketToViewersAndSelf(getVelocityPacket());
setNoGravity(true);
onStuck();
@ -139,8 +130,8 @@ public class EntityProjectile extends Entity {
* @return if an arrow is stuck in block / hit an entity.
*/
@SuppressWarnings("ConstantConditions")
private boolean isStuck(Position pos, Position posNow) {
if (pos.isSimilar(posNow)) {
private boolean isStuck(Point pos, Point posNow) {
if (pos.samePoint(posNow)) {
return true;
}
@ -200,5 +191,4 @@ public class EntityProjectile extends Entity {
}
return false;
}
}

View File

@ -21,10 +21,10 @@ public enum EntitySpawnType {
ObjectDataProvider objectDataProvider = (ObjectDataProvider) entity.getEntityMeta();
packet.data = objectDataProvider.getObjectData();
if (objectDataProvider.requiresVelocityPacketAtSpawn()) {
Vector velocity = entity.getVelocityForPacket();
packet.velocityX = (short) velocity.getX();
packet.velocityY = (short) velocity.getY();
packet.velocityZ = (short) velocity.getZ();
final var velocity = entity.getVelocityForPacket();
packet.velocityX = (short) velocity.x();
packet.velocityY = (short) velocity.y();
packet.velocityZ = (short) velocity.z();
}
}
return packet;
@ -38,11 +38,11 @@ public enum EntitySpawnType {
packet.entityUuid = entity.getUuid();
packet.entityType = entity.getEntityType().ordinal();
packet.position = entity.getPosition();
packet.headPitch = entity.getPosition().getPitch();
Vector velocity = entity.getVelocityForPacket();
packet.velocityX = (short) velocity.getX();
packet.velocityY = (short) velocity.getY();
packet.velocityZ = (short) velocity.getZ();
packet.headPitch = entity.getPosition().pitch();
final var velocity = entity.getVelocityForPacket();
packet.velocityX = (short) velocity.x();
packet.velocityY = (short) velocity.y();
packet.velocityZ = (short) velocity.z();
return packet;
}
},

View File

@ -1,10 +1,6 @@
package net.minestom.server.entity;
import net.minestom.server.instance.Instance;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import net.minestom.server.utils.coordinate.Vec;
import java.util.Comparator;
@ -14,22 +10,13 @@ public class ExperienceOrb extends Entity {
private Player target;
private long lastTargetUpdateTick;
public ExperienceOrb(short experienceCount, @NotNull Position spawnPosition) {
super(EntityType.EXPERIENCE_ORB, spawnPosition);
public ExperienceOrb(short experienceCount) {
super(EntityType.EXPERIENCE_ORB);
setBoundingBox(0.5f, 0.5f, 0.5f);
//todo vanilla sets random velocity here?
this.experienceCount = experienceCount;
}
public ExperienceOrb(short experienceCount, @NotNull Position spawnPosition, @Nullable Instance instance) {
this(experienceCount, spawnPosition);
if (instance != null) {
setInstance(instance);
}
}
@Override
public void update(long time) {
@ -44,7 +31,7 @@ public class ExperienceOrb extends Entity {
double d = 8.0;
if (lastTargetUpdateTick < time - 20 + getEntityId() % 100) {
if (target == null || target.getPosition().getDistanceSquared(getPosition()) > 64) {
if (target == null || target.getPosition().distanceSquared(getPosition()) > 64) {
this.target = getClosestPlayer(this, 8);
}
@ -56,13 +43,13 @@ public class ExperienceOrb extends Entity {
}
if (target != null) {
Position pos = getPosition();
Position targetPos = target.getPosition();
Vector toTarget = new Vector(targetPos.getX() - pos.getX(), targetPos.getY() + (target.getEyeHeight() / 2) - pos.getY(), targetPos.getZ() - pos.getZ());
final var pos = getPosition();
final var targetPos = target.getPosition();
final Vec toTarget = new Vec(targetPos.x() - pos.x(), targetPos.y() + (target.getEyeHeight() / 2) - pos.y(), targetPos.z() - pos.z());
double e = toTarget.length(); //could really be lengthSquared
if (e < 8) {
double f = 1 - (e / 8);
setVelocity(getVelocity().add(toTarget.normalize().multiply(f * f * 0.1)));
setVelocity(getVelocity().add(toTarget.normalize().mul(f * f * 0.1)));
}
}
@ -74,9 +61,10 @@ public class ExperienceOrb extends Entity {
}
// apply slipperiness
setVelocity(getVelocity().multiply(new Vector(g, 0.98f, g)));
if (isOnGround())
setVelocity(getVelocity().multiply(new Vector(1, -0.9f, 1)));
setVelocity(getVelocity().mul(new Vec(g, 0.98f, g)));
if (isOnGround()) {
setVelocity(getVelocity().mul(new Vec(1, -0.9f, 1)));
}
}
@Override

View File

@ -4,10 +4,8 @@ import net.minestom.server.entity.metadata.item.ItemEntityMeta;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityItemMergeEvent;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.StackingRule;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.time.Cooldown;
import net.minestom.server.utils.time.TimeUnit;
import org.jetbrains.annotations.NotNull;
@ -41,20 +39,12 @@ public class ItemEntity extends Entity {
private long spawnTime;
private long pickupDelay;
public ItemEntity(@NotNull ItemStack itemStack, @NotNull Position spawnPosition) {
super(EntityType.ITEM, spawnPosition);
public ItemEntity(@NotNull ItemStack itemStack) {
super(EntityType.ITEM);
setItemStack(itemStack);
setBoundingBox(0.25f, 0.25f, 0.25f);
}
public ItemEntity(@NotNull ItemStack itemStack, @NotNull Position spawnPosition, @Nullable Instance instance) {
this(itemStack, spawnPosition);
if (instance != null) {
setInstance(instance);
}
}
/**
* Gets the update option for the merging feature.
*
@ -70,7 +60,6 @@ public class ItemEntity extends Entity {
* Can be set to null to entirely remove the delay.
*
* @param mergeUpdateOption the new merge update option
*
* @deprecated Replaced by {@link #setMergeDelay(Duration)}
*/
@SuppressWarnings("removal")
@ -239,7 +228,7 @@ public class ItemEntity extends Entity {
/**
* Sets the pickup delay of the ItemEntity.
*
* @param delay the pickup delay
* @param delay the pickup delay
* @param temporalUnit the unit of the delay
*/
public void setPickupDelay(long delay, @NotNull TemporalUnit temporalUnit) {
@ -249,7 +238,7 @@ public class ItemEntity extends Entity {
/**
* Sets the pickup delay of the ItemEntity.
*
* @param delay the pickup delay
* @param delay the pickup delay
*/
public void setPickupDelay(Duration delay) {
this.pickupDelay = delay.toMillis();

View File

@ -26,9 +26,9 @@ import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.scoreboard.Team;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.block.BlockIterator;
import net.minestom.server.utils.coordinate.Vec;
import net.minestom.server.utils.time.Cooldown;
import net.minestom.server.utils.time.TimeUnit;
import org.jetbrains.annotations.NotNull;
@ -90,7 +90,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
* Constructor which allows to specify an UUID. Only use if you know what you are doing!
*/
public LivingEntity(@NotNull EntityType entityType, @NotNull UUID uuid) {
this(entityType, uuid, new Position());
super(entityType, uuid);
initEquipments();
}
@ -98,20 +98,6 @@ public class LivingEntity extends Entity implements EquipmentHandler {
this(entityType, UUID.randomUUID());
}
/**
* Constructor which allows to specify an UUID. Only use if you know what you are doing!
*/
@Deprecated
public LivingEntity(@NotNull EntityType entityType, @NotNull UUID uuid, @NotNull Position spawnPosition) {
super(entityType, uuid, spawnPosition);
initEquipments();
}
@Deprecated
public LivingEntity(@NotNull EntityType entityType, @NotNull Position spawnPosition) {
this(entityType, UUID.randomUUID(), spawnPosition);
}
private void initEquipments() {
this.mainHandItem = ItemStack.AIR;
this.offHandItem = ItemStack.AIR;
@ -300,7 +286,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
setHealth(0);
// Reset velocity
velocity.zero();
this.velocity = Vec.ZERO;
// Remove passengers if any
if (hasPassenger()) {
@ -323,8 +309,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
/**
* Sets fire to this entity for a given duration.
*
* @param duration duration of the effect
* @param temporalUnit unit used to express the duration
* @param duration duration of the effect
* @param temporalUnit unit used to express the duration
* @see #setOnFire(boolean) if you want it to be permanent without any event callback
*/
public void setFireForDuration(int duration, TemporalUnit temporalUnit) {
@ -804,8 +790,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
* Note: The strength is reduced based on knockback resistance
*
* @param strength the strength of the knockback, 0.4 is the vanilla value for a bare hand hit
* @param x knockback on x axle, for default knockback use the following formula <pre>sin(attacker.yaw * (pi/180))</pre>
* @param z knockback on z axle, for default knockback use the following formula <pre>-cos(attacker.yaw * (pi/180))</pre>
* @param x knockback on x axle, for default knockback use the following formula <pre>sin(attacker.yaw * (pi/180))</pre>
* @param z knockback on z axle, for default knockback use the following formula <pre>-cos(attacker.yaw * (pi/180))</pre>
*/
@Override
public void takeKnockback(float strength, final double x, final double z) {

View File

@ -68,6 +68,8 @@ import net.minestom.server.stat.PlayerStatistic;
import net.minestom.server.utils.*;
import net.minestom.server.utils.chunk.ChunkCallback;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Pos;
import net.minestom.server.utils.entity.EntityUtils;
import net.minestom.server.utils.identity.NamedAndIdentified;
import net.minestom.server.utils.instance.InstanceUtils;
@ -130,7 +132,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
private byte heldSlot;
private Position respawnPoint;
private Pos respawnPoint;
private int food;
private float foodSaturation;
@ -179,7 +181,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
setBoundingBox(0.6f, 1.8f, 0.6f);
setRespawnPoint(new Position(0, 0, 0));
setRespawnPoint(Pos.ZERO);
this.settings = new PlayerSettings();
this.inventory = new PlayerInventory(this);
@ -520,9 +522,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* @param spawnPosition the new position of the player
*/
@Override
public void setInstance(@NotNull Instance instance, @NotNull Position spawnPosition) {
public void setInstance(@NotNull Instance instance, @NotNull Pos spawnPosition) {
Check.argCondition(this.instance == instance, "Instance should be different than the current one");
// true if the chunks need to be sent to the client, can be false if the instances share the same chunks (eg SharedInstance)
final boolean needWorldRefresh = !InstanceUtils.areLinked(this.instance, instance) ||
!spawnPosition.inSameChunk(this.position);
@ -557,7 +558,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* if the player is not in any instance).
*
* @param instance the new player instance
* @see #setInstance(Instance, Position)
* @see #setInstance(Instance, Pos)
*/
@Override
public void setInstance(@NotNull Instance instance) {
@ -569,14 +570,14 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* <p>
* Does add the player to {@code instance}, remove all viewable entities and call {@link PlayerSpawnEvent}.
* <p>
* UNSAFE: only called with {@link #setInstance(Instance, Position)}.
* UNSAFE: only called with {@link #setInstance(Instance, Pos)}.
*
* @param spawnPosition the position to teleport the player
* @param firstSpawn true if this is the player first spawn
* @param updateChunks true if chunks should be refreshed, false if the new instance shares the same
* chunks
*/
private void spawnPlayer(@NotNull Instance instance, @NotNull Position spawnPosition,
private void spawnPlayer(@NotNull Instance instance, @NotNull Pos spawnPosition,
boolean firstSpawn, boolean dimensionChange, boolean updateChunks) {
if (!firstSpawn) {
// Player instance changed, clear current viewable collections
@ -768,7 +769,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
@Override
public void playSound(@NotNull Sound sound) {
this.playSound(sound, this.position.getX(), this.position.getY(), this.position.getZ());
this.playSound(sound, this.position.x(), this.position.y(), this.position.z());
}
@Override
@ -1294,14 +1295,14 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
facePosition(facePoint, entity.getPosition(), entity, targetPoint);
}
private void facePosition(@NotNull FacePoint facePoint, @NotNull Position targetPosition,
private void facePosition(@NotNull FacePoint facePoint, @NotNull Point targetPosition,
@Nullable Entity entity, @Nullable FacePoint targetPoint) {
FacePlayerPacket facePlayerPacket = new FacePlayerPacket();
facePlayerPacket.entityFacePosition = facePoint == FacePoint.EYE ?
FacePlayerPacket.FacePosition.EYES : FacePlayerPacket.FacePosition.FEET;
facePlayerPacket.targetX = targetPosition.getX();
facePlayerPacket.targetY = targetPosition.getY();
facePlayerPacket.targetZ = targetPosition.getZ();
facePlayerPacket.targetX = targetPosition.x();
facePlayerPacket.targetY = targetPosition.y();
facePlayerPacket.targetZ = targetPosition.z();
if (entity != null) {
facePlayerPacket.entityId = entity.getEntityId();
facePlayerPacket.entityFacePosition = targetPoint == FacePoint.EYE ?
@ -1329,13 +1330,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
/**
* Used to retrieve the default spawn point.
* <p>
* Can be altered by the {@link PlayerRespawnEvent#setRespawnPosition(Position)}.
* Can be altered by the {@link PlayerRespawnEvent#setRespawnPosition(Pos)}.
*
* @return a copy of the default respawn point
*/
@NotNull
public Position getRespawnPoint() {
return respawnPoint.clone();
public @NotNull Pos getRespawnPoint() {
return respawnPoint;
}
/**
@ -1343,7 +1343,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*
* @param respawnPoint the player respawn point
*/
public void setRespawnPoint(@NotNull Position respawnPoint) {
public void setRespawnPoint(@NotNull Pos respawnPoint) {
this.respawnPoint = respawnPoint;
}
@ -1365,8 +1365,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
{
// Send new chunks
final BlockPosition pos = position.toBlockPosition();
final Chunk chunk = instance.getChunk(pos.getX() >> 4, pos.getZ() >> 4);
final Chunk chunk = instance.getChunkAt(position);
Check.notNull(chunk, "Tried to interact with an unloaded chunk.");
refreshVisibleChunks(chunk);
}
@ -1903,7 +1902,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
protected void synchronizePosition(boolean includeSelf) {
if (includeSelf) {
final PlayerPositionAndLookPacket positionAndLookPacket = new PlayerPositionAndLookPacket();
positionAndLookPacket.position = position.clone();
positionAndLookPacket.position = position;
positionAndLookPacket.flags = 0x00;
positionAndLookPacket.teleportId = teleportId.incrementAndGet();
playerConnection.sendPacket(positionAndLookPacket);
@ -2324,7 +2323,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
entityHeadLookPacket.entityId = getEntityId();
entityHeadLookPacket.yaw = position.getYaw();
entityHeadLookPacket.yaw = position.yaw();
connection.sendPacket(entityHeadLookPacket);
}

View File

@ -2,11 +2,10 @@ package net.minestom.server.entity.ai.goal;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.EntityProjectile;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.entity.pathfinding.Navigator;
import net.minestom.server.entity.EntityProjectile;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.time.Cooldown;
import net.minestom.server.utils.time.TimeUnit;
import net.minestom.server.utils.validate.Check;
@ -175,7 +174,7 @@ public class CombinedAttackGoal extends GoalSelector {
if (!Cooldown.hasCooldown(time, this.lastAttack, this.rangedDelay)) {
if (this.entityCreature.hasLineOfSight(target)) {
// If target is on line of entity sight, ranged attack can be performed
Position to = target.getPosition().clone().add(0D, target.getEyeHeight(), 0D);
final var to = target.getPosition().add(0D, target.getEyeHeight(), 0D);
Function<Entity, EntityProjectile> projectileGenerator = this.projectileGenerator;
if (projectileGenerator == null) {
@ -193,7 +192,7 @@ public class CombinedAttackGoal extends GoalSelector {
}
}
Navigator navigator = this.entityCreature.getNavigator();
Position pathPosition = navigator.getPathPosition();
final var pathPosition = navigator.getPathPosition();
// If we don't want to come close and we're already within desirable range, no movement is needed.
if (!comeClose && distanceSquared <= this.desirableRangeSquared) {
if (pathPosition != null) {
@ -202,8 +201,8 @@ public class CombinedAttackGoal extends GoalSelector {
return;
}
// Otherwise going to the target.
Position targetPosition = target.getPosition();
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
final var targetPosition = target.getPosition();
if (pathPosition == null || !pathPosition.samePoint(targetPosition)) {
if (this.cooldown.isReady(time)) {
this.cooldown.refreshLastUpdate(time);
navigator.setPathTo(targetPosition);

View File

@ -1,95 +0,0 @@
package net.minestom.server.entity.ai.goal;
import it.unimi.dsi.fastutil.shorts.Short2ShortArrayMap;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.BlockPosition;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
public class EatBlockGoal extends GoalSelector {
private static final Random RANDOM = new Random();
private final Short2ShortArrayMap eatBelowMap;
private final Short2ShortArrayMap eatInMap;
private final int chancePerTick;
private int eatAnimationTick;
/**
* @param entityCreature Creature that should eat a block.
* @param eatInMap Map containing the block IDs that the entity can eat (when inside the block) and the block ID of the replacement block.
* @param eatBelowMap Map containing block IDs that the entity can eat (when above the block) and the block ID of the replacement block.
* @param chancePerTick The chance (per tick) that the entity eats. Settings this to N would mean there is a 1 in N chance.
*/
public EatBlockGoal(
@NotNull EntityCreature entityCreature,
@NotNull Short2ShortArrayMap eatInMap,
@NotNull Short2ShortArrayMap eatBelowMap,
int chancePerTick) {
super(entityCreature);
this.eatInMap = eatInMap;
this.eatBelowMap = eatBelowMap;
this.chancePerTick = chancePerTick;
}
@Override
public boolean shouldStart() {
// TODO: is Baby
if (RANDOM.nextInt(chancePerTick) != 0) {
return false;
}
final Instance instance = entityCreature.getInstance();
// An entity shouldn't be eating blocks on null instances.
if (instance == null) {
return false;
}
final BlockPosition blockPosition = entityCreature.getPosition().toBlockPosition();
final short blockStateIdIn = instance.getBlock(blockPosition.clone().subtract(0, 1, 0)).stateId();
final short blockStateIdBelow = instance.getBlock(blockPosition.clone().subtract(0, 2, 0)).stateId();
return eatInMap.containsKey(blockStateIdIn) || eatBelowMap.containsKey(blockStateIdBelow);
}
@Override
public void start() {
this.eatAnimationTick = 40;
// TODO: EatBlockEvent call here.
// Stop moving
entityCreature.getNavigator().setPathTo(null);
}
@Override
public void tick(long time) {
this.eatAnimationTick = Math.max(0, this.eatAnimationTick - 1);
if (this.eatAnimationTick != 4) {
return;
}
Instance instance = entityCreature.getInstance();
final BlockPosition currentPosition = entityCreature.getPosition().toBlockPosition().clone().subtract(0, 1, 0);
final BlockPosition belowPosition = currentPosition.clone().subtract(0, 1, 0);
final short blockStateIdIn = instance.getBlock(currentPosition).stateId();
final short blockStateIdBelow = instance.getBlock(belowPosition).stateId();
if (eatInMap.containsKey(blockStateIdIn)) {
instance.setBlock(currentPosition, Block.fromStateId(eatInMap.get(blockStateIdIn)));
} else if (eatBelowMap.containsKey(blockStateIdBelow)) {
instance.setBlock(belowPosition, Block.fromStateId(eatBelowMap.get(blockStateIdBelow)));
}
// TODO: Call Entity Eat Animation
}
@Override
public boolean shouldEnd() {
return eatAnimationTick <= 0;
}
@Override
public void end() {
this.eatAnimationTick = 0;
}
}

View File

@ -4,8 +4,7 @@ import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.entity.pathfinding.Navigator;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Point;
import org.jetbrains.annotations.NotNull;
import java.time.Duration;
@ -15,14 +14,13 @@ public class FollowTargetGoal extends GoalSelector {
private final Duration pathDuration;
private long lastUpdateTime = 0;
private boolean forceEnd = false;
private Position lastTargetPos;
private Point lastTargetPos;
/**
* Creates a follow target goal object.
*
* @param entityCreature the entity
* @param pathUpdateOption the time between each path update (to check if the target moved)
*
* @deprecated Replaced by {@link #FollowTargetGoal(EntityCreature, Duration)}
*/
@SuppressWarnings("removal")
@ -34,8 +32,8 @@ public class FollowTargetGoal extends GoalSelector {
/**
* Creates a follow target goal object.
*
* @param entityCreature the entity
* @param pathDuration the time between each path update (to check if the target moved)
* @param entityCreature the entity
* @param pathDuration the time between each path update (to check if the target moved)
*/
public FollowTargetGoal(@NotNull EntityCreature entityCreature, @NotNull Duration pathDuration) {
super(entityCreature);
@ -45,7 +43,7 @@ public class FollowTargetGoal extends GoalSelector {
@Override
public boolean shouldStart() {
return entityCreature.getTarget() != null &&
getDistance(entityCreature.getTarget().getPosition(), entityCreature.getPosition()) >= 2;
entityCreature.getTarget().getPosition().distance(entityCreature.getPosition()) >= 2;
}
@Override
@ -54,19 +52,18 @@ public class FollowTargetGoal extends GoalSelector {
forceEnd = false;
lastTargetPos = null;
final Entity target = entityCreature.getTarget();
if (target != null) {
Navigator navigator = entityCreature.getNavigator();
lastTargetPos = target.getPosition().clone();
if (getDistance(lastTargetPos, entityCreature.getPosition()) < 2) {
lastTargetPos = target.getPosition();
if (lastTargetPos.distance(entityCreature.getPosition()) < 2) {
forceEnd = true;
navigator.setPathTo(null);
return;
}
if (navigator.getPathPosition() == null ||
(!navigator.getPathPosition().isSimilar(lastTargetPos))) {
(!navigator.getPathPosition().samePoint(lastTargetPos))) {
navigator.setPathTo(lastTargetPos);
} else {
forceEnd = true;
@ -83,28 +80,24 @@ public class FollowTargetGoal extends GoalSelector {
pathDuration.toMillis() + lastUpdateTime > time) {
return;
}
Position targetPos = entityCreature.getTarget() != null ? entityCreature.getTarget().getPosition() : null;
if (targetPos != null && !targetPos.equals(lastTargetPos)) {
lastUpdateTime = time;
lastTargetPos.copy(lastTargetPos);
entityCreature.getNavigator().setPathTo(targetPos);
final var targetPos = entityCreature.getTarget() != null ? entityCreature.getTarget().getPosition() : null;
if (targetPos != null && !targetPos.samePoint(lastTargetPos)) {
this.lastUpdateTime = time;
this.lastTargetPos = targetPos;
this.entityCreature.getNavigator().setPathTo(targetPos);
}
}
@Override
public boolean shouldEnd() {
final Entity target = entityCreature.getTarget();
return forceEnd ||
entityCreature.getTarget() == null ||
getDistance(entityCreature.getTarget().getPosition(), entityCreature.getPosition()) < 2;
target == null ||
target.getPosition().distance(entityCreature.getPosition()) < 2;
}
@Override
public void end() {
entityCreature.getNavigator().setPathTo(null);
}
private double getDistance(@NotNull Position a, @NotNull Position b) {
return MathUtils.square(a.getX() - b.getX()) +
MathUtils.square(a.getZ() - b.getZ());
}
}

View File

@ -5,7 +5,7 @@ import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.entity.ai.TargetSelector;
import net.minestom.server.entity.pathfinding.Navigator;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.time.Cooldown;
import net.minestom.server.utils.time.TimeUnit;
import org.jetbrains.annotations.NotNull;
@ -61,7 +61,7 @@ public class MeleeAttackGoal extends GoalSelector {
@Override
public void start() {
final Position targetPosition = this.cachedTarget.getPosition();
final Point targetPosition = this.cachedTarget.getPosition();
entityCreature.getNavigator().setPathTo(targetPosition);
}
@ -90,9 +90,9 @@ public class MeleeAttackGoal extends GoalSelector {
// Move toward the target entity
Navigator navigator = entityCreature.getNavigator();
final Position pathPosition = navigator.getPathPosition();
final Position targetPosition = target.getPosition();
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
final var pathPosition = navigator.getPathPosition();
final var targetPosition = target.getPosition();
if (pathPosition == null || !pathPosition.samePoint(targetPosition)) {
if (this.cooldown.isReady(time)) {
this.cooldown.refreshLastUpdate(time);
navigator.setPathTo(targetPosition);

View File

@ -3,6 +3,7 @@ package net.minestom.server.entity.ai.goal;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
@ -13,20 +14,20 @@ public class RandomLookAroundGoal extends GoalSelector {
private static final Random RANDOM = new Random();
private final int chancePerTick;
private final Supplier<Integer> minimalLookTimeSupplier;
private final Function<EntityCreature, Vector> randomDirectionFunction;
private Vector lookDirection;
private final Function<EntityCreature, Vec> randomDirectionFunction;
private Vec lookDirection;
private int lookTime = 0;
public RandomLookAroundGoal(EntityCreature entityCreature, int chancePerTick) {
this(entityCreature, chancePerTick,
// These two functions act similarily enough to how MC randomly looks around.
// These two functions act similarly enough to how MC randomly looks around.
// Look in one direction for at most 40 ticks and at minimum 20 ticks.
() -> 20 + RANDOM.nextInt(20),
// Look at a random block
(creature) -> {
final double n = Math.PI * 2 * RANDOM.nextDouble();
return new Vector(
return new Vec(
(float) Math.cos(n),
0,
(float) Math.sin(n)
@ -44,8 +45,7 @@ public class RandomLookAroundGoal extends GoalSelector {
EntityCreature entityCreature,
int chancePerTick,
@NotNull Supplier<Integer> minimalLookTimeSupplier,
@NotNull Function<EntityCreature, Vector> randomDirectionFunction
) {
@NotNull Function<EntityCreature, Vec> randomDirectionFunction) {
super(entityCreature);
this.chancePerTick = chancePerTick;
this.minimalLookTimeSupplier = minimalLookTimeSupplier;
@ -79,6 +79,5 @@ public class RandomLookAroundGoal extends GoalSelector {
@Override
public void end() {
}
}

View File

@ -2,7 +2,7 @@ package net.minestom.server.entity.ai.goal;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@ -14,14 +14,13 @@ public class RandomStrollGoal extends GoalSelector {
private static final long DELAY = 2500;
private final int radius;
private final List<Position> closePositions;
private final List<Vec> closePositions;
private long lastStroll;
public RandomStrollGoal(@NotNull EntityCreature entityCreature, int radius) {
super(entityCreature);
this.radius = radius;
this.closePositions = getNearbyBlocks(radius);
}
@ -33,20 +32,17 @@ public class RandomStrollGoal extends GoalSelector {
@Override
public void start() {
Collections.shuffle(closePositions);
for (Position position : closePositions) {
final Position target = position.clone().add(entityCreature.getPosition());
for (var position : closePositions) {
final var target = entityCreature.getPosition().add(position);
final boolean result = entityCreature.getNavigator().setPathTo(target);
if (result) {
break;
}
}
}
@Override
public void tick(long time) {
}
@Override
@ -64,17 +60,15 @@ public class RandomStrollGoal extends GoalSelector {
}
@NotNull
private List<Position> getNearbyBlocks(int radius) {
List<Position> blocks = new ArrayList<>();
private List<Vec> getNearbyBlocks(int radius) {
List<Vec> blocks = new ArrayList<>();
for (int x = -radius; x <= radius; x++) {
for (int y = -radius; y <= radius; y++) {
for (int z = -radius; z <= radius; z++) {
final Position position = new Position(x, y, z);
blocks.add(position);
blocks.add(new Vec(x, y, z));
}
}
}
return blocks;
}
}

View File

@ -104,7 +104,7 @@ public class RangedAttackGoal extends GoalSelector {
if (distanceSquared <= this.attackRangeSquared) {
if (!Cooldown.hasCooldown(time, this.lastShot, this.delay)) {
if (this.entityCreature.hasLineOfSight(target)) {
Position to = target.getPosition().clone().add(0D, target.getEyeHeight(), 0D);
final var to = target.getPosition().add(0D, target.getEyeHeight(), 0D);
Function<Entity, EntityProjectile> projectileGenerator = this.projectileGenerator;
if (projectileGenerator == null) {
@ -121,15 +121,15 @@ public class RangedAttackGoal extends GoalSelector {
}
}
Navigator navigator = this.entityCreature.getNavigator();
Position pathPosition = navigator.getPathPosition();
final var pathPosition = navigator.getPathPosition();
if (!comeClose && distanceSquared <= this.desirableRangeSquared) {
if (pathPosition != null) {
navigator.setPathTo(null);
}
return;
}
Position targetPosition = target.getPosition();
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
final var targetPosition = target.getPosition();
if (pathPosition == null || !pathPosition.samePoint(targetPosition)) {
if (this.cooldown.isReady(time)) {
this.cooldown.refreshLastUpdate(time);
navigator.setPathTo(targetPosition);

View File

@ -9,6 +9,7 @@ import net.minestom.server.entity.Player;
import net.minestom.server.entity.metadata.other.ArmorStandMeta;
import net.minestom.server.instance.Instance;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Pos;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
@ -25,7 +26,7 @@ public class Hologram implements Viewable {
private final Entity entity;
private final float yOffset;
private Position position;
private Pos position;
private Component text;
private boolean removed;
@ -36,35 +37,8 @@ public class Hologram implements Viewable {
* @param instance The instance where the hologram should be spawned.
* @param spawnPosition The spawn position of this hologram.
* @param text The text of this hologram.
* @param autoViewable {@code true}if the hologram should be visible automatically, otherwise {@code false}.
* @deprecated Use {@link #Hologram(Instance, Position, Component, boolean)}
*/
@Deprecated
public Hologram(Instance instance, Position spawnPosition, JsonMessage text, boolean autoViewable) {
this(instance, spawnPosition, text.asComponent(), autoViewable);
}
/**
* Constructs a new {@link Hologram} with the given parameters.
*
* @param instance The instance where the hologram should be spawned.
* @param spawnPosition The spawn position of this hologram.
* @param text The text of this hologram.
* @deprecated Use {@link #Hologram(Instance, Position, Component)}
*/
@Deprecated
public Hologram(Instance instance, Position spawnPosition, JsonMessage text) {
this(instance, spawnPosition, text, true);
}
/**
* Constructs a new {@link Hologram} with the given parameters.
*
* @param instance The instance where the hologram should be spawned.
* @param spawnPosition The spawn position of this hologram.
* @param text The text of this hologram.
*/
public Hologram(Instance instance, Position spawnPosition, Component text) {
public Hologram(Instance instance, Pos spawnPosition, Component text) {
this(instance, spawnPosition, text, true);
}
@ -76,7 +50,7 @@ public class Hologram implements Viewable {
* @param text The text of this hologram.
* @param autoViewable {@code true}if the hologram should be visible automatically, otherwise {@code false}.
*/
public Hologram(Instance instance, Position spawnPosition, Component text, boolean autoViewable) {
public Hologram(Instance instance, Pos spawnPosition, Component text, boolean autoViewable) {
this(instance, spawnPosition, text, autoViewable, false);
}
@ -88,7 +62,7 @@ public class Hologram implements Viewable {
* @param text The text of this hologram.
* @param autoViewable {@code true}if the hologram should be visible automatically, otherwise {@code false}.
*/
public Hologram(Instance instance, Position spawnPosition, Component text, boolean autoViewable, boolean marker) {
public Hologram(Instance instance, Pos spawnPosition, Component text, boolean autoViewable, boolean marker) {
this.entity = new Entity(EntityType.ARMOR_STAND);
ArmorStandMeta armorStandMeta = (ArmorStandMeta) entity.getEntityMeta();
@ -109,7 +83,7 @@ public class Hologram implements Viewable {
armorStandMeta.setNotifyAboutChanges(true);
this.entity.setInstance(instance, spawnPosition.clone().add(0, this.yOffset, 0));
this.entity.setInstance(instance, spawnPosition.add(0, this.yOffset, 0));
this.entity.setAutoViewable(autoViewable);
this.position = spawnPosition;
@ -121,7 +95,7 @@ public class Hologram implements Viewable {
*
* @return the hologram's position
*/
public Position getPosition() {
public Pos getPosition() {
return position;
}
@ -130,11 +104,10 @@ public class Hologram implements Viewable {
*
* @param position the new hologram's position
*/
public void setPosition(Position position) {
public void setPosition(Pos position) {
checkRemoved();
position.add(0, this.yOffset, 0);
this.position = position;
this.entity.teleport(position);
this.position = position.add(0, this.yOffset, 0);
this.entity.teleport(this.position);
}
/**

View File

@ -12,6 +12,9 @@ import net.minestom.server.instance.WorldBorder;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Pos;
import net.minestom.server.utils.coordinate.Vec;
import net.minestom.server.utils.position.PositionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -26,7 +29,7 @@ public class Navigator {
private final PFPathingEntity pathingEntity;
private HydrazinePathFinder pathFinder;
private IPath path;
private Position pathPosition;
private Point pathPosition;
private final Entity entity;
@ -43,17 +46,16 @@ public class Navigator {
* @param direction the targeted position
* @param speed define how far the entity will move
*/
public void moveTowards(@NotNull Position direction, double speed) {
public void moveTowards(@NotNull Point direction, double speed) {
final Pos position = entity.getPosition();
final Position position = entity.getPosition();
final double currentX = position.x();
final double currentY = position.y();
final double currentZ = position.z();
final double currentX = position.getX();
final double currentY = position.getY();
final double currentZ = position.getZ();
final double targetX = direction.getX();
final double targetY = direction.getY();
final double targetZ = direction.getZ();
final double targetX = direction.x();
final double targetY = direction.y();
final double targetZ = direction.z();
final double dx = targetX - currentX;
final double dy = targetY - currentY;
@ -71,7 +73,7 @@ public class Navigator {
final double speedZ = Math.sin(radians) * speed;
// Update 'position' view
PositionUtils.lookAlong(position, dx, direction.getY(), dz);
PositionUtils.lookAlong(position, dx, direction.y(), dz);
Position newPosition = new Position();
Vector newVelocityOut = new Vector();
@ -87,8 +89,7 @@ public class Navigator {
public void jump(float height) {
// FIXME magic value
final Vector velocity = new Vector(0, height * 2.5f, 0);
this.entity.setVelocity(velocity);
this.entity.setVelocity(new Vec(0, height * 2.5f, 0));
}
/**
@ -99,13 +100,13 @@ public class Navigator {
* The position is cloned, if you want the entity to continually follow this position object
* you need to call this when you want the path to update.
*
* @param position the position to find the path to, null to reset the pathfinder
* @param point the position to find the path to, null to reset the pathfinder
* @param bestEffort whether to use the best-effort algorithm to the destination,
* if false then this method is more likely to return immediately
* @return true if a path has been found
*/
public synchronized boolean setPathTo(@Nullable Position position, boolean bestEffort) {
if (position != null && pathPosition != null && position.isSimilar(pathPosition)) {
public synchronized boolean setPathTo(@Nullable Point point, boolean bestEffort) {
if (point != null && pathPosition != null && point.samePoint(pathPosition)) {
// Tried to set path to the same target position
return false;
}
@ -118,7 +119,7 @@ public class Navigator {
}
pathFinder.reset();
if (position == null) {
if (point == null) {
return false;
}
@ -129,38 +130,36 @@ public class Navigator {
// Can't path outside of the world border
final WorldBorder worldBorder = instance.getWorldBorder();
if (!worldBorder.isInside(position)) {
if (!worldBorder.isInside(point)) {
return false;
}
// Can't path in an unloaded chunk
final Chunk chunk = instance.getChunkAt(position);
final Chunk chunk = instance.getChunkAt(point);
if (!ChunkUtils.isLoaded(chunk)) {
return false;
}
final Position targetPosition = position.clone();
final PathOptions pathOptions = new PathOptions()
.targetingStrategy(bestEffort ? PathOptions.TargetingStrategy.gravitySnap :
PathOptions.TargetingStrategy.none);
final IPath path = pathFinder.initiatePathTo(
targetPosition.getX(),
targetPosition.getY(),
targetPosition.getZ(),
point.x(),
point.y(),
point.z(),
pathOptions);
this.path = path;
final boolean success = path != null;
this.pathPosition = success ? targetPosition : null;
this.pathPosition = success ? point : null;
return success;
}
/**
* @see #setPathTo(Position, boolean) with {@code bestEffort} sets to {@code true}.
* @see #setPathTo(Point, boolean) with {@code bestEffort} sets to {@code true}.
*/
public boolean setPathTo(@Nullable Position position) {
public boolean setPathTo(@Nullable Point position) {
return setPathTo(position, true);
}
@ -174,7 +173,7 @@ public class Navigator {
this.path = path;
if (path != null) {
final Position targetPosition = pathingEntity.getTargetPosition();
final Point targetPosition = pathingEntity.getTargetPosition();
if (targetPosition != null) {
moveTowards(targetPosition, speed);
}
@ -220,8 +219,7 @@ public class Navigator {
*
* @return the target pathfinder position, null if there is no one
*/
@Nullable
public Position getPathPosition() {
public @Nullable Point getPathPosition() {
return pathPosition;
}
@ -229,10 +227,10 @@ public class Navigator {
* Changes the position this element is trying to reach.
*
* @param pathPosition the new current path position
* @deprecated Please use {@link #setPathTo(Position)}
* @deprecated Please use {@link #setPathTo(Point)}
*/
@Deprecated
public void setPathPosition(@Nullable Position pathPosition) {
public void setPathPosition(@Nullable Point pathPosition) {
this.pathPosition = pathPosition;
}

View File

@ -8,6 +8,7 @@ import net.minestom.server.attribute.Attribute;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.LivingEntity;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Point;
import org.jetbrains.annotations.NotNull;
public class PFPathingEntity implements IPathingEntity {
@ -16,7 +17,7 @@ public class PFPathingEntity implements IPathingEntity {
private final Entity entity;
private float searchRange;
private Position targetPosition;
private Point targetPosition;
// Capacities
private boolean fireResistant;
@ -36,7 +37,7 @@ public class PFPathingEntity implements IPathingEntity {
this.searchRange = getAttributeValue(Attribute.FOLLOW_RANGE);
}
public Position getTargetPosition() {
public Point getTargetPosition() {
return targetPosition;
}
@ -195,16 +196,16 @@ public class PFPathingEntity implements IPathingEntity {
public void moveTo(Vec3d position, Passibility passibility, Gravitation gravitation) {
this.targetPosition = new Position(position.x, position.y, position.z);
final double entityY = entity.getPosition().getY();
if (entityY < targetPosition.getY()) {
final double entityY = entity.getPosition().y();
if (entityY < targetPosition.y()) {
this.navigator.jump(1);
}
}
@Override
public Vec3d coordinates() {
final Position position = entity.getPosition();
return new Vec3d(position.getX(), position.getY(), position.getZ());
final var position = entity.getPosition();
return new Vec3d(position.x(), position.y(), position.z());
}
@Override

View File

@ -5,6 +5,7 @@ import net.minestom.server.entity.EntityProjectile;
import net.minestom.server.event.trait.CancellableEvent;
import net.minestom.server.event.trait.EntityEvent;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Point;
import org.jetbrains.annotations.NotNull;
/**
@ -14,13 +15,13 @@ public class EntityShootEvent implements EntityEvent, CancellableEvent {
private final Entity entity;
private final Entity projectile;
private final Position to;
private final Point to;
private double power;
private double spread;
private boolean cancelled;
public EntityShootEvent(@NotNull Entity entity, @NotNull Entity projectile, @NotNull Position to, double power, double spread) {
public EntityShootEvent(@NotNull Entity entity, @NotNull Entity projectile, @NotNull Point to, double power, double spread) {
this.entity = entity;
this.projectile = projectile;
this.to = to;
@ -42,7 +43,7 @@ public class EntityShootEvent implements EntityEvent, CancellableEvent {
*
* @return the position projectile was shot to.
*/
public Position getTo() {
public Point getTo() {
return this.to;
}

View File

@ -3,20 +3,20 @@ package net.minestom.server.event.entity;
import net.minestom.server.entity.Entity;
import net.minestom.server.event.trait.CancellableEvent;
import net.minestom.server.event.trait.EntityEvent;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
/**
* Called when a velocity is applied to an entity using {@link Entity#setVelocity(Vector)}.
* Called when a velocity is applied to an entity using {@link Entity#setVelocity(Vec)}.
*/
public class EntityVelocityEvent implements EntityEvent, CancellableEvent {
private final Entity entity;
private Vector velocity;
private Vec velocity;
private boolean cancelled;
public EntityVelocityEvent(@NotNull Entity entity, @NotNull Vector velocity) {
public EntityVelocityEvent(@NotNull Entity entity, @NotNull Vec velocity) {
this.entity = entity;
this.velocity = velocity;
}
@ -26,9 +26,8 @@ public class EntityVelocityEvent implements EntityEvent, CancellableEvent {
*
* @return the entity
*/
@NotNull
@Override
public Entity getEntity() {
public @NotNull Entity getEntity() {
return entity;
}
@ -37,8 +36,7 @@ public class EntityVelocityEvent implements EntityEvent, CancellableEvent {
*
* @return the velocity
*/
@NotNull
public Vector getVelocity() {
public @NotNull Vec getVelocity() {
return velocity;
}
@ -47,7 +45,7 @@ public class EntityVelocityEvent implements EntityEvent, CancellableEvent {
*
* @param velocity the new velocity
*/
public void setVelocity(@NotNull Vector velocity) {
public void setVelocity(@NotNull Vec velocity) {
this.velocity = velocity;
}

View File

@ -3,7 +3,7 @@ package net.minestom.server.event.player;
import net.minestom.server.entity.Player;
import net.minestom.server.event.trait.CancellableEvent;
import net.minestom.server.event.trait.PlayerEvent;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
/**
@ -12,11 +12,11 @@ import org.jetbrains.annotations.NotNull;
public class PlayerMoveEvent implements PlayerEvent, CancellableEvent {
private final Player player;
private Position newPosition;
private Pos newPosition;
private boolean cancelled;
public PlayerMoveEvent(@NotNull Player player, @NotNull Position newPosition) {
public PlayerMoveEvent(@NotNull Player player, @NotNull Pos newPosition) {
this.player = player;
this.newPosition = newPosition;
}
@ -26,8 +26,7 @@ public class PlayerMoveEvent implements PlayerEvent, CancellableEvent {
*
* @return the new position
*/
@NotNull
public Position getNewPosition() {
public @NotNull Pos getNewPosition() {
return newPosition;
}
@ -36,7 +35,7 @@ public class PlayerMoveEvent implements PlayerEvent, CancellableEvent {
*
* @param newPosition the new target position
*/
public void setNewPosition(@NotNull Position newPosition) {
public void setNewPosition(@NotNull Pos newPosition) {
this.newPosition = newPosition;
}

View File

@ -1,9 +1,8 @@
package net.minestom.server.event.player;
import net.minestom.server.entity.Player;
import net.minestom.server.event.Event;
import net.minestom.server.event.trait.PlayerEvent;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
/**
@ -13,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
public class PlayerRespawnEvent implements PlayerEvent {
private final Player player;
private Position respawnPosition;
private Pos respawnPosition;
public PlayerRespawnEvent(@NotNull Player player) {
this.player = player;
@ -27,8 +26,7 @@ public class PlayerRespawnEvent implements PlayerEvent {
*
* @return the respawn position
*/
@NotNull
public Position getRespawnPosition() {
public @NotNull Pos getRespawnPosition() {
return respawnPosition;
}
@ -37,7 +35,7 @@ public class PlayerRespawnEvent implements PlayerEvent {
*
* @param respawnPosition the new respawn position
*/
public void setRespawnPosition(@NotNull Position respawnPosition) {
public void setRespawnPosition(@NotNull Pos respawnPosition) {
this.respawnPosition = respawnPosition;
}

View File

@ -35,6 +35,7 @@ import net.minestom.server.utils.Position;
import net.minestom.server.utils.chunk.ChunkCallback;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Pos;
import net.minestom.server.utils.entity.EntityUtils;
import net.minestom.server.utils.time.Cooldown;
import net.minestom.server.utils.time.TimeUnit;
@ -309,10 +310,10 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
* <p>
* Always returning false allow entities to survive in the void.
*
* @param position the position in the world
* @return true iif position is inside the void
* @param point the point in the world
* @return true if the point is inside the void
*/
public abstract boolean isInVoid(@NotNull Position position);
public abstract boolean isInVoid(@NotNull Point point);
/**
* Gets if the instance has been registered in {@link InstanceManager}.
@ -535,12 +536,12 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
/**
* Loads the chunk at the given {@link Position} with a callback.
*
* @param position the chunk position
* @param point the chunk position
* @param callback the optional callback to run when the chunk is loaded
*/
public void loadChunk(@NotNull Position position, @Nullable ChunkCallback callback) {
final int chunkX = ChunkUtils.getChunkCoordinate(position.getX());
final int chunkZ = ChunkUtils.getChunkCoordinate(position.getZ());
public void loadChunk(@NotNull Point point, @Nullable ChunkCallback callback) {
final int chunkX = ChunkUtils.getChunkCoordinate(point.x());
final int chunkZ = ChunkUtils.getChunkCoordinate(point.z());
loadChunk(chunkX, chunkZ, callback);
}
@ -548,12 +549,12 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
* Loads a {@link Chunk} (if {@link #hasEnabledAutoChunkLoad()} returns true)
* at the given {@link Position} with a callback.
*
* @param position the chunk position
* @param point the chunk position
* @param callback the optional callback executed when the chunk is loaded (or with a null chunk if not)
*/
public void loadOptionalChunk(@NotNull Position position, @Nullable ChunkCallback callback) {
final int chunkX = ChunkUtils.getChunkCoordinate(position.getX());
final int chunkZ = ChunkUtils.getChunkCoordinate(position.getZ());
public void loadOptionalChunk(@NotNull Point point, @Nullable ChunkCallback callback) {
final int chunkX = ChunkUtils.getChunkCoordinate(point.x());
final int chunkZ = ChunkUtils.getChunkCoordinate(point.z());
loadOptionalChunk(chunkX, chunkZ, callback);
}
@ -703,7 +704,7 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
}
AddEntityToInstanceEvent event = new AddEntityToInstanceEvent(this, entity);
EventDispatcher.callCancellable(event, () -> {
final Position entityPosition = entity.getPosition();
final Pos entityPosition = entity.getPosition();
final boolean isPlayer = entity instanceof Player;
if (isPlayer) {

View File

@ -19,7 +19,6 @@ import net.minestom.server.network.packet.server.play.UnloadChunkPacket;
import net.minestom.server.storage.StorageLocation;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.PacketUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.callback.OptionalCallback;
import net.minestom.server.utils.chunk.ChunkCallback;
import net.minestom.server.utils.chunk.ChunkSupplier;
@ -385,9 +384,9 @@ public class InstanceContainer extends Instance {
}
@Override
public boolean isInVoid(@NotNull Position position) {
public boolean isInVoid(@NotNull Point point) {
// TODO: customizable
return position.getY() < -64;
return point.y() < -64;
}
/**

View File

@ -4,7 +4,6 @@ import net.minestom.server.entity.Player;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.storage.StorageLocation;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.chunk.ChunkCallback;
import net.minestom.server.utils.coordinate.Point;
import org.jetbrains.annotations.NotNull;
@ -119,8 +118,8 @@ public class SharedInstance extends Instance {
}
@Override
public boolean isInVoid(@NotNull Position position) {
return instanceContainer.isInVoid(position);
public boolean isInVoid(@NotNull Point point) {
return instanceContainer.isInVoid(point);
}
/**

View File

@ -5,7 +5,7 @@ import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.utils.PacketUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Point;
import org.jetbrains.annotations.NotNull;
/**
@ -159,14 +159,13 @@ public class WorldBorder {
/**
* Used to check at which axis does the position collides with the world border.
*
* @param position the position to check
* @param point the point to check
* @return the axis where the position collides with the world border
*/
@NotNull
public CollisionAxis getCollisionAxis(@NotNull Position position) {
public @NotNull CollisionAxis getCollisionAxis(@NotNull Point point) {
final double radius = getDiameter() / 2d;
final boolean checkX = position.getX() <= getCenterX() + radius && position.getX() >= getCenterX() - radius;
final boolean checkZ = position.getZ() <= getCenterZ() + radius && position.getZ() >= getCenterZ() - radius;
final boolean checkX = point.x() <= getCenterX() + radius && point.x() >= getCenterX() - radius;
final boolean checkZ = point.z() <= getCenterZ() + radius && point.z() >= getCenterZ() - radius;
if (!checkX && !checkZ) {
return CollisionAxis.BOTH;
} else if (!checkX) {
@ -180,11 +179,11 @@ public class WorldBorder {
/**
* Used to know if a position is located inside the world border or not.
*
* @param position the position to check
* @param point the point to check
* @return true if {@code position} is inside the world border, false otherwise
*/
public boolean isInside(@NotNull Position position) {
return getCollisionAxis(position) == CollisionAxis.NONE;
public boolean isInside(@NotNull Point point) {
return getCollisionAxis(point) == CollisionAxis.NONE;
}
/**

View File

@ -155,7 +155,7 @@ public class StairsPlacementRule extends BlockPlacementRule {
@NotNull
private Facing getFacing(@NotNull Player player) {
float degrees = (player.getPosition().getYaw() - 90) % 360;
float degrees = (player.getPosition().yaw() - 90) % 360;
if (degrees < 0) {
degrees += 360;
}

View File

@ -13,7 +13,6 @@ import net.minestom.server.item.ItemStack;
import net.minestom.server.item.StackingRule;
import net.minestom.server.network.packet.client.play.ClientPlayerDiggingPacket;
import net.minestom.server.network.packet.server.play.AcknowledgePlayerDiggingPacket;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.coordinate.Point;
import org.jetbrains.annotations.NotNull;
@ -150,11 +149,10 @@ public class PlayerDiggingListener {
if (!result) {
if (block.isSolid()) {
final BlockPosition playerBlockPosition = player.getPosition().toBlockPosition();
final var playerPosition = player.getPosition();
// Teleport the player back if he broke a solid block just below him
if (playerBlockPosition.subtract(0, 1, 0).equals(blockPosition))
player.teleport(player.getPosition());
if (playerPosition.sub(0, 1, 0).samePoint(blockPosition))
player.teleport(playerPosition);
}
}
}

View File

@ -5,8 +5,8 @@ import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.instance.Instance;
import net.minestom.server.network.packet.client.play.*;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
public class PlayerPositionListener {
@ -16,10 +16,10 @@ public class PlayerPositionListener {
}
public static void playerLookListener(ClientPlayerRotationPacket packet, Player player) {
final Position playerPosition = player.getPosition();
final double x = playerPosition.getX();
final double y = playerPosition.getY();
final double z = playerPosition.getZ();
final var playerPosition = player.getPosition();
final double x = playerPosition.x();
final double y = playerPosition.y();
final double z = playerPosition.z();
final float yaw = packet.yaw;
final float pitch = packet.pitch;
final boolean onGround = packet.onGround;
@ -27,9 +27,9 @@ public class PlayerPositionListener {
}
public static void playerPositionListener(ClientPlayerPositionPacket packet, Player player) {
final Position playerPosition = player.getPosition();
final float yaw = playerPosition.getYaw();
final float pitch = playerPosition.getPitch();
final var playerPosition = player.getPosition();
final float yaw = playerPosition.yaw();
final float pitch = playerPosition.pitch();
final boolean onGround = packet.onGround;
processMovement(player,
packet.x, packet.y, packet.z,
@ -53,46 +53,35 @@ public class PlayerPositionListener {
private static void processMovement(@NotNull Player player, double x, double y, double z,
float yaw, float pitch, boolean onGround) {
final Instance instance = player.getInstance();
// Prevent moving before the player spawned, probably a modified client (or high latency?)
if (instance == null) {
return;
}
// Prevent the player from moving during a teleport
if (player.getLastSentTeleportId() != player.getLastReceivedTeleportId()) {
return;
}
// Try to move in an unloaded chunk, prevent it
if (!ChunkUtils.isLoaded(instance, x, z)) {
player.teleport(player.getPosition());
return;
}
final Position currentPosition = player.getPosition().clone();
Position newPosition = new Position(x, y, z, yaw, pitch);
final Position cachedPosition = newPosition.clone();
final var currentPosition = player.getPosition();
final var newPosition = new Pos(x, y, z, yaw, pitch);
PlayerMoveEvent playerMoveEvent = new PlayerMoveEvent(player, newPosition);
EventDispatcher.call(playerMoveEvent);
// True if the event call changed the player position (possibly a teleport)
final boolean positionChanged = !currentPosition.equals(player.getPosition());
if (!playerMoveEvent.isCancelled() && !positionChanged) {
// Move the player
newPosition = playerMoveEvent.getNewPosition();
if (!newPosition.equals(cachedPosition)) {
// New position from the event changed, teleport the player
player.teleport(newPosition);
}
// Change the internal data
player.refreshPosition(newPosition);
player.refreshPosition(playerMoveEvent.getNewPosition());
player.refreshOnGround(onGround);
} else {
// Cancelled, teleport to previous position
player.teleport(player.getPosition());
}
}
}

View File

@ -6,7 +6,7 @@ import net.minestom.server.entity.metadata.other.BoatMeta;
import net.minestom.server.network.packet.client.play.ClientSteerBoatPacket;
import net.minestom.server.network.packet.client.play.ClientSteerVehiclePacket;
import net.minestom.server.network.packet.client.play.ClientVehicleMovePacket;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Pos;
public class PlayerVehicleListener {
@ -19,11 +19,10 @@ public class PlayerVehicleListener {
public static void vehicleMoveListener(ClientVehicleMovePacket packet, Player player) {
final Entity vehicle = player.getVehicle();
if (vehicle == null)
return;
final Position newPosition = new Position((float) packet.x, (float) packet.y, (float) packet.z, packet.yaw, packet.pitch);
final var newPosition = new Pos(packet.x, packet.y, packet.z, packet.yaw, packet.pitch);
vehicle.refreshPosition(newPosition);
// This packet causes weird screen distortion
@ -39,7 +38,6 @@ public class PlayerVehicleListener {
public static void boatSteerListener(ClientSteerBoatPacket packet, Player player) {
final Entity vehicle = player.getVehicle();
if (!(vehicle.getEntityMeta() instanceof BoatMeta))
return;
@ -47,5 +45,4 @@ public class PlayerVehicleListener {
boat.setLeftPaddleTurning(packet.leftPaddleTurning);
boat.setRightPaddleTurning(packet.rightPaddleTurning);
}
}

View File

@ -2,9 +2,9 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
public class EntityPositionAndRotationPacket implements ServerPacket {
@ -14,7 +14,8 @@ public class EntityPositionAndRotationPacket implements ServerPacket {
public float yaw, pitch;
public boolean onGround;
public EntityPositionAndRotationPacket() {}
public EntityPositionAndRotationPacket() {
}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -44,15 +45,15 @@ public class EntityPositionAndRotationPacket implements ServerPacket {
}
public static EntityPositionAndRotationPacket getPacket(int entityId,
@NotNull Position newPosition, @NotNull Position oldPosition,
@NotNull Pos newPosition, @NotNull Pos oldPosition,
boolean onGround) {
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
entityPositionAndRotationPacket.entityId = entityId;
entityPositionAndRotationPacket.deltaX = (short) ((newPosition.getX() * 32 - oldPosition.getX() * 32) * 128);
entityPositionAndRotationPacket.deltaY = (short) ((newPosition.getY() * 32 - oldPosition.getY() * 32) * 128);
entityPositionAndRotationPacket.deltaZ = (short) ((newPosition.getZ() * 32 - oldPosition.getZ() * 32) * 128);
entityPositionAndRotationPacket.yaw = newPosition.getYaw();
entityPositionAndRotationPacket.pitch = newPosition.getPitch();
entityPositionAndRotationPacket.deltaX = (short) ((newPosition.x() * 32 - oldPosition.x() * 32) * 128);
entityPositionAndRotationPacket.deltaY = (short) ((newPosition.y() * 32 - oldPosition.y() * 32) * 128);
entityPositionAndRotationPacket.deltaZ = (short) ((newPosition.z() * 32 - oldPosition.z() * 32) * 128);
entityPositionAndRotationPacket.yaw = newPosition.yaw();
entityPositionAndRotationPacket.pitch = newPosition.pitch();
entityPositionAndRotationPacket.onGround = onGround;
return entityPositionAndRotationPacket;

View File

@ -2,9 +2,9 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
public class EntityPositionPacket implements ServerPacket {
@ -13,7 +13,8 @@ public class EntityPositionPacket implements ServerPacket {
public short deltaX, deltaY, deltaZ;
public boolean onGround;
public EntityPositionPacket() {}
public EntityPositionPacket() {
}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -40,13 +41,13 @@ public class EntityPositionPacket implements ServerPacket {
@NotNull
public static EntityPositionPacket getPacket(int entityId,
@NotNull Position newPosition, @NotNull Position oldPosition,
@NotNull Pos newPosition, @NotNull Pos oldPosition,
boolean onGround) {
EntityPositionPacket entityPositionPacket = new EntityPositionPacket();
entityPositionPacket.entityId = entityId;
entityPositionPacket.deltaX = (short) ((newPosition.getX() * 32 - oldPosition.getX() * 32) * 128);
entityPositionPacket.deltaY = (short) ((newPosition.getY() * 32 - oldPosition.getY() * 32) * 128);
entityPositionPacket.deltaZ = (short) ((newPosition.getZ() * 32 - oldPosition.getZ() * 32) * 128);
entityPositionPacket.deltaX = (short) ((newPosition.x() * 32 - oldPosition.x() * 32) * 128);
entityPositionPacket.deltaY = (short) ((newPosition.y() * 32 - oldPosition.y() * 32) * 128);
entityPositionPacket.deltaZ = (short) ((newPosition.z() * 32 - oldPosition.z() * 32) * 128);
entityPositionPacket.onGround = onGround;
return entityPositionPacket;

View File

@ -2,42 +2,42 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
public class EntityTeleportPacket implements ServerPacket {
public int entityId;
public Position position;
public Pos position;
public boolean onGround;
public EntityTeleportPacket() {
position = new Position();
position = Pos.ZERO;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(entityId);
writer.writeDouble(position.getX());
writer.writeDouble(position.getY());
writer.writeDouble(position.getZ());
writer.writeByte((byte) (position.getYaw() * 256f / 360f));
writer.writeByte((byte) (position.getPitch() * 256f / 360f));
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeByte((byte) (position.yaw() * 256f / 360f));
writer.writeByte((byte) (position.pitch() * 256f / 360f));
writer.writeBoolean(onGround);
}
@Override
public void read(@NotNull BinaryReader reader) {
entityId = reader.readVarInt();
position = new Position(
position = new Pos(
reader.readDouble(),
reader.readDouble(),
reader.readDouble(),
reader.readByte() * 360f / 256f,
reader.readByte() * 360f / 256f
);
);
onGround = reader.readBoolean();
}

View File

@ -2,30 +2,30 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
public class PlayerPositionAndLookPacket implements ServerPacket {
public Position position;
public Pos position;
public byte flags;
public int teleportId;
public boolean dismountVehicle;
public PlayerPositionAndLookPacket() {
position = new Position();
position = Pos.ZERO;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeDouble(position.getX());
writer.writeDouble(position.getY());
writer.writeDouble(position.getZ());
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeFloat(position.getYaw());
writer.writeFloat(position.getPitch());
writer.writeFloat(position.yaw());
writer.writeFloat(position.pitch());
writer.writeByte(flags);
writer.writeVarInt(teleportId);
@ -34,7 +34,7 @@ public class PlayerPositionAndLookPacket implements ServerPacket {
@Override
public void read(@NotNull BinaryReader reader) {
position = new Position(reader.readDouble(), reader.readDouble(), reader.readDouble(), reader.readFloat(), reader.readFloat());
position = new Pos(reader.readDouble(), reader.readDouble(), reader.readDouble(), reader.readFloat(), reader.readFloat());
flags = reader.readByte();
teleportId = reader.readVarInt();

View File

@ -5,9 +5,9 @@ import net.minestom.server.adventure.AdventurePacketConvertor;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
public class SoundEffectPacket implements ServerPacket {
@ -23,18 +23,19 @@ public class SoundEffectPacket implements ServerPacket {
}
@NotNull
public static SoundEffectPacket create(Source category, SoundEvent sound, Position position, float volume, float pitch) {
public static SoundEffectPacket create(Source category, SoundEvent sound, Pos position, float volume, float pitch) {
SoundEffectPacket packet = new SoundEffectPacket();
packet.soundId = sound.getId();
packet.soundSource = category;
// *8 converts to fixed-point representation with 3 bits for fractional part
packet.x = (int) position.getX();
packet.y = (int) position.getY();
packet.z = (int) position.getZ();
packet.x = (int) position.x();
packet.y = (int) position.y();
packet.z = (int) position.z();
packet.volume = volume;
packet.pitch = pitch;
return packet;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(soundId);
@ -50,9 +51,9 @@ public class SoundEffectPacket implements ServerPacket {
public void read(@NotNull BinaryReader reader) {
soundId = reader.readVarInt();
soundSource = Source.values()[reader.readVarInt()];
x = reader.readInt()/8;
y = reader.readInt()/8;
z = reader.readInt()/8;
x = reader.readInt() / 8;
y = reader.readInt() / 8;
z = reader.readInt() / 8;
volume = reader.readFloat();
pitch = reader.readFloat();
}

View File

@ -2,9 +2,9 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@ -14,13 +14,13 @@ public class SpawnEntityPacket implements ServerPacket {
public int entityId;
public UUID uuid;
public int type;
public Position position;
public Pos position;
public int data;
public short velocityX, velocityY, velocityZ;
public SpawnEntityPacket() {
uuid = new UUID(0, 0);
position = new Position();
position = Pos.ZERO;
}
@Override
@ -29,12 +29,12 @@ public class SpawnEntityPacket implements ServerPacket {
writer.writeUuid(uuid);
writer.writeVarInt(type);
writer.writeDouble(position.getX());
writer.writeDouble(position.getY());
writer.writeDouble(position.getZ());
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeByte((byte) (position.getYaw() * 256 / 360));
writer.writeByte((byte) (position.getPitch() * 256 / 360));
writer.writeByte((byte) (position.yaw() * 256 / 360));
writer.writeByte((byte) (position.pitch() * 256 / 360));
writer.writeInt(data);
@ -49,10 +49,9 @@ public class SpawnEntityPacket implements ServerPacket {
uuid = reader.readUuid();
type = reader.readVarInt();
position = new Position(reader.readDouble(), reader.readDouble(), reader.readDouble());
position.setYaw(reader.readByte() * 360f / 256f);
position.setPitch(reader.readByte() * 360f / 256f);
position = new Pos(reader.readDouble(), reader.readDouble(), reader.readDouble(),
reader.readByte() * 360f / 256f,
reader.readByte() * 360f / 256f);
data = reader.readInt();

View File

@ -2,34 +2,34 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
public class SpawnExperienceOrbPacket implements ServerPacket {
public int entityId;
public Position position;
public Pos position;
public short expCount;
public SpawnExperienceOrbPacket() {
position = new Position();
position = Pos.ZERO;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(entityId);
writer.writeDouble(position.getX());
writer.writeDouble(position.getY());
writer.writeDouble(position.getZ());
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeShort(expCount);
}
@Override
public void read(@NotNull BinaryReader reader) {
entityId = reader.readVarInt();
position = new Position(reader.readDouble(), reader.readDouble(), reader.readDouble());
position = new Pos(reader.readDouble(), reader.readDouble(), reader.readDouble());
expCount = reader.readShort();
}

View File

@ -2,9 +2,9 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@ -14,13 +14,13 @@ public class SpawnLivingEntityPacket implements ServerPacket {
public int entityId;
public UUID entityUuid;
public int entityType;
public Position position;
public Pos position;
public float headPitch;
public short velocityX, velocityY, velocityZ;
public SpawnLivingEntityPacket() {
entityUuid = new UUID(0, 0);
position = new Position();
position = Pos.ZERO;
}
@Override
@ -29,12 +29,12 @@ public class SpawnLivingEntityPacket implements ServerPacket {
writer.writeUuid(entityUuid);
writer.writeVarInt(entityType);
writer.writeDouble(position.getX());
writer.writeDouble(position.getY());
writer.writeDouble(position.getZ());
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeByte((byte) (position.getYaw() * 256 / 360));
writer.writeByte((byte) (position.getPitch() * 256 / 360));
writer.writeByte((byte) (position.yaw() * 256 / 360));
writer.writeByte((byte) (position.pitch() * 256 / 360));
writer.writeByte((byte) (headPitch * 256 / 360));
writer.writeShort(velocityX);
@ -48,10 +48,9 @@ public class SpawnLivingEntityPacket implements ServerPacket {
entityUuid = reader.readUuid();
entityType = reader.readVarInt();
position = new Position(reader.readDouble(), reader.readDouble(), reader.readDouble());
position.setYaw(reader.readByte() * 360f / 256f);
position.setPitch(reader.readByte() * 360f / 256f);
position = new Pos(reader.readDouble(), reader.readDouble(), reader.readDouble(),
reader.readByte() * 360f / 256f,
reader.readByte() * 360f / 256f);
headPitch = reader.readByte() * 360f / 256f;
velocityX = reader.readShort();

View File

@ -2,9 +2,9 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@ -13,31 +13,31 @@ public class SpawnPlayerPacket implements ServerPacket {
public int entityId;
public UUID playerUuid;
public Position position;
public Pos position;
public SpawnPlayerPacket() {
playerUuid = new UUID(0,0);
position = new Position();
playerUuid = new UUID(0, 0);
position = Pos.ZERO;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(entityId);
writer.writeUuid(playerUuid);
writer.writeDouble(position.getX());
writer.writeDouble(position.getY());
writer.writeDouble(position.getZ());
writer.writeByte((byte) (position.getYaw() * 256f / 360f));
writer.writeByte((byte) (position.getPitch() * 256f / 360f));
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeByte((byte) (position.yaw() * 256f / 360f));
writer.writeByte((byte) (position.pitch() * 256f / 360f));
}
@Override
public void read(@NotNull BinaryReader reader) {
entityId = reader.readVarInt();
playerUuid = reader.readUuid();
position = new Position(reader.readDouble(), reader.readDouble(), reader.readDouble());
position.setYaw((reader.readByte() * 360f) / 256f);
position.setPitch((reader.readByte() * 360f) / 256f);
this.entityId = reader.readVarInt();
this.playerUuid = reader.readUuid();
this.position = new Pos(reader.readDouble(), reader.readDouble(), reader.readDouble(),
(reader.readByte() * 360f) / 256f,
(reader.readByte() * 360f) / 256f);
}
@Override

View File

@ -5,6 +5,7 @@ import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
@ -228,7 +229,7 @@ public class BlockIterator implements Iterator<BlockPosition> {
* trace. Setting this value above 140 may lead to problems with
* unloaded chunks. A value of 0 indicates no limit
*/
public BlockIterator(@NotNull Position pos, double yOffset, int maxDistance) {
public BlockIterator(@NotNull Pos pos, double yOffset, int maxDistance) {
this(pos.toVector(), pos.getDirection(), yOffset, maxDistance);
}
@ -242,7 +243,7 @@ public class BlockIterator implements Iterator<BlockPosition> {
* by this value
*/
public BlockIterator(@NotNull Position pos, double yOffset) {
public BlockIterator(@NotNull Pos pos, double yOffset) {
this(pos.toVector(), pos.getDirection(), yOffset, 0);
}
@ -254,7 +255,7 @@ public class BlockIterator implements Iterator<BlockPosition> {
* @param pos The position for the start of the ray trace
*/
public BlockIterator(@NotNull Position pos) {
public BlockIterator(@NotNull Pos pos) {
this(pos, 0f);
}

View File

@ -6,6 +6,7 @@ import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.callback.OptionalCallback;
import net.minestom.server.utils.coordinate.Point;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -103,8 +104,8 @@ public final class ChunkUtils {
return originChunk;
}
public static Chunk retrieve(Instance instance, Chunk originChunk, Position position) {
return retrieve(instance, originChunk, position.getX(), position.getZ());
public static Chunk retrieve(Instance instance, Chunk originChunk, Point position) {
return retrieve(instance, originChunk, position.x(), position.z());
}
public static Chunk retrieve(Instance instance, Chunk originChunk, BlockPosition blockPosition) {
@ -170,11 +171,11 @@ public final class ChunkUtils {
/**
* Gets the chunks in range of a position.
*
* @param position the initial position
* @param point the initial point
* @param range how far should it retrieves chunk
* @return an array containing chunks index
*/
public static long @NotNull [] getChunksInRange(@NotNull Position position, int range) {
public static long @NotNull [] getChunksInRange(@NotNull Point point, int range) {
long[] visibleChunks = new long[MathUtils.square(range * 2 + 1)];
int xDistance = 0;
int xDirection = 1;
@ -184,8 +185,8 @@ public final class ChunkUtils {
int corner = 0;
for (int i = 0; i < visibleChunks.length; i++) {
final int chunkX = getChunkCoordinate(xDistance * Chunk.CHUNK_SIZE_X + position.getX());
final int chunkZ = getChunkCoordinate(zDistance * Chunk.CHUNK_SIZE_Z + position.getZ());
final int chunkX = getChunkCoordinate(xDistance * Chunk.CHUNK_SIZE_X + point.x());
final int chunkZ = getChunkCoordinate(zDistance * Chunk.CHUNK_SIZE_Z + point.z());
visibleChunks[i] = getChunkIndex(chunkX, chunkZ);
if (corner % 2 == 0) {

View File

@ -1,6 +1,7 @@
package net.minestom.server.utils.coordinate;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@ -138,4 +139,27 @@ public interface Point {
MathUtils.square(y() - point.y()) +
MathUtils.square(z() - point.z());
}
/**
* Checks it two points have similar (x/y/z).
*
* @param point the point to compare
* @return true if the two positions are similar
*/
default boolean samePoint(@NotNull Point point) {
return Double.compare(point.x(), x()) == 0 &&
Double.compare(point.y(), y()) == 0 &&
Double.compare(point.z(), z()) == 0;
}
/**
* Gets if two points are in the same chunk.
*
* @param point the point to compare two
* @return true if 'this' is in the same chunk as {@code position}
*/
default boolean inSameChunk(@NotNull Point point) {
return ChunkUtils.getChunkCoordinate(x()) == ChunkUtils.getChunkCoordinate(point.x()) &&
ChunkUtils.getChunkCoordinate(z()) == ChunkUtils.getChunkCoordinate(point.z());
}
}

View File

@ -1,8 +1,10 @@
package net.minestom.server.utils.coordinate;
import net.minestom.server.utils.Position;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.function.DoubleUnaryOperator;
/**
@ -11,6 +13,8 @@ import java.util.function.DoubleUnaryOperator;
* To become record and primitive.
*/
public final class Pos implements Point {
public static final Pos ZERO = new Pos(0, 0, 0);
private final double x, y, z;
private final float yaw, pitch;
@ -34,6 +38,10 @@ public final class Pos implements Point {
this(point, 0, 0);
}
public static @NotNull Pos fromPosition(@NotNull Position position) {
return new Pos(position.getX(), position.getY(), position.getZ(), position.getYaw(), position.getPitch());
}
@Contract(pure = true)
public @NotNull Pos withCoord(double x, double y, double z) {
return new Pos(x, y, z, yaw, pitch);
@ -69,6 +77,33 @@ public final class Pos implements Point {
return new Pos(x, y, z, yaw, (float) operator.applyAsDouble(pitch));
}
/**
* Checks if two positions have a similar view (yaw/pitch).
*
* @param position the position to compare
* @return true if the two positions have the same view
*/
public boolean sameView(@NotNull Pos position) {
return Float.compare(position.yaw, yaw) == 0 &&
Float.compare(position.pitch, pitch) == 0;
}
/**
* Gets a unit-vector pointing in the direction that this Location is
* facing.
*
* @return a vector pointing the direction of this location's {@link
* #pitch() pitch} and {@link #yaw() yaw}
*/
public @NotNull Vec direction() {
final float rotX = yaw;
final float rotY = pitch;
final double xz = Math.cos(Math.toRadians(rotY));
return new Vec(-xz * Math.sin(Math.toRadians(rotX)),
-Math.sin(Math.toRadians(rotY)),
xz * Math.cos(Math.toRadians(rotX)));
}
@Override
@Contract(pure = true)
public double x() {
@ -203,6 +238,23 @@ public final class Pos implements Point {
return new Vec(x, y, z);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pos pos = (Pos) o;
return Double.compare(pos.x, x) == 0 &&
Double.compare(pos.y, y) == 0 &&
Double.compare(pos.z, z) == 0 &&
Float.compare(pos.yaw, yaw) == 0 &&
Float.compare(pos.pitch, pitch) == 0;
}
@Override
public int hashCode() {
return Objects.hash(x, y, z, yaw, pitch);
}
@FunctionalInterface
public interface Operator {
@NotNull Pos apply(double x, double y, double z);

View File

@ -156,19 +156,19 @@ public class EntityFinder {
// Diff X/Y/Z
if (dx != null || dy != null || dz != null) {
result = result.stream().filter(entity -> {
final Position entityPosition = entity.getPosition();
final var entityPosition = entity.getPosition();
if (dx != null && !MathUtils.isBetweenUnordered(
entityPosition.getX(),
entityPosition.x(),
startPosition.getX(), dx))
return false;
if (dy != null && !MathUtils.isBetweenUnordered(
entityPosition.getY(),
entityPosition.y(),
startPosition.getY(), dy))
return false;
if (dz != null && !MathUtils.isBetweenUnordered(
entityPosition.getZ(),
entityPosition.z(),
startPosition.getZ(), dz))
return false;
@ -231,12 +231,12 @@ public class EntityFinder {
// RANDOM is handled below
return 1;
case FURTHEST:
return startPosition.getDistance(ent1.getPosition()) >
startPosition.getDistance(ent2.getPosition()) ?
return startPosition.distance(ent1.getPosition()) >
startPosition.distance(ent2.getPosition()) ?
1 : 0;
case NEAREST:
return startPosition.getDistance(ent1.getPosition()) <
startPosition.getDistance(ent2.getPosition()) ?
return startPosition.distance(ent1.getPosition()) <
startPosition.distance(ent2.getPosition()) ?
1 : 0;
}
return 1;
@ -346,7 +346,7 @@ public class EntityFinder {
Collection<Player> instancePlayers = instance != null ?
instance.getPlayers() : MinecraftServer.getConnectionManager().getOnlinePlayers();
for (Player player : instancePlayers) {
final double distance = player.getPosition().getDistance(startPosition);
final double distance = player.getPosition().distance(startPosition);
if (distance < closestDistance) {
entity = player;
closestDistance = distance;

View File

@ -5,9 +5,9 @@ import net.minestom.server.entity.Entity;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
@ -18,11 +18,10 @@ public final class EntityUtils {
}
public static void forEachRange(@NotNull Instance instance, @NotNull Position position,
public static void forEachRange(@NotNull Instance instance, @NotNull Point point,
int viewDistance,
@NotNull Consumer<Entity> consumer) {
final long[] chunksInRange = ChunkUtils.getChunksInRange(position, viewDistance);
final long[] chunksInRange = ChunkUtils.getChunksInRange(point, viewDistance);
for (long chunkIndex : chunksInRange) {
final int chunkX = ChunkUtils.getChunkCoordX(chunkIndex);
final int chunkZ = ChunkUtils.getChunkCoordZ(chunkIndex);
@ -40,7 +39,6 @@ public final class EntityUtils {
return false;
final Chunk chunk = ent1.getInstance().getChunkAt(ent1.getPosition());
final long[] visibleChunksEntity = ChunkUtils.getChunksInRange(ent2.getPosition(), MinecraftServer.getEntityViewDistance());
for (long visibleChunk : visibleChunksEntity) {
final int chunkX = ChunkUtils.getChunkCoordX(visibleChunk);
@ -48,7 +46,6 @@ public final class EntityUtils {
if (chunk.getChunkX() == chunkX && chunk.getChunkZ() == chunkZ)
return true;
}
return false;
}
@ -56,18 +53,14 @@ public final class EntityUtils {
final Chunk chunk = entity.getChunk();
if (chunk == null)
return false;
final Position entityPosition = entity.getPosition();
final Pos entityPosition = entity.getPosition();
// TODO: check entire bounding box
final BlockPosition blockPosition = entityPosition.toBlockPosition().subtract(0, 1, 0);
try {
final Block block = chunk.getBlock(blockPosition);
final Block block = chunk.getBlock(entityPosition.sub(0, 1, 0));
return block.isSolid();
} catch (NullPointerException e) {
// Probably an entity at the border of an unloaded chunk
return false;
}
}
}

View File

@ -2,6 +2,8 @@ package net.minestom.server.utils.location;
import net.minestom.server.entity.Entity;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Point;
import net.minestom.server.utils.coordinate.Pos;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -11,7 +13,7 @@ import org.jetbrains.annotations.Nullable;
*
* @param <T> the location type
*/
public abstract class RelativeLocation<T> {
public abstract class RelativeLocation<T extends Point> {
protected T location;
protected boolean relativeX, relativeY, relativeZ;
@ -41,13 +43,13 @@ public abstract class RelativeLocation<T> {
* @return the location
*/
public T from(@Nullable Entity entity) {
final Position entityPosition = entity != null ? entity.getPosition() : new Position();
final var entityPosition = entity != null ? entity.getPosition() : Pos.ZERO;
return from(entityPosition);
}
@ApiStatus.Experimental
public T fromView(@Nullable Entity entity) {
final Position entityPosition = entity != null ? entity.getPosition() : new Position();
final var entityPosition = entity != null ? entity.getPosition() : Pos.ZERO;
return fromView(entityPosition);
}

View File

@ -7,7 +7,7 @@ import net.minestom.server.event.player.PlayerLoginEvent;
import net.minestom.server.instance.*;
import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.coordinate.Pos;
import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull;
@ -31,7 +31,7 @@ public class MainDemo {
globalEventHandler.addListener(PlayerLoginEvent.class, event -> {
final Player player = event.getPlayer();
event.setSpawningInstance(instanceContainer);
player.setRespawnPoint(new Position(0, 42, 0));
player.setRespawnPoint(new Pos(0, 42, 0));
});
// Start the server on port 25565

View File

@ -30,8 +30,8 @@ import net.minestom.server.item.Material;
import net.minestom.server.monitoring.BenchmarkManager;
import net.minestom.server.monitoring.TickMonitor;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.coordinate.Pos;
import net.minestom.server.utils.coordinate.Vec;
import net.minestom.server.utils.time.TimeUnit;
import net.minestom.server.world.DimensionType;
@ -75,11 +75,11 @@ public class PlayerInit {
final Player player = event.getPlayer();
ItemStack droppedItem = event.getItemStack();
Position position = player.getPosition().clone().add(0, 1.5f, 0);
ItemEntity itemEntity = new ItemEntity(droppedItem, position);
Pos playerPos = player.getPosition();
ItemEntity itemEntity = new ItemEntity(droppedItem);
itemEntity.setPickupDelay(Duration.of(500, TimeUnit.MILLISECOND));
itemEntity.setInstance(player.getInstance());
Vector velocity = player.getPosition().clone().getDirection().multiply(6);
itemEntity.setInstance(player.getInstance(), playerPos.withY(y -> y + 1.5));
Vec velocity = playerPos.direction().mul(6);
itemEntity.setVelocity(velocity);
})
.addListener(PlayerDisconnectEvent.class, event -> System.out.println("DISCONNECTION " + event.getPlayer().getUsername()))
@ -91,7 +91,7 @@ public class PlayerInit {
event.setSpawningInstance(instance);
int x = Math.abs(ThreadLocalRandom.current().nextInt()) % 500 - 250;
int z = Math.abs(ThreadLocalRandom.current().nextInt()) % 500 - 250;
player.setRespawnPoint(new Position(0, 42f, 0));
player.setRespawnPoint(new Pos(0, 42f, 0));
})
.addListener(PlayerSpawnEvent.class, event -> {
final Player player = event.getPlayer();