Merge remote-tracking branch 'upstream/master'

This commit is contained in:
iamceph 2021-01-26 09:46:41 +01:00
commit 564d549f81
26 changed files with 444 additions and 211 deletions

View File

@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
public class BoundingBox { public class BoundingBox {
private final Entity entity; private final Entity entity;
private final float x, y, z; private final double x, y, z;
/** /**
* Creates a {@link BoundingBox} linked to an {@link Entity} and with a specific size. * Creates a {@link BoundingBox} linked to an {@link Entity} and with a specific size.
@ -22,7 +22,7 @@ public class BoundingBox {
* @param y the height size * @param y the height size
* @param z the depth size * @param z the depth size
*/ */
public BoundingBox(@NotNull Entity entity, float x, float y, float z) { public BoundingBox(@NotNull Entity entity, double x, double y, double z) {
this.entity = entity; this.entity = entity;
this.x = x; this.x = x;
this.y = y; this.y = y;
@ -59,30 +59,30 @@ public class BoundingBox {
*/ */
public boolean intersect(@NotNull BlockPosition blockPosition) { public boolean intersect(@NotNull BlockPosition blockPosition) {
final float offsetX = 1; final double offsetX = 1;
final float x = blockPosition.getX(); final double x = blockPosition.getX();
final float maxX = x + offsetX; final double maxX = x + offsetX;
final boolean checkX = getMinX() < maxX && getMaxX() > x; final boolean checkX = getMinX() < maxX && getMaxX() > x;
if (!checkX) if (!checkX)
return false; return false;
final float y = blockPosition.getY(); final double y = blockPosition.getY();
final float maxY = y + 0.99999f; final double maxY = y + 0.99999;
final boolean checkY = getMinY() < maxY && getMaxY() > y; final boolean checkY = getMinY() < maxY && getMaxY() > y;
if (!checkY) if (!checkY)
return false; return false;
final float offsetZ = 1; final double offsetZ = 1;
final float z = blockPosition.getZ(); final double z = blockPosition.getZ();
final float maxZ = z + offsetZ; final double maxZ = z + offsetZ;
// Z check // Z check
return getMinZ() < maxZ && getMaxZ() > z; return getMinZ() < maxZ && getMaxZ() > z;
} }
public boolean intersect(float x, float y, float z) { public boolean intersect(double x, double y, double z) {
return (x >= getMinX() && x <= getMaxX()) && return (x >= getMinX() && x <= getMaxX()) &&
(y >= getMinY() && y <= getMaxY()) && (y >= getMinY() && y <= getMaxY()) &&
(z >= getMinZ() && z <= getMaxZ()); (z >= getMinZ() && z <= getMaxZ());
@ -101,7 +101,7 @@ public class BoundingBox {
* @return a new {@link BoundingBox} expanded * @return a new {@link BoundingBox} expanded
*/ */
@NotNull @NotNull
public BoundingBox expand(float x, float y, float z) { public BoundingBox expand(double x, double y, double z) {
return new BoundingBox(entity, this.x + x, this.y + y, this.z + z); return new BoundingBox(entity, this.x + x, this.y + y, this.z + z);
} }
@ -114,7 +114,7 @@ public class BoundingBox {
* @return a new bounding box contracted * @return a new bounding box contracted
*/ */
@NotNull @NotNull
public BoundingBox contract(float x, float y, float z) { public BoundingBox contract(double x, double y, double z) {
return new BoundingBox(entity, this.x - x, this.y - y, this.z - z); return new BoundingBox(entity, this.x - x, this.y - y, this.z - z);
} }
@ -123,7 +123,7 @@ public class BoundingBox {
* *
* @return the width * @return the width
*/ */
public float getWidth() { public double getWidth() {
return x; return x;
} }
@ -132,7 +132,7 @@ public class BoundingBox {
* *
* @return the height * @return the height
*/ */
public float getHeight() { public double getHeight() {
return y; return y;
} }
@ -141,7 +141,7 @@ public class BoundingBox {
* *
* @return the depth * @return the depth
*/ */
public float getDepth() { public double getDepth() {
return z; return z;
} }
@ -150,7 +150,7 @@ public class BoundingBox {
* *
* @return the min X * @return the min X
*/ */
public float getMinX() { public double getMinX() {
return entity.getPosition().getX() - (x / 2); return entity.getPosition().getX() - (x / 2);
} }
@ -159,7 +159,7 @@ public class BoundingBox {
* *
* @return the max X * @return the max X
*/ */
public float getMaxX() { public double getMaxX() {
return entity.getPosition().getX() + (x / 2); return entity.getPosition().getX() + (x / 2);
} }
@ -168,7 +168,7 @@ public class BoundingBox {
* *
* @return the min Y * @return the min Y
*/ */
public float getMinY() { public double getMinY() {
return entity.getPosition().getY(); return entity.getPosition().getY();
} }
@ -177,7 +177,7 @@ public class BoundingBox {
* *
* @return the max Y * @return the max Y
*/ */
public float getMaxY() { public double getMaxY() {
return entity.getPosition().getY() + y; return entity.getPosition().getY() + y;
} }
@ -186,7 +186,7 @@ public class BoundingBox {
* *
* @return the min Z * @return the min Z
*/ */
public float getMinZ() { public double getMinZ() {
return entity.getPosition().getZ() - (z / 2); return entity.getPosition().getZ() - (z / 2);
} }
@ -195,7 +195,7 @@ public class BoundingBox {
* *
* @return the max Z * @return the max Z
*/ */
public float getMaxZ() { public double getMaxZ() {
return entity.getPosition().getZ() + (z / 2); return entity.getPosition().getZ() + (z / 2);
} }

View File

@ -80,7 +80,7 @@ public class CollisionUtils {
* @param corners the corners to check against * @param corners the corners to check against
* @return true if a collision has been found * @return true if a collision has been found
*/ */
private static boolean stepAxis(Instance instance, Vector startPosition, Vector axis, float stepAmount, Vector positionOut, Vector... corners) { private static boolean stepAxis(Instance instance, Vector startPosition, Vector axis, double stepAmount, Vector positionOut, Vector... corners) {
positionOut.copy(startPosition); positionOut.copy(startPosition);
if (corners.length == 0) if (corners.length == 0)
return false; // avoid degeneracy in following computations return false; // avoid degeneracy in following computations
@ -93,9 +93,9 @@ public class CollisionUtils {
cornerPositions[i] = new BlockPosition(corners[i]); cornerPositions[i] = new BlockPosition(corners[i]);
} }
float sign = Math.signum(stepAmount); final double sign = Math.signum(stepAmount);
final int blockLength = (int) stepAmount; final int blockLength = (int) stepAmount;
final float remainingLength = stepAmount - blockLength; final double remainingLength = stepAmount - blockLength;
// used to determine if 'remainingLength' should be used // used to determine if 'remainingLength' should be used
boolean collisionFound = false; boolean collisionFound = false;
for (int i = 0; i < Math.abs(blockLength); i++) { for (int i = 0; i < Math.abs(blockLength); i++) {
@ -115,9 +115,9 @@ public class CollisionUtils {
} }
// find the corner which moved the least // find the corner which moved the least
float smallestDisplacement = Float.POSITIVE_INFINITY; double smallestDisplacement = Double.POSITIVE_INFINITY;
for (int i = 0; i < corners.length; i++) { for (int i = 0; i < corners.length; i++) {
final float displacement = (float) corners[i].distance(cornersCopy[i]); final double displacement = corners[i].distance(cornersCopy[i]);
if (displacement < smallestDisplacement) { if (displacement < smallestDisplacement) {
smallestDisplacement = displacement; smallestDisplacement = displacement;
} }
@ -133,12 +133,13 @@ public class CollisionUtils {
* *
* @param instance instance to get blocks from * @param instance instance to get blocks from
* @param axis the axis to move along * @param axis the axis to move along
* @param amount
* @param cornersCopy the corners of the bounding box to consider (mutable) * @param cornersCopy the corners of the bounding box to consider (mutable)
* @param cornerPositions the corners, converted to BlockPosition (mutable) * @param cornerPositions the corners, converted to BlockPosition (mutable)
* @return false if this method encountered a collision * @return false if this method encountered a collision
*/ */
private static boolean stepOnce(Instance instance, Vector axis, float amount, Vector[] cornersCopy, BlockPosition[] cornerPositions) { private static boolean stepOnce(Instance instance, Vector axis, double amount, Vector[] cornersCopy, BlockPosition[] cornerPositions) {
final float sign = Math.signum(amount); final double sign = Math.signum(amount);
for (int cornerIndex = 0; cornerIndex < cornersCopy.length; cornerIndex++) { for (int cornerIndex = 0; cornerIndex < cornersCopy.length; cornerIndex++) {
Vector corner = cornersCopy[cornerIndex]; Vector corner = cornersCopy[cornerIndex];
BlockPosition blockPos = cornerPositions[cornerIndex]; BlockPosition blockPos = cornerPositions[cornerIndex];

View File

@ -80,8 +80,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
protected Instance instance; protected Instance instance;
protected final Position position; protected final Position position;
protected float lastX, lastY, lastZ; protected double lastX, lastY, lastZ;
protected float cacheX, cacheY, cacheZ; // Used to synchronize with #getPosition protected double cacheX, cacheY, cacheZ; // Used to synchronize with #getPosition
protected float lastYaw, lastPitch; protected float lastYaw, lastPitch;
protected float cacheYaw, cachePitch; protected float cacheYaw, cachePitch;
protected boolean onGround; protected boolean onGround;
@ -93,9 +93,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
// Velocity // Velocity
protected Vector velocity = new Vector(); // Movement in block per second protected Vector velocity = new Vector(); // Movement in block per second
protected float gravityDragPerTick; protected double gravityDragPerTick;
protected float gravityAcceleration; protected double gravityAcceleration;
protected float gravityTerminalVelocity; protected double gravityTerminalVelocity;
protected int gravityTickCount; // Number of tick where gravity tick was applied protected int gravityTickCount; // Number of tick where gravity tick was applied
private boolean autoViewable; private boolean autoViewable;
@ -422,7 +422,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
cacheZ != position.getZ(); cacheZ != position.getZ();
final boolean viewChange = cacheYaw != position.getYaw() || final boolean viewChange = cacheYaw != position.getYaw() ||
cachePitch != position.getPitch(); cachePitch != position.getPitch();
final float distance = positionChange ? position.getDistance(cacheX, cacheY, cacheZ) : 0; final double distance = positionChange ? position.getDistance(cacheX, cacheY, cacheZ) : 0;
if (distance >= 8 || (positionChange && PlayerUtils.isNettyClient(this))) { if (distance >= 8 || (positionChange && PlayerUtils.isNettyClient(this))) {
// Teleport has the priority over everything else // Teleport has the priority over everything else
@ -477,16 +477,16 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
if (applyVelocity) { if (applyVelocity) {
final float tps = MinecraftServer.TICK_PER_SECOND; final float tps = MinecraftServer.TICK_PER_SECOND;
final float newX = position.getX() + velocity.getX() / tps; final double newX = position.getX() + velocity.getX() / tps;
final float newY = position.getY() + velocity.getY() / tps; final double newY = position.getY() + velocity.getY() / tps;
final float newZ = position.getZ() + velocity.getZ() / tps; final double newZ = position.getZ() + velocity.getZ() / tps;
Position newPosition = new Position(newX, newY, newZ); Position newPosition = new Position(newX, newY, newZ);
Vector newVelocityOut = new Vector(); Vector newVelocityOut = new Vector();
// Gravity force // Gravity force
final float gravityY = !noGravity ? Math.min( final double gravityY = !noGravity ? Math.min(
gravityDragPerTick + (gravityAcceleration * (float) gravityTickCount), gravityDragPerTick + (gravityAcceleration * (double) gravityTickCount),
gravityTerminalVelocity) : 0f; gravityTerminalVelocity) : 0f;
final Vector deltaPos = new Vector( final Vector deltaPos = new Vector(
@ -716,7 +716,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* @param y the bounding box Y size * @param y the bounding box Y size
* @param z the bounding box Z size * @param z the bounding box Z size
*/ */
public void setBoundingBox(float x, float y, float z) { public void setBoundingBox(double x, double y, double z) {
this.boundingBox = new BoundingBox(this, x, y, z); this.boundingBox = new BoundingBox(this, x, y, z);
} }
@ -815,7 +815,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* *
* @return the gravity drag per tick in block * @return the gravity drag per tick in block
*/ */
public float getGravityDragPerTick() { public double getGravityDragPerTick() {
return gravityDragPerTick; return gravityDragPerTick;
} }
@ -824,7 +824,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* *
* @return the gravity acceleration in block * @return the gravity acceleration in block
*/ */
public float getGravityAcceleration() { public double getGravityAcceleration() {
return gravityAcceleration; return gravityAcceleration;
} }
@ -833,7 +833,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* *
* @return the maximum gravity velocity in block * @return the maximum gravity velocity in block
*/ */
public float getGravityTerminalVelocity() { public double getGravityTerminalVelocity() {
return gravityTerminalVelocity; return gravityTerminalVelocity;
} }
@ -854,7 +854,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* @param gravityTerminalVelocity the gravity terminal velocity (maximum) in block * @param gravityTerminalVelocity the gravity terminal velocity (maximum) in block
* @see <a href="https://minecraft.gamepedia.com/Entity#Motion_of_entities">Entities motion</a> * @see <a href="https://minecraft.gamepedia.com/Entity#Motion_of_entities">Entities motion</a>
*/ */
public void setGravity(float gravityDragPerTick, float gravityAcceleration, float gravityTerminalVelocity) { public void setGravity(double gravityDragPerTick, double gravityAcceleration, double gravityTerminalVelocity) {
this.gravityDragPerTick = gravityDragPerTick; this.gravityDragPerTick = gravityDragPerTick;
this.gravityAcceleration = gravityAcceleration; this.gravityAcceleration = gravityAcceleration;
this.gravityTerminalVelocity = gravityTerminalVelocity; this.gravityTerminalVelocity = gravityTerminalVelocity;
@ -866,7 +866,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* @param entity the entity to get the distance from * @param entity the entity to get the distance from
* @return the distance between this and {@code entity} * @return the distance between this and {@code entity}
*/ */
public float getDistance(@NotNull Entity entity) { public double getDistance(@NotNull Entity entity) {
return getPosition().getDistance(entity.getPosition()); return getPosition().getDistance(entity.getPosition());
} }
@ -1102,7 +1102,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* @param y new position Y * @param y new position Y
* @param z new position Z * @param z new position Z
*/ */
public void refreshPosition(float x, float y, float z) { public void refreshPosition(double x, double y, double z) {
position.setX(x); position.setX(x);
position.setY(y); position.setY(y);
position.setZ(z); position.setZ(z);
@ -1147,7 +1147,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
/** /**
* @param position the new position * @param position the new position
* @see #refreshPosition(float, float, float) * @see #refreshPosition(double, double, double)
*/ */
public void refreshPosition(@NotNull Position position) { public void refreshPosition(@NotNull Position position) {
refreshPosition(position.getX(), position.getY(), position.getZ()); refreshPosition(position.getX(), position.getY(), position.getZ());
@ -1237,8 +1237,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* *
* @return the entity eye height * @return the entity eye height
*/ */
public float getEyeHeight() { public double getEyeHeight() {
return boundingBox.getHeight() * 0.85f; return boundingBox.getHeight() * 0.85;
} }
/** /**

View File

@ -3,12 +3,13 @@ package net.minestom.server.entity;
import net.minestom.server.instance.Instance; import net.minestom.server.instance.Instance;
import net.minestom.server.network.packet.server.play.SpawnExperienceOrbPacket; import net.minestom.server.network.packet.server.play.SpawnExperienceOrbPacket;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position; import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector; import net.minestom.server.utils.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Comparator;
public class ExperienceOrb extends Entity { public class ExperienceOrb extends Entity {
private short experienceCount; private short experienceCount;
@ -132,7 +133,7 @@ public class ExperienceOrb extends Entity {
Player closest = entity.getInstance() Player closest = entity.getInstance()
.getPlayers() .getPlayers()
.stream() .stream()
.min((a, b) -> Float.compare(a.getDistance(entity), b.getDistance(entity))) .min(Comparator.comparingDouble(a -> a.getDistance(entity)))
.orElse(null); .orElse(null);
if (closest == null) return null; if (closest == null) return null;
if (closest.getDistance(entity) > maxDistance) return null; if (closest.getDistance(entity) > maxDistance) return null;

View File

@ -27,7 +27,6 @@ import net.minestom.server.utils.block.BlockIterator;
import net.minestom.server.utils.time.CooldownUtils; import net.minestom.server.utils.time.CooldownUtils;
import net.minestom.server.utils.time.TimeUnit; import net.minestom.server.utils.time.TimeUnit;
import net.minestom.server.utils.time.UpdateOption; import net.minestom.server.utils.time.UpdateOption;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -451,7 +450,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
} }
@Override @Override
public void setBoundingBox(float x, float y, float z) { public void setBoundingBox(double x, double y, double z) {
super.setBoundingBox(x, y, z); super.setBoundingBox(x, y, z);
this.expandedBoundingBox = getBoundingBox().expand(1, 0.5f, 1); this.expandedBoundingBox = getBoundingBox().expand(1, 0.5f, 1);
} }

View File

@ -169,7 +169,8 @@ public class Player extends LivingEntity implements CommandSender {
// Position synchronization with viewers // Position synchronization with viewers
private long lastPlayerSynchronizationTime; private long lastPlayerSynchronizationTime;
private float lastPlayerSyncX, lastPlayerSyncY, lastPlayerSyncZ, lastPlayerSyncYaw, lastPlayerSyncPitch; private double lastPlayerSyncX, lastPlayerSyncY, lastPlayerSyncZ;
private float lastPlayerSyncYaw, lastPlayerSyncPitch;
// Experience orb pickup // Experience orb pickup
protected UpdateOption experiencePickupCooldown = new UpdateOption(10, TimeUnit.TICK); protected UpdateOption experiencePickupCooldown = new UpdateOption(10, TimeUnit.TICK);
@ -1615,7 +1616,7 @@ public class Player extends LivingEntity implements CommandSender {
// Manage already viewable entities // Manage already viewable entities
this.viewableEntities.forEach(entity -> { this.viewableEntities.forEach(entity -> {
final float distance = entity.getDistance(this); final double distance = entity.getDistance(this);
if (distance > maximalDistance) { if (distance > maximalDistance) {
// Entity shouldn't be viewable anymore // Entity shouldn't be viewable anymore
if (isAutoViewable()) { if (isAutoViewable()) {

View File

@ -83,7 +83,7 @@ public class FollowTargetGoal extends GoalSelector {
entityCreature.setPathTo(null); entityCreature.setPathTo(null);
} }
private float getDistance(@NotNull Position a, @NotNull Position b) { private double getDistance(@NotNull Position a, @NotNull Position b) {
return MathUtils.square(a.getX() - b.getX()) + return MathUtils.square(a.getX() - b.getX()) +
MathUtils.square(a.getZ() - b.getZ()); MathUtils.square(a.getZ() - b.getZ());
} }

View File

@ -39,7 +39,7 @@ public class ClosestEntityTarget extends TargetSelector {
final List<Chunk> chunks = getNeighbours(instance, currentChunk.getChunkX(), currentChunk.getChunkZ()); final List<Chunk> chunks = getNeighbours(instance, currentChunk.getChunkX(), currentChunk.getChunkZ());
Entity entity = null; Entity entity = null;
float distance = Float.MAX_VALUE; double distance = Double.MAX_VALUE;
for (Chunk chunk : chunks) { for (Chunk chunk : chunks) {
final Set<Entity> entities = instance.getChunkEntities(chunk); final Set<Entity> entities = instance.getChunkEntities(chunk);
@ -76,7 +76,7 @@ public class ClosestEntityTarget extends TargetSelector {
} }
// Check distance // Check distance
final float d = entityCreature.getDistance(ent); final double d = entityCreature.getDistance(ent);
if ((entity == null || d < distance) && d < range) { if ((entity == null || d < distance) && d < range) {
entity = ent; entity = ent;
distance = d; distance = d;

View File

@ -12,7 +12,6 @@ import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector; import net.minestom.server.utils.Vector;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.position.PositionUtils; import net.minestom.server.utils.position.PositionUtils;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -29,32 +28,32 @@ public interface NavigableEntity {
* @param direction the targeted position * @param direction the targeted position
* @param speed define how far the entity will move * @param speed define how far the entity will move
*/ */
default void moveTowards(@NotNull Position direction, float speed) { default void moveTowards(@NotNull Position direction, double speed) {
final Position position = getNavigableEntity().getPosition(); final Position position = getNavigableEntity().getPosition();
final float currentX = position.getX(); final double currentX = position.getX();
final float currentY = position.getY(); final double currentY = position.getY();
final float currentZ = position.getZ(); final double currentZ = position.getZ();
final float targetX = direction.getX(); final double targetX = direction.getX();
final float targetY = direction.getY(); final double targetY = direction.getY();
final float targetZ = direction.getZ(); final double targetZ = direction.getZ();
final float dx = targetX - currentX; final double dx = targetX - currentX;
final float dy = targetY - currentY; final double dy = targetY - currentY;
final float dz = targetZ - currentZ; final double dz = targetZ - currentZ;
// the purpose of these few lines is to slow down entities when they reach their destination // the purpose of these few lines is to slow down entities when they reach their destination
final float distSquared = dx * dx + dy * dy + dz * dz; final double distSquared = dx * dx + dy * dy + dz * dz;
if (speed > distSquared) { if (speed > distSquared) {
speed = distSquared; speed = distSquared;
} }
final float radians = (float) Math.atan2(dz, dx); final double radians = Math.atan2(dz, dx);
final float speedX = (float) (Math.cos(radians) * speed); final double speedX = Math.cos(radians) * speed;
final float speedY = dy * speed; final double speedY = dy * speed;
final float speedZ = (float) (Math.sin(radians) * speed); final double speedZ = Math.sin(radians) * speed;
// Update 'position' view // Update 'position' view
PositionUtils.lookAlong(position, dx, direction.getY(), dz); PositionUtils.lookAlong(position, dx, direction.getY(), dz);

View File

@ -189,13 +189,10 @@ public class PFPathingEntity implements IPathingEntity {
@Override @Override
public void moveTo(Vec3d position, Passibility passibility, Gravitation gravitation) { public void moveTo(Vec3d position, Passibility passibility, Gravitation gravitation) {
final float x = (float) position.x; this.targetPosition = new Position(position.x, position.y, position.z);
final float y = (float) position.y;
final float z = (float) position.z;
this.targetPosition = new Position(x, y, z);
final float entityY = entity.getPosition().getY(); final double entityY = entity.getPosition().getY();
if (entityY < y) { if (entityY < targetPosition.getY()) {
navigableEntity.jump(1); navigableEntity.jump(1);
} }
} }
@ -208,12 +205,12 @@ public class PFPathingEntity implements IPathingEntity {
@Override @Override
public float width() { public float width() {
return entity.getBoundingBox().getWidth(); return (float) entity.getBoundingBox().getWidth();
} }
@Override @Override
public float height() { public float height() {
return entity.getBoundingBox().getHeight(); return (float) entity.getBoundingBox().getHeight();
} }
private float getAttributeValue(@NotNull Attribute attribute) { private float getAttributeValue(@NotNull Attribute attribute) {

View File

@ -311,15 +311,15 @@ public class EntityArmorStand extends ObjectEntity implements EquipmentHandler {
} }
private float getRotationX(Vector vector) { private float getRotationX(Vector vector) {
return vector != null ? vector.getX() : 0; return vector != null ? (float) vector.getX() : 0;
} }
private float getRotationY(Vector vector) { private float getRotationY(Vector vector) {
return vector != null ? vector.getY() : 0; return vector != null ? (float) vector.getY() : 0;
} }
private float getRotationZ(Vector vector) { private float getRotationZ(Vector vector) {
return vector != null ? vector.getZ() : 0; return vector != null ? (float) vector.getZ() : 0;
} }
// Equipments // Equipments

View File

@ -62,7 +62,7 @@ public class EntityZombie extends EntityCreature implements Monster {
} }
@Override @Override
public float getEyeHeight() { public double getEyeHeight() {
return isBaby() ? 0.93f : 1.74f; return isBaby() ? 0.93 : 1.74;
} }
} }

View File

@ -72,7 +72,7 @@ public class EntityZombifiedPiglin extends EntityCreature implements Monster {
} }
@Override @Override
public float getEyeHeight() { public double getEyeHeight() {
return isBaby() ? 0.93f : 1.74f; return isBaby() ? 0.93 : 1.74;
} }
} }

View File

@ -657,8 +657,8 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
* @param z the Z position * @param z the Z position
* @return the block state id at the position * @return the block state id at the position
*/ */
public short getBlockStateId(float x, float y, float z) { public short getBlockStateId(double x, double y, double z) {
return getBlockStateId(Math.round(x), Math.round(y), Math.round(z)); return getBlockStateId((int) Math.round(x), (int) Math.round(y), (int) Math.round(z));
} }
/** /**
@ -785,7 +785,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
* @return the chunk at the given position, null if not loaded * @return the chunk at the given position, null if not loaded
*/ */
@Nullable @Nullable
public Chunk getChunkAt(float x, float z) { public Chunk getChunkAt(double x, double z) {
final int chunkX = ChunkUtils.getChunkCoordinate((int) Math.floor(x)); final int chunkX = ChunkUtils.getChunkCoordinate((int) Math.floor(x));
final int chunkZ = ChunkUtils.getChunkCoordinate((int) Math.floor(z)); final int chunkZ = ChunkUtils.getChunkCoordinate((int) Math.floor(z));
return getChunk(chunkX, chunkZ); return getChunk(chunkX, chunkZ);

View File

@ -155,13 +155,13 @@ public final class InstanceManager {
} }
/** /**
* Gets instance by given UUID. * Gets an instance by the given UUID.
* *
* @param uuid UUID of the instance * @param uuid UUID of the instance
* @return {@link Optional#empty()} if instance is not found * @return the instance with the given UUID, null if not found
*/ */
@NotNull @Nullable
public @Nullable Instance getInstance(UUID uuid) { public Instance getInstance(@NotNull UUID uuid) {
Optional<Instance> instance = getInstances() Optional<Instance> instance = getInstances()
.stream() .stream()
.filter(someInstance -> someInstance.getUniqueId().equals(uuid)) .filter(someInstance -> someInstance.getUniqueId().equals(uuid))

View File

@ -20,9 +20,9 @@ public class PlayerPositionListener {
public static void playerLookListener(ClientPlayerRotationPacket packet, Player player) { public static void playerLookListener(ClientPlayerRotationPacket packet, Player player) {
final Position playerPosition = player.getPosition(); final Position playerPosition = player.getPosition();
final float x = playerPosition.getX(); final double x = playerPosition.getX();
final float y = playerPosition.getY(); final double y = playerPosition.getY();
final float z = playerPosition.getZ(); final double z = playerPosition.getZ();
final float yaw = packet.yaw; final float yaw = packet.yaw;
final float pitch = packet.pitch; final float pitch = packet.pitch;
final boolean onGround = packet.onGround; final boolean onGround = packet.onGround;
@ -31,26 +31,24 @@ public class PlayerPositionListener {
public static void playerPositionListener(ClientPlayerPositionPacket packet, Player player) { public static void playerPositionListener(ClientPlayerPositionPacket packet, Player player) {
final Position playerPosition = player.getPosition(); final Position playerPosition = player.getPosition();
final float x = (float) packet.x;
final float y = (float) packet.y;
final float z = (float) packet.z;
final float yaw = playerPosition.getYaw(); final float yaw = playerPosition.getYaw();
final float pitch = playerPosition.getPitch(); final float pitch = playerPosition.getPitch();
final boolean onGround = packet.onGround; final boolean onGround = packet.onGround;
processMovement(player, x, y, z, yaw, pitch, onGround); processMovement(player,
packet.x, packet.y, packet.z,
yaw, pitch, onGround);
} }
public static void playerPositionAndLookListener(ClientPlayerPositionAndRotationPacket packet, Player player) { public static void playerPositionAndLookListener(ClientPlayerPositionAndRotationPacket packet, Player player) {
final float x = (float) packet.x;
final float y = (float) packet.y;
final float z = (float) packet.z;
final float yaw = packet.yaw; final float yaw = packet.yaw;
final float pitch = packet.pitch; final float pitch = packet.pitch;
final boolean onGround = packet.onGround; final boolean onGround = packet.onGround;
processMovement(player, x, y, z, yaw, pitch, onGround); processMovement(player,
packet.x, packet.y, packet.z,
yaw, pitch, onGround);
} }
private static void processMovement(@NotNull Player player, float x, float y, float z, private static void processMovement(@NotNull Player player, double x, double y, double z,
float yaw, float pitch, boolean onGround) { float yaw, float pitch, boolean onGround) {
final Instance instance = player.getInstance(); final Instance instance = player.getInstance();
@ -60,7 +58,7 @@ public class PlayerPositionListener {
} }
// Prevent the player from moving during a teleport // Prevent the player from moving during a teleport
final float distance = player.getPosition().getDistance(x, y, z); final double distance = player.getPosition().getDistance(x, y, z);
final int chunkRange = player.getChunkRange() * Chunk.CHUNK_SECTION_SIZE; final int chunkRange = player.getChunkRange() * Chunk.CHUNK_SECTION_SIZE;
if (distance >= chunkRange) { if (distance >= chunkRange) {
return; return;

View File

@ -1,6 +1,5 @@
package net.minestom.server.scoreboard; package net.minestom.server.scoreboard;
import com.google.common.collect.Queues;
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet; import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
import net.minestom.server.chat.ChatParser; import net.minestom.server.chat.ChatParser;
import net.minestom.server.chat.ColoredText; import net.minestom.server.chat.ColoredText;
@ -16,8 +15,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -37,7 +34,7 @@ public class Sidebar implements Scoreboard {
private static final AtomicInteger COUNTER = new AtomicInteger(); private static final AtomicInteger COUNTER = new AtomicInteger();
/** /**
* <b>WARNING:</b> You shouldn't create scoreboards/teams with the same prefixes as those * <b>WARNING:</b> You should NOT create any scoreboards/teams with the same prefixes as those
*/ */
private static final String SCOREBOARD_PREFIX = "sb-"; private static final String SCOREBOARD_PREFIX = "sb-";
private static final String TEAM_PREFIX = "sbt-"; private static final String TEAM_PREFIX = "sbt-";
@ -48,9 +45,8 @@ public class Sidebar implements Scoreboard {
private static final int MAX_LINES_COUNT = 15; private static final int MAX_LINES_COUNT = 15;
private final Set<Player> viewers = new CopyOnWriteArraySet<>(); private final Set<Player> viewers = new CopyOnWriteArraySet<>();
private final Set<Player> unmodifiableViewers = Collections.unmodifiableSet(viewers);
private final Queue<ScoreboardLine> lines = Queues.newConcurrentLinkedQueue(); private final Set<ScoreboardLine> lines = new CopyOnWriteArraySet<>();
private final IntLinkedOpenHashSet availableColors = new IntLinkedOpenHashSet(); private final IntLinkedOpenHashSet availableColors = new IntLinkedOpenHashSet();
private final String objectiveName; private final String objectiveName;
@ -164,26 +160,33 @@ public class Sidebar implements Scoreboard {
return null; return null;
} }
/**
* Gets a {@link Set} containing all the registered lines.
*
* @return an unmodifiable set containing the sidebar's lines
*/
@NotNull
public Set<ScoreboardLine> getLines() {
return Collections.unmodifiableSet(lines);
}
/** /**
* Removes a {@link ScoreboardLine} through the given identifier * Removes a {@link ScoreboardLine} through the given identifier
* *
* @param id the identifier of the {@link ScoreboardLine} * @param id the identifier of the {@link ScoreboardLine}
*/ */
public void removeLine(@NotNull String id) { public void removeLine(@NotNull String id) {
synchronized (lines) { this.lines.removeIf(line -> {
Iterator<ScoreboardLine> iterator = lines.iterator();
while (iterator.hasNext()) {
final ScoreboardLine line = iterator.next();
if (line.id.equals(id)) { if (line.id.equals(id)) {
// Remove the line for current viewers // Remove the line for current viewers
sendPacketsToViewers(line.getScoreCreationPacket(objectiveName), line.sidebarTeam.getDestructionPacket()); sendPacketsToViewers(line.getScoreCreationPacket(objectiveName), line.sidebarTeam.getDestructionPacket());
line.returnName(availableColors); line.returnName(availableColors);
iterator.remove(); return true;
}
}
} }
return false;
});
} }
@Override @Override
@ -221,7 +224,7 @@ public class Sidebar implements Scoreboard {
@NotNull @NotNull
@Override @Override
public Set<Player> getViewers() { public Set<Player> getViewers() {
return unmodifiableViewers; return Collections.unmodifiableSet(viewers);
} }
@Override @Override
@ -258,7 +261,7 @@ public class Sidebar implements Scoreboard {
*/ */
private SidebarTeam sidebarTeam; private SidebarTeam sidebarTeam;
public ScoreboardLine(String id, JsonMessage content, int line) { public ScoreboardLine(@NotNull String id, @NotNull JsonMessage content, int line) {
this.id = id; this.id = id;
this.content = content; this.content = content;
this.line = line; this.line = line;
@ -271,6 +274,7 @@ public class Sidebar implements Scoreboard {
* *
* @return the line identifier * @return the line identifier
*/ */
@NotNull
public String getId() { public String getId() {
return id; return id;
} }
@ -280,6 +284,7 @@ public class Sidebar implements Scoreboard {
* *
* @return The line content * @return The line content
*/ */
@NotNull
public JsonMessage getContent() { public JsonMessage getContent() {
return sidebarTeam == null ? content : sidebarTeam.getPrefix(); return sidebarTeam == null ? content : sidebarTeam.getPrefix();
} }
@ -473,7 +478,7 @@ public class Sidebar implements Scoreboard {
* *
* @param prefix The refreshed prefix * @param prefix The refreshed prefix
*/ */
private void refreshPrefix(JsonMessage prefix) { private void refreshPrefix(@NotNull JsonMessage prefix) {
this.prefix = prefix; this.prefix = prefix;
} }
} }

View File

@ -38,7 +38,7 @@ public class BlockPosition implements PublicCloneable<BlockPosition> {
* @param y the block Y * @param y the block Y
* @param z the block Z * @param z the block Z
*/ */
public BlockPosition(float x, float y, float z) { public BlockPosition(double x, double y, double z) {
final int castedY = (int) y; final int castedY = (int) y;
this.x = (int) Math.floor(x); this.x = (int) Math.floor(x);
@ -50,7 +50,7 @@ public class BlockPosition implements PublicCloneable<BlockPosition> {
* Creates a new {@link BlockPosition} from a {@link Vector}. * Creates a new {@link BlockPosition} from a {@link Vector}.
* *
* @param position the position vector * @param position the position vector
* @see #BlockPosition(float, float, float) * @see #BlockPosition(double, double, double)
*/ */
public BlockPosition(@NotNull Vector position) { public BlockPosition(@NotNull Vector position) {
this(position.getX(), position.getY(), position.getZ()); this(position.getX(), position.getY(), position.getZ());

View File

@ -14,6 +14,10 @@ public final class MathUtils {
return num * num; return num * num;
} }
public static double square(double num) {
return num * num;
}
public static double round(double value, int places) { public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException(); if (places < 0) throw new IllegalArgumentException();
@ -55,10 +59,22 @@ public final class MathUtils {
return number >= min && number <= max; return number >= min && number <= max;
} }
public static boolean isBetween(double number, double min, double max) {
return number >= min && number <= max;
}
public static boolean isBetween(float number, float min, float max) { public static boolean isBetween(float number, float min, float max) {
return number >= min && number <= max; return number >= min && number <= max;
} }
public static boolean isBetweenUnordered(double number, double compare1, double compare2) {
if (compare1 > compare2) {
return isBetween(number, compare2, compare1);
} else {
return isBetween(number, compare1, compare2);
}
}
public static boolean isBetweenUnordered(float number, float compare1, float compare2) { public static boolean isBetweenUnordered(float number, float compare1, float compare2) {
if (compare1 > compare2) { if (compare1 > compare2) {
return isBetween(number, compare2, compare1); return isBetween(number, compare2, compare1);

View File

@ -13,10 +13,10 @@ import java.util.Objects;
*/ */
public class Position implements PublicCloneable<Position> { public class Position implements PublicCloneable<Position> {
private float x, y, z; private double x, y, z;
private float yaw, pitch; private float yaw, pitch;
public Position(float x, float y, float z, float yaw, float pitch) { public Position(double x, double y, double z, float yaw, float pitch) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
@ -24,7 +24,7 @@ public class Position implements PublicCloneable<Position> {
this.pitch = pitch; this.pitch = pitch;
} }
public Position(float x, float y, float z) { public Position(double x, double y, double z) {
this(x, y, z, 0, 0); this(x, y, z, 0, 0);
} }
@ -40,7 +40,8 @@ public class Position implements PublicCloneable<Position> {
* @param z the Z offset * @param z the Z offset
* @return the same object position * @return the same object position
*/ */
public Position add(float x, float y, float z) { @NotNull
public Position add(double x, double y, double z) {
this.x += x; this.x += x;
this.y += y; this.y += y;
this.z += z; this.z += z;
@ -53,7 +54,8 @@ public class Position implements PublicCloneable<Position> {
* @param position the position to add to this * @param position the position to add to this
* @return the same object position * @return the same object position
*/ */
public Position add(Position position) { @NotNull
public Position add(@NotNull Position position) {
this.x += position.x; this.x += position.x;
this.y += position.y; this.y += position.y;
this.z += position.z; this.z += position.z;
@ -68,15 +70,16 @@ public class Position implements PublicCloneable<Position> {
* @param z the Z offset * @param z the Z offset
* @return the same object position * @return the same object position
*/ */
public Position subtract(float x, float y, float z) { @NotNull
public Position subtract(double x, double y, double z) {
this.x -= x; this.x -= x;
this.y -= y; this.y -= y;
this.z -= z; this.z -= z;
return this; return this;
} }
public float getDistance(float x, float y, float z) { public double getDistance(double x, double y, double z) {
return (float) Math.sqrt(MathUtils.square(x - getX()) + return Math.sqrt(MathUtils.square(x - getX()) +
MathUtils.square(y - getY()) + MathUtils.square(y - getY()) +
MathUtils.square(z - getZ())); MathUtils.square(z - getZ()));
} }
@ -89,7 +92,7 @@ public class Position implements PublicCloneable<Position> {
* @param position the second position * @param position the second position
* @return the distance between {@code this} and {@code position} * @return the distance between {@code this} and {@code position}
*/ */
public float getDistance(@NotNull Position position) { public double getDistance(@NotNull Position position) {
return getDistance(position.getX(), position.getY(), position.getZ()); return getDistance(position.getX(), position.getY(), position.getZ());
} }
@ -99,7 +102,7 @@ public class Position implements PublicCloneable<Position> {
* @param position the second position * @param position the second position
* @return the squared distance between {@code this} and {@code position} * @return the squared distance between {@code this} and {@code position}
*/ */
public float getDistanceSquared(@NotNull Position position) { public double getDistanceSquared(@NotNull Position position) {
return MathUtils.square(getX() - position.getX()) + return MathUtils.square(getX() - position.getX()) +
MathUtils.square(getY() - position.getY()) + MathUtils.square(getY() - position.getY()) +
MathUtils.square(getZ() - position.getZ()); MathUtils.square(getZ() - position.getZ());
@ -123,8 +126,8 @@ public class Position implements PublicCloneable<Position> {
final double xz = Math.cos(Math.toRadians(rotY)); final double xz = Math.cos(Math.toRadians(rotY));
vector.setX((float) (-xz * Math.sin(Math.toRadians(rotX)))); vector.setX((-xz * Math.sin(Math.toRadians(rotX))));
vector.setZ((float) (xz * Math.cos(Math.toRadians(rotX)))); vector.setZ((xz * Math.cos(Math.toRadians(rotX))));
return vector; return vector;
} }
@ -144,8 +147,8 @@ public class Position implements PublicCloneable<Position> {
* z = Adj * z = Adj
*/ */
final double _2PI = 2 * Math.PI; final double _2PI = 2 * Math.PI;
final float x = vector.getX(); final double x = vector.getX();
final float z = vector.getZ(); final double z = vector.getZ();
if (x == 0 && z == 0) { if (x == 0 && z == 0) {
pitch = vector.getY() > 0 ? -90 : 90; pitch = vector.getY() > 0 ? -90 : 90;
@ -155,9 +158,9 @@ public class Position implements PublicCloneable<Position> {
final double theta = Math.atan2(-x, z); final double theta = Math.atan2(-x, z);
yaw = (float) Math.toDegrees((theta + _2PI) % _2PI); yaw = (float) Math.toDegrees((theta + _2PI) % _2PI);
final float x2 = MathUtils.square(x); final double x2 = MathUtils.square(x);
final float z2 = MathUtils.square(z); final double z2 = MathUtils.square(z);
final float xz = (float) Math.sqrt(x2 + z2); final double xz = Math.sqrt(x2 + z2);
pitch = (float) Math.toDegrees(Math.atan(-vector.getY() / xz)); pitch = (float) Math.toDegrees(Math.atan(-vector.getY() / xz));
return this; return this;
@ -228,11 +231,11 @@ public class Position implements PublicCloneable<Position> {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
Position position = (Position) o; Position position = (Position) o;
return Float.compare(position.x, x) == 0 && return Double.compare(position.x, x) == 0 &&
Float.compare(position.y, y) == 0 && Double.compare(position.y, y) == 0 &&
Float.compare(position.z, z) == 0 && Double.compare(position.z, z) == 0 &&
Float.compare(position.yaw, yaw) == 0 && Double.compare(position.yaw, yaw) == 0 &&
Float.compare(position.pitch, pitch) == 0; Double.compare(position.pitch, pitch) == 0;
} }
/** /**
@ -242,9 +245,9 @@ public class Position implements PublicCloneable<Position> {
* @return true if the two positions are similar * @return true if the two positions are similar
*/ */
public boolean isSimilar(@NotNull Position position) { public boolean isSimilar(@NotNull Position position) {
return Float.compare(position.x, x) == 0 && return Double.compare(position.x, x) == 0 &&
Float.compare(position.y, y) == 0 && Double.compare(position.y, y) == 0 &&
Float.compare(position.z, z) == 0; Double.compare(position.z, z) == 0;
} }
/** /**
@ -284,7 +287,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @return the position X * @return the position X
*/ */
public float getX() { public double getX() {
return x; return x;
} }
@ -293,7 +296,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @param x the new position X * @param x the new position X
*/ */
public void setX(float x) { public void setX(double x) {
this.x = x; this.x = x;
} }
@ -302,7 +305,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @return the position Y * @return the position Y
*/ */
public float getY() { public double getY() {
return y; return y;
} }
@ -311,7 +314,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @param y the new position Y * @param y the new position Y
*/ */
public void setY(float y) { public void setY(double y) {
this.y = y; this.y = y;
} }
@ -320,7 +323,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @return the position Z * @return the position Z
*/ */
public float getZ() { public double getZ() {
return z; return z;
} }
@ -329,7 +332,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @param z the new position Z * @param z the new position Z
*/ */
public void setZ(float z) { public void setZ(double z) {
this.z = z; this.z = z;
} }
@ -374,6 +377,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @return the converted {@link BlockPosition} * @return the converted {@link BlockPosition}
*/ */
@NotNull
public BlockPosition toBlockPosition() { public BlockPosition toBlockPosition() {
return new BlockPosition(x, y, z); return new BlockPosition(x, y, z);
} }
@ -383,6 +387,7 @@ public class Position implements PublicCloneable<Position> {
* *
* @return the converted {@link Vector} * @return the converted {@link Vector}
*/ */
@NotNull
public Vector toVector() { public Vector toVector() {
return new Vector(x, y, z); return new Vector(x, y, z);
} }

View File

@ -1,5 +1,6 @@
package net.minestom.server.utils; package net.minestom.server.utils;
import com.google.common.primitives.Doubles;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.utils.clone.PublicCloneable; import net.minestom.server.utils.clone.PublicCloneable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -8,7 +9,7 @@ public class Vector implements PublicCloneable<Vector> {
private static final double epsilon = 0.000001; private static final double epsilon = 0.000001;
protected float x, y, z; protected double x, y, z;
public Vector() { public Vector() {
this.x = 0; this.x = 0;
@ -16,7 +17,7 @@ public class Vector implements PublicCloneable<Vector> {
this.z = 0; this.z = 0;
} }
public Vector(float x, float y, float z) { public Vector(double x, double y, double z) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
@ -31,7 +32,7 @@ public class Vector implements PublicCloneable<Vector> {
} }
@NotNull @NotNull
public Vector add(float x, float y, float z) { public Vector add(double x, double y, double z) {
this.x += x; this.x += x;
this.y += y; this.y += y;
this.z += z; this.z += z;
@ -53,7 +54,7 @@ public class Vector implements PublicCloneable<Vector> {
} }
@NotNull @NotNull
public Vector subtract(float x, float y, float z) { public Vector subtract(double x, double y, double z) {
this.x -= x; this.x -= x;
this.y -= y; this.y -= y;
this.z -= z; this.z -= z;
@ -126,6 +127,15 @@ public class Vector implements PublicCloneable<Vector> {
return Math.sqrt(MathUtils.square(x) + MathUtils.square(y) + MathUtils.square(z)); return Math.sqrt(MathUtils.square(x) + MathUtils.square(y) + MathUtils.square(z));
} }
/**
* Gets the magnitude of the vector squared.
*
* @return the magnitude
*/
public double lengthSquared() {
return MathUtils.square(x) + MathUtils.square(y) + MathUtils.square(z);
}
/** /**
* Gets the distance between this vector and another. The value of this * Gets the distance between this vector and another. The value of this
* method is not cached and uses a costly square-root function, so do not * method is not cached and uses a costly square-root function, so do not
@ -150,6 +160,18 @@ public class Vector implements PublicCloneable<Vector> {
return MathUtils.square(x - o.x) + MathUtils.square(y - o.y) + MathUtils.square(z - o.z); return MathUtils.square(x - o.x) + MathUtils.square(y - o.y) + MathUtils.square(z - o.z);
} }
/**
* Gets the angle between this vector and another in radians.
*
* @param other The other vector
* @return angle in radians
*/
public float angle(@NotNull Vector other) {
double dot = Doubles.constrainToRange(dot(other) / (length() * other.length()), -1.0, 1.0);
return (float) Math.acos(dot);
}
/** /**
* Performs scalar multiplication, multiplying all components with a * Performs scalar multiplication, multiplying all components with a
* scalar. * scalar.
@ -195,6 +217,57 @@ public class Vector implements PublicCloneable<Vector> {
return this; return this;
} }
/**
* Calculates the dot product of this vector with another. The dot product
* is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar.
*
* @param other The other vector
* @return dot product
*/
public double dot(@NotNull Vector other) {
return x * other.x + y * other.y + z * other.z;
}
/**
* Calculates the cross product of this vector with another. The cross
* product is defined as:
* <ul>
* <li>x = y1 * z2 - y2 * z1
* <li>y = z1 * x2 - z2 * x1
* <li>z = x1 * y2 - x2 * y1
* </ul>
*
* @param o The other vector
* @return the same vector
*/
@NotNull
public Vector crossProduct(@NotNull Vector o) {
this.x = y * o.z - o.y * z;
this.y = z * o.x - o.z * x;
this.z = x * o.y - o.x * y;
return this;
}
/**
* Calculates the cross product of this vector with another without mutating
* the original. The cross product is defined as:
* <ul>
* <li>x = y1 * z2 - y2 * z1
* <li>y = z1 * x2 - z2 * x1
* <li>z = x1 * y2 - x2 * y1
* </ul>
*
* @param o The other vector
* @return a new vector
*/
@NotNull
public Vector getCrossProduct(@NotNull Vector o) {
final double x = this.y * o.z - o.y * this.z;
final double y = this.z * o.x - o.z * this.x;
final double z = this.x * o.y - o.x * this.y;
return new Vector(x, y, z);
}
/** /**
* Converts this vector to a unit vector (a vector with length of 1). * Converts this vector to a unit vector (a vector with length of 1).
* *
@ -223,6 +296,145 @@ public class Vector implements PublicCloneable<Vector> {
return this; return this;
} }
/**
* Returns if a vector is normalized
*
* @return whether the vector is normalised
*/
public boolean isNormalized() {
return Math.abs(this.lengthSquared() - 1) < getEpsilon();
}
/**
* Rotates the vector around the x axis.
* <p>
* This piece of math is based on the standard rotation matrix for vectors
* in three dimensional space. This matrix can be found here:
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
* Matrix</a>.
*
* @param angle the angle to rotate the vector about. This angle is passed
* in radians
* @return the same vector
*/
@NotNull
public Vector rotateAroundX(double angle) {
double angleCos = Math.cos(angle);
double angleSin = Math.sin(angle);
this.y = angleCos * getY() - angleSin * getZ();
this.z = angleSin * getY() + angleCos * getZ();
return this;
}
/**
* Rotates the vector around the y axis.
* <p>
* This piece of math is based on the standard rotation matrix for vectors
* in three dimensional space. This matrix can be found here:
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
* Matrix</a>.
*
* @param angle the angle to rotate the vector about. This angle is passed
* in radians
* @return the same vector
*/
@NotNull
public Vector rotateAroundY(double angle) {
double angleCos = Math.cos(angle);
double angleSin = Math.sin(angle);
this.x = angleCos * getX() + angleSin * getZ();
this.z = -angleSin * getX() + angleCos * getZ();
return this;
}
/**
* Rotates the vector around the z axis
* <p>
* This piece of math is based on the standard rotation matrix for vectors
* in three dimensional space. This matrix can be found here:
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
* Matrix</a>.
*
* @param angle the angle to rotate the vector about. This angle is passed
* in radians
* @return the same vector
*/
@NotNull
public Vector rotateAroundZ(double angle) {
double angleCos = Math.cos(angle);
double angleSin = Math.sin(angle);
this.x = angleCos * getX() - angleSin * getY();
this.y = angleSin * getX() + angleCos * getY();
return this;
}
/**
* Rotates the vector around a given arbitrary axis in 3 dimensional space.
*
* <p>
* Rotation will follow the general Right-Hand-Rule, which means rotation
* will be counterclockwise when the axis is pointing towards the observer.
* <p>
* This method will always make sure the provided axis is a unit vector, to
* not modify the length of the vector when rotating. If you are experienced
* with the scaling of a non-unit axis vector, you can use
* {@link Vector#rotateAroundNonUnitAxis(Vector, double)}.
*
* @param axis the axis to rotate the vector around. If the passed vector is
* not of length 1, it gets copied and normalized before using it for the
* rotation. Please use {@link Vector#normalize()} on the instance before
* passing it to this method
* @param angle the angle to rotate the vector around the axis
* @return the same vector
*/
@NotNull
public Vector rotateAroundAxis(@NotNull Vector axis, double angle) throws IllegalArgumentException {
return rotateAroundNonUnitAxis(axis.isNormalized() ? axis : axis.clone().normalize(), angle);
}
/**
* Rotates the vector around a given arbitrary axis in 3 dimensional space.
*
* <p>
* Rotation will follow the general Right-Hand-Rule, which means rotation
* will be counterclockwise when the axis is pointing towards the observer.
* <p>
* Note that the vector length will change accordingly to the axis vector
* length. If the provided axis is not a unit vector, the rotated vector
* will not have its previous length. The scaled length of the resulting
* vector will be related to the axis vector. If you are not perfectly sure
* about the scaling of the vector, use
* {@link Vector#rotateAroundAxis(Vector, double)}
*
* @param axis the axis to rotate the vector around.
* @param angle the angle to rotate the vector around the axis
* @return the same vector
*/
@NotNull
public Vector rotateAroundNonUnitAxis(@NotNull Vector axis, double angle) throws IllegalArgumentException {
double x = getX(), y = getY(), z = getZ();
double x2 = axis.getX(), y2 = axis.getY(), z2 = axis.getZ();
double cosTheta = Math.cos(angle);
double sinTheta = Math.sin(angle);
double dotProduct = this.dot(axis);
this.x = x2 * dotProduct * (1d - cosTheta)
+ x * cosTheta
+ (-z2 * y + y2 * z) * sinTheta;
this.y = y2 * dotProduct * (1d - cosTheta)
+ y * cosTheta
+ (z2 * x - x2 * z) * sinTheta;
this.z = z2 * dotProduct * (1d - cosTheta)
+ z * cosTheta
+ (-y2 * x + x2 * y) * sinTheta;
return this;
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof Vector)) { if (!(obj instanceof Vector)) {
@ -278,27 +490,27 @@ public class Vector implements PublicCloneable<Vector> {
} }
} }
public float getX() { public double getX() {
return x; return x;
} }
public void setX(float x) { public void setX(double x) {
this.x = x; this.x = x;
} }
public float getY() { public double getY() {
return y; return y;
} }
public void setY(float y) { public void setY(double y) {
this.y = y; this.y = y;
} }
public float getZ() { public double getZ() {
return z; return z;
} }
public void setZ(float z) { public void setZ(double z) {
this.z = z; this.z = z;
} }

View File

@ -1,8 +1,5 @@
package net.minestom.server.utils.block; package net.minestom.server.utils.block;
import java.util.Iterator;
import java.util.NoSuchElementException;
import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.LivingEntity;
import net.minestom.server.instance.block.BlockFace; import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.BlockPosition;
@ -10,6 +7,9 @@ import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector; import net.minestom.server.utils.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.NoSuchElementException;
/** /**
* This class performs ray tracing and iterates along blocks on a line * This class performs ray tracing and iterates along blocks on a line
*/ */
@ -48,9 +48,8 @@ public class BlockIterator implements Iterator<BlockPosition> {
* @param maxDistance This is the maximum distance in blocks for the * @param maxDistance This is the maximum distance in blocks for the
* trace. Setting this value above 140 may lead to problems with * trace. Setting this value above 140 may lead to problems with
* unloaded chunks. A value of 0 indicates no limit * unloaded chunks. A value of 0 indicates no limit
*
*/ */
public BlockIterator(@NotNull Vector start, @NotNull Vector direction, float yOffset, int maxDistance) { public BlockIterator(@NotNull Vector start, @NotNull Vector direction, double yOffset, int maxDistance) {
this.maxDistance = maxDistance; this.maxDistance = maxDistance;
Vector startClone = start.clone(); Vector startClone = start.clone();
@ -112,15 +111,15 @@ public class BlockIterator implements Iterator<BlockPosition> {
// trace line backwards to find intercept with plane perpendicular to the main axis // trace line backwards to find intercept with plane perpendicular to the main axis
double d = mainPosition / mainDirection; // how far to hit face behind double d = mainPosition / mainDirection; // how far to hit face behind
double secondd = secondPosition - secondDirection * d; double second = secondPosition - secondDirection * d;
double thirdd = thirdPosition - thirdDirection * d; double third = thirdPosition - thirdDirection * d;
// Guarantee that the ray will pass though the start block. // Guarantee that the ray will pass though the start block.
// It is possible that it would miss due to rounding // It is possible that it would miss due to rounding
// This should only move the ray by 1 grid position // This should only move the ray by 1 grid position
secondError = floor(secondd * gridSize); secondError = floor(second * gridSize);
secondStep = round(secondDirection / mainDirection * gridSize); secondStep = round(secondDirection / mainDirection * gridSize);
thirdError = floor(thirdd * gridSize); thirdError = floor(third * gridSize);
thirdStep = round(thirdDirection / mainDirection * gridSize); thirdStep = round(thirdDirection / mainDirection * gridSize);
if (secondError + secondStep <= 0) { if (secondError + secondStep <= 0) {
@ -229,7 +228,7 @@ public class BlockIterator implements Iterator<BlockPosition> {
* trace. Setting this value above 140 may lead to problems with * trace. Setting this value above 140 may lead to problems with
* unloaded chunks. A value of 0 indicates no limit * unloaded chunks. A value of 0 indicates no limit
*/ */
public BlockIterator(@NotNull Position pos, float yOffset, int maxDistance) { public BlockIterator(@NotNull Position pos, double yOffset, int maxDistance) {
this(pos.toVector(), pos.getDirection(), yOffset, maxDistance); this(pos.toVector(), pos.getDirection(), yOffset, maxDistance);
} }
@ -243,7 +242,7 @@ public class BlockIterator implements Iterator<BlockPosition> {
* by this value * by this value
*/ */
public BlockIterator(@NotNull Position pos, float yOffset) { public BlockIterator(@NotNull Position pos, double yOffset) {
this(pos.toVector(), pos.getDirection(), yOffset, 0); this(pos.toVector(), pos.getDirection(), yOffset, 0);
} }

View File

@ -76,7 +76,7 @@ public final class ChunkUtils {
* @param z instance Z coordinate * @param z instance Z coordinate
* @return true if the chunk is loaded, false otherwise * @return true if the chunk is loaded, false otherwise
*/ */
public static boolean isLoaded(@NotNull Instance instance, float x, float z) { public static boolean isLoaded(@NotNull Instance instance, double x, double z) {
final int chunkX = getChunkCoordinate((int) x); final int chunkX = getChunkCoordinate((int) x);
final int chunkZ = getChunkCoordinate((int) z); final int chunkZ = getChunkCoordinate((int) z);

View File

@ -270,12 +270,12 @@ public class EntityFinder {
if (targetSelector == TargetSelector.NEAREST_PLAYER) { if (targetSelector == TargetSelector.NEAREST_PLAYER) {
Entity entity = null; Entity entity = null;
float closestDistance = Float.MAX_VALUE; double closestDistance = Double.MAX_VALUE;
Collection<Player> instancePlayers = instance != null ? Collection<Player> instancePlayers = instance != null ?
instance.getPlayers() : MinecraftServer.getConnectionManager().getOnlinePlayers(); instance.getPlayers() : MinecraftServer.getConnectionManager().getOnlinePlayers();
for (Player player : instancePlayers) { for (Player player : instancePlayers) {
final float distance = player.getPosition().getDistance(startPosition); final double distance = player.getPosition().getDistance(startPosition);
if (distance < closestDistance) { if (distance < closestDistance) {
entity = player; entity = player;
closestDistance = distance; closestDistance = distance;

View File

@ -23,9 +23,9 @@ public class RelativeVec extends RelativeLocation<Vector> {
} }
final Position entityPosition = entity.getPosition(); final Position entityPosition = entity.getPosition();
final float x = location.getX() + (relativeX ? entityPosition.getX() : 0); final double x = location.getX() + (relativeX ? entityPosition.getX() : 0);
final float y = location.getY() + (relativeY ? entityPosition.getY() : 0); final double y = location.getY() + (relativeY ? entityPosition.getY() : 0);
final float z = location.getZ() + (relativeZ ? entityPosition.getZ() : 0); final double z = location.getZ() + (relativeZ ? entityPosition.getZ() : 0);
return new Vector(x, y, z); return new Vector(x, y, z);
} }

View File

@ -5,8 +5,8 @@ import org.jetbrains.annotations.NotNull;
public final class PositionUtils { public final class PositionUtils {
public static void lookAlong(@NotNull Position position, float dx, float dy, float dz) { public static void lookAlong(@NotNull Position position, double dx, double dy, double dz) {
final float horizontalAngle = (float) Math.atan2(dz, dx); final double horizontalAngle = Math.atan2(dz, dx);
final float yaw = (float) (horizontalAngle * (180.0 / Math.PI)) - 90; final float yaw = (float) (horizontalAngle * (180.0 / Math.PI)) - 90;
final float pitch = (float) Math.atan2(dy, Math.max(Math.abs(dx), Math.abs(dz))); final float pitch = (float) Math.atan2(dy, Math.max(Math.abs(dx), Math.abs(dz)));