mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-03 23:17:48 +01:00
Added WorldBorder#isInside + physics now support world border
This commit is contained in:
parent
224a8a3b86
commit
ef261c1792
@ -15,7 +15,8 @@ public class CollisionUtils {
|
||||
|
||||
/**
|
||||
* Moves an entity with physics applied (ie checking against blocks)
|
||||
* @param entity the entity to move
|
||||
*
|
||||
* @param entity the entity to move
|
||||
* @param positionOut the Position object in which the new position will be saved
|
||||
* @param velocityOut the Vector object in which the new velocity will be saved
|
||||
* @return whether this entity is on the ground
|
||||
@ -29,7 +30,7 @@ public class CollisionUtils {
|
||||
boolean yCollision = stepAxis(instance, currentPosition.toVector(), Y_AXIS, deltaPosition.getY(),
|
||||
intermediaryPosition,
|
||||
deltaPosition.getY() > 0 ? boundingBox.getTopFace() : boundingBox.getBottomFace()
|
||||
);
|
||||
);
|
||||
|
||||
boolean xCollision = stepAxis(instance, intermediaryPosition, X_AXIS, deltaPosition.getX(),
|
||||
intermediaryPosition,
|
||||
@ -61,12 +62,13 @@ public class CollisionUtils {
|
||||
/**
|
||||
* Steps on a single axis. Checks against collisions for each point of 'corners'. This method assumes that startPosition is valid.
|
||||
* Immediately return false if corners is of length 0.
|
||||
* @param instance instance to check blocks from
|
||||
*
|
||||
* @param instance instance to check blocks from
|
||||
* @param startPosition starting position for stepping, can be intermediary position from last step
|
||||
* @param axis step direction. Works best if unit vector and aligned to an axis
|
||||
* @param stepAmount how much to step in the direction (in blocks)
|
||||
* @param positionOut the vector in which to store the new position
|
||||
* @param corners the corners to check against
|
||||
* @param axis step direction. Works best if unit vector and aligned to an axis
|
||||
* @param stepAmount how much to step in the direction (in blocks)
|
||||
* @param positionOut the vector in which to store the new position
|
||||
* @param corners the corners to check against
|
||||
* @return true iif a collision has been found
|
||||
*/
|
||||
private static boolean stepAxis(Instance instance, Vector startPosition, Vector axis, float stepAmount, Vector positionOut, Vector... corners) {
|
||||
@ -83,21 +85,21 @@ public class CollisionUtils {
|
||||
}
|
||||
|
||||
float sign = Math.signum(stepAmount);
|
||||
int blockLength = (int)stepAmount;
|
||||
float remainingLength = stepAmount-blockLength;
|
||||
int blockLength = (int) stepAmount;
|
||||
float remainingLength = stepAmount - blockLength;
|
||||
// used to determine if 'remainingLength' should be used
|
||||
boolean collisionFound = false;
|
||||
for (int i = 0; i < Math.abs(blockLength); i++) {
|
||||
if (!stepOnce(instance, axis, sign, cornersCopy, cornerPositions)) {
|
||||
collisionFound = true;
|
||||
}
|
||||
if(collisionFound) {
|
||||
if (collisionFound) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add remainingLength
|
||||
if(!collisionFound) {
|
||||
if (!collisionFound) {
|
||||
Vector direction = new Vector();
|
||||
direction.copy(axis);
|
||||
collisionFound |= !stepOnce(instance, direction, remainingLength, cornersCopy, cornerPositions);
|
||||
@ -113,15 +115,16 @@ public class CollisionUtils {
|
||||
}
|
||||
|
||||
positionOut.copy(startPosition);
|
||||
positionOut.add(smallestDisplacement*axis.getX()*sign, smallestDisplacement*axis.getY()*sign, smallestDisplacement*axis.getZ()*sign);
|
||||
positionOut.add(smallestDisplacement * axis.getX() * sign, smallestDisplacement * axis.getY() * sign, smallestDisplacement * axis.getZ() * sign);
|
||||
return collisionFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps once (by a length of 1 block) on the given axis. Returns false if this method encountered a collision
|
||||
* @param instance instance to get blocks from
|
||||
* @param axis the axis to move along
|
||||
* @param cornersCopy the corners of the bounding box to consider (mutable)
|
||||
*
|
||||
* @param instance instance to get blocks from
|
||||
* @param axis the axis to move along
|
||||
* @param cornersCopy the corners of the bounding box to consider (mutable)
|
||||
* @param cornerPositions the corners, converted to BlockPosition (mutable)
|
||||
* @return
|
||||
*/
|
||||
@ -130,7 +133,7 @@ public class CollisionUtils {
|
||||
for (int cornerIndex = 0; cornerIndex < cornersCopy.length; cornerIndex++) {
|
||||
Vector corner = cornersCopy[cornerIndex];
|
||||
BlockPosition blockPos = cornerPositions[cornerIndex];
|
||||
corner.add(axis.getX()*amount, axis.getY()*amount, axis.getZ()*amount);
|
||||
corner.add(axis.getX() * amount, axis.getY() * amount, axis.getZ() * amount);
|
||||
blockPos.setX((int) Math.floor(corner.getX()));
|
||||
blockPos.setY((int) Math.floor(corner.getY()));
|
||||
blockPos.setZ((int) Math.floor(corner.getZ()));
|
||||
@ -140,7 +143,7 @@ public class CollisionUtils {
|
||||
// TODO: block collision boxes
|
||||
// TODO: for the moment, always consider a full block
|
||||
if (block.isSolid()) {
|
||||
corner.subtract(axis.getX()*amount, axis.getY()*amount, axis.getZ()*amount);
|
||||
corner.subtract(axis.getX() * amount, axis.getY() * amount, axis.getZ() * amount);
|
||||
|
||||
if (Math.abs(axis.getX()) > 10e-16) {
|
||||
corner.setX(blockPos.getX() - axis.getX() * sign);
|
||||
|
@ -16,6 +16,7 @@ import net.minestom.server.event.entity.EntityVelocityEvent;
|
||||
import net.minestom.server.event.handler.EventHandler;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.WorldBorder;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
@ -289,8 +290,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
this.lastUpdate = time;
|
||||
|
||||
// Velocity
|
||||
boolean applyVelocity = (PlayerUtils.isNettyClient(this) && hasVelocity())
|
||||
|| !PlayerUtils.isNettyClient(this);
|
||||
final boolean applyVelocity = !PlayerUtils.isNettyClient(this) ||
|
||||
(PlayerUtils.isNettyClient(this) && hasVelocity());
|
||||
if (applyVelocity) {
|
||||
final float tps = MinecraftServer.TICK_PER_SECOND;
|
||||
float newX = position.getX() + velocity.getX() / tps;
|
||||
@ -299,11 +300,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
|
||||
Position newPosition = new Position(newX, newY, newZ);
|
||||
|
||||
//if (!PlayerUtils.isNettyClient(this) && !noGravity) { // players handle gravity by themselves
|
||||
if (!noGravity) {
|
||||
velocity.setY(velocity.getY() - gravityDragPerTick * tps);
|
||||
}
|
||||
// }
|
||||
|
||||
Vector newVelocityOut = new Vector();
|
||||
Vector deltaPos = new Vector(
|
||||
@ -313,7 +312,15 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
);
|
||||
onGround = CollisionUtils.handlePhysics(this, deltaPos, newPosition, newVelocityOut);
|
||||
|
||||
refreshPosition(newPosition);
|
||||
WorldBorder worldBorder = instance.getWorldBorder();
|
||||
if (worldBorder.isInside(newPosition)) {
|
||||
// Apply velocity + gravity
|
||||
refreshPosition(newPosition);
|
||||
} else {
|
||||
// Only apply Y velocity/gravity
|
||||
refreshPosition(position.getX(), newPosition.getY(), position.getZ());
|
||||
}
|
||||
|
||||
velocity.copy(newVelocityOut);
|
||||
velocity.multiply(tps);
|
||||
|
||||
|
@ -230,7 +230,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
// Additional hearts support
|
||||
if (this instanceof Player) {
|
||||
Player player = (Player) this;
|
||||
float additionalHearts = player.getAdditionalHearts();
|
||||
final float additionalHearts = player.getAdditionalHearts();
|
||||
if (additionalHearts > 0) {
|
||||
if (damage > additionalHearts) {
|
||||
damage -= additionalHearts;
|
||||
|
@ -127,7 +127,7 @@ public class Player extends LivingEntity {
|
||||
private PlayerVehicleInformation vehicleInformation = new PlayerVehicleInformation();
|
||||
|
||||
// Tick related
|
||||
private final PlayerTickEvent playerTickEvent = new PlayerTickEvent();
|
||||
private final PlayerTickEvent playerTickEvent = new PlayerTickEvent(this);
|
||||
|
||||
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
||||
super(EntityType.PLAYER);
|
||||
|
@ -1,6 +1,17 @@
|
||||
package net.minestom.server.event.player;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.Event;
|
||||
|
||||
public class PlayerTickEvent extends Event {
|
||||
|
||||
private Player player;
|
||||
|
||||
public PlayerTickEvent(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
package net.minestom.server.instance;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.play.WorldBorderPacket;
|
||||
import net.minestom.server.utils.Position;
|
||||
|
||||
public class WorldBorder {
|
||||
|
||||
private Instance instance;
|
||||
|
||||
private double centerX, centerZ;
|
||||
private float centerX, centerZ;
|
||||
|
||||
private volatile double currentDiameter;
|
||||
|
||||
@ -33,7 +35,7 @@ public class WorldBorder {
|
||||
|
||||
}
|
||||
|
||||
public void setCenter(double centerX, double centerZ) {
|
||||
public void setCenter(float centerX, float centerZ) {
|
||||
this.centerX = centerX;
|
||||
this.centerZ = centerZ;
|
||||
refreshCenter();
|
||||
@ -43,7 +45,7 @@ public class WorldBorder {
|
||||
return centerX;
|
||||
}
|
||||
|
||||
public void setCenterX(double centerX) {
|
||||
public void setCenterX(float centerX) {
|
||||
this.centerX = centerX;
|
||||
refreshCenter();
|
||||
}
|
||||
@ -52,7 +54,7 @@ public class WorldBorder {
|
||||
return centerZ;
|
||||
}
|
||||
|
||||
public void setCenterZ(double centerZ) {
|
||||
public void setCenterZ(float centerZ) {
|
||||
this.centerZ = centerZ;
|
||||
refreshCenter();
|
||||
}
|
||||
@ -134,6 +136,31 @@ public class WorldBorder {
|
||||
sendPacket(worldBorderPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to know if a position is located inside the world border or not
|
||||
*
|
||||
* @param position the position to check
|
||||
* @return true if {@code position} is inside the world border, false otherwise
|
||||
*/
|
||||
public boolean isInside(Position position) {
|
||||
final double radius = getDiameter() / 2d;
|
||||
final boolean checkX = position.getX() < getCenterX() + radius && position.getX() > getCenterX() - radius;
|
||||
if (!checkX)
|
||||
return false;
|
||||
final boolean checkZ = position.getZ() < getCenterZ() + radius && position.getZ() > getCenterZ() - radius;
|
||||
return checkZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to know if an entity is located inside the world border or not
|
||||
*
|
||||
* @param entity the entity to check
|
||||
* @return true if {@code entity} is inside the world border, false otherwise
|
||||
*/
|
||||
public boolean isInside(Entity entity) {
|
||||
return isInside(entity.getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to update in real-time the current diameter time
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user