diff --git a/src/main/java/net/pivipi/LoginHandler.java b/src/main/java/net/pivipi/LoginHandler.java index 915628a..3b01c71 100644 --- a/src/main/java/net/pivipi/LoginHandler.java +++ b/src/main/java/net/pivipi/LoginHandler.java @@ -12,6 +12,7 @@ import net.minestom.server.instance.Instance; import net.minestom.server.instance.Weather; import net.pivipi.ball.Ball; import net.pivipi.ball.BallKicker; +import net.pivipi.physics.aabb.AABBPlayer; import net.pivipi.world.Stadium; public class LoginHandler { @@ -36,7 +37,7 @@ public class LoginHandler { event.setHardcore(true); player.setRespawnPoint(new Pos(0, 67, 0)); - stadium.players.add(player); + stadium.players.add((AABBPlayer)player); } private void onQuit(PlayerDisconnectEvent event) { diff --git a/src/main/java/net/pivipi/Main.java b/src/main/java/net/pivipi/Main.java index 6a412a0..2500fd1 100644 --- a/src/main/java/net/pivipi/Main.java +++ b/src/main/java/net/pivipi/Main.java @@ -1,16 +1,25 @@ package net.pivipi; +import java.util.UUID; + +import org.jetbrains.annotations.NotNull; + import net.minestom.server.MinecraftServer; +import net.minestom.server.entity.Player; import net.minestom.server.event.GlobalEventHandler; import net.minestom.server.instance.InstanceContainer; import net.minestom.server.instance.InstanceManager; import net.minestom.server.instance.LightingChunk; import net.minestom.server.instance.Weather; +import net.minestom.server.network.ConnectionManager; +import net.minestom.server.network.PlayerProvider; +import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.registry.DynamicRegistry.Key; import net.minestom.server.timer.SchedulerManager; import net.minestom.server.timer.TaskSchedule; import net.minestom.server.world.DimensionType; +import net.pivipi.physics.aabb.AABBPlayer; import net.pivipi.world.FancyDimension; import net.pivipi.world.SoccerGenerator; import net.pivipi.world.WorldConstraints; @@ -20,7 +29,7 @@ public class Main { System.setProperty("minestom.tps", "100"); MinecraftServer minecraftServer = MinecraftServer.init(); - + ConnectionManager connectionManager = MinecraftServer.getConnectionManager(); InstanceManager instanceManager = MinecraftServer.getInstanceManager(); GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler(); @@ -36,6 +45,14 @@ public class Main { WorldConstraints worldConstraints = new WorldConstraints(); worldConstraints.setup(globalEventHandler); + + connectionManager.setPlayerProvider(new PlayerProvider() { + @Override + public @NotNull Player createPlayer(@NotNull UUID uuid, @NotNull String username, + @NotNull PlayerConnection connection) { + return new AABBPlayer(uuid, username, connection); + } + }); /* done */ diff --git a/src/main/java/net/pivipi/ball/Ball.java b/src/main/java/net/pivipi/ball/Ball.java index 6f5533a..e298aca 100644 --- a/src/main/java/net/pivipi/ball/Ball.java +++ b/src/main/java/net/pivipi/ball/Ball.java @@ -10,9 +10,10 @@ import net.minestom.server.event.player.PlayerEntityInteractEvent; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; import net.pivipi.physics.Physics; +import net.pivipi.physics.aabb.AABBEntity; import net.pivipi.world.Stadium; -public class Ball extends Entity { +public class Ball extends AABBEntity { private long lastTick; private Player holder; diff --git a/src/main/java/net/pivipi/ball/BallKicker.java b/src/main/java/net/pivipi/ball/BallKicker.java index c9da3c8..515e8b0 100644 --- a/src/main/java/net/pivipi/ball/BallKicker.java +++ b/src/main/java/net/pivipi/ball/BallKicker.java @@ -19,7 +19,7 @@ import net.minestom.server.instance.block.Block; import net.minestom.server.item.ItemStack; import net.minestom.server.network.packet.server.play.BlockActionPacket; import net.minestom.server.particle.Particle.Item; -import net.pivipi.physics.Collision; +import net.pivipi.physics.CollisionDetector; import net.pivipi.physics.CollisionData; import net.pivipi.world.Stadium; @@ -50,7 +50,7 @@ public class BallKicker { // TODO apply physics settings here Player player = event.getPlayer(); Pos deltaPos = new Pos(0, 0.3, 0); - boolean collides = Collision.collidesWithEntity(stadium.ball, player); + boolean collides = CollisionDetector.collidesWithEntity(stadium.ball, player); if (collides) { System.out.println(deltaPos); stadium.ball.addPos(deltaPos.asVec()); @@ -87,7 +87,7 @@ public class BallKicker { // TODO apply physics settings here Player player = event.getPlayer(); CollisionData collisionData = new CollisionData(); - Collision.pushOutside(player, stadium.ball, collisionData); + CollisionDetector.pushOutside(player, stadium.ball, collisionData); double distance = collisionData.distance.withY(0).distance(0, 0, 0); if (collisionData.distance.y() < verticalReach && distance < reach) { diff --git a/src/main/java/net/pivipi/physics/Collision.java b/src/main/java/net/pivipi/physics/CollisionDetector.java similarity index 57% rename from src/main/java/net/pivipi/physics/Collision.java rename to src/main/java/net/pivipi/physics/CollisionDetector.java index ca9b6d6..d0b4501 100644 --- a/src/main/java/net/pivipi/physics/Collision.java +++ b/src/main/java/net/pivipi/physics/CollisionDetector.java @@ -7,8 +7,10 @@ import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Player; +import net.minestom.server.instance.Instance; +import net.minestom.server.instance.block.Block; -public class Collision { +public class CollisionDetector { /** * * @param entity @@ -42,6 +44,29 @@ public class Collision { return new BoundingBox(10, 1, 10).intersectEntity(entity.getPosition().withY(groundY - 1).sub(5, 0, 5), entity); } + /** + * + * @param blockPos the block position + * @param blockBoundingBox the block bounding box get it with registry.shape + * @param pushed the pushed entity + * @return offset you must apply to push the entity outside, null if doesn't collide + */ + public static Vec pushOutsideBlock(Pos blockPos, BoundingBox blockBoundingBox, Entity pushed) { + return pushOutsideBlock(blockPos, blockBoundingBox, pushed, null); + } + + /** + * + * @param blockPos the block position + * @param blockBoundingBox the block bounding box get it with registry.shape + * @param pushed the pushed entity + * @param collisionData puts data in this object + * @return offset you must apply to push the entity outside, null if doesn't collide + */ + public static Vec pushOutsideBlock(Pos blockPos, BoundingBox blockBoundingBox, Entity pushed, CollisionData collisionData) { + return pushOutside(blockPos.add(0.5, 0, 0.5), blockBoundingBox, pushed.getPosition(), pushed.getBoundingBox(), collisionData); // TODO + } + /** * * @param pusher the entity that's pushing like a player @@ -60,7 +85,8 @@ public class Collision { * @return offset you must apply to push the entity outside, null if doesn't collide */ public static Vec pushOutside(Entity pusher, Entity pushed, CollisionData collisionData) { - double ballXSize = pushed.getBoundingBox().width(); + return pushOutside(pusher.getPosition(), pusher.getBoundingBox(), pushed.getPosition(), pushed.getBoundingBox(), collisionData); + /*double ballXSize = pushed.getBoundingBox().width(); double playerXSize = pusher.getBoundingBox().width(); double ballZSize = pushed.getBoundingBox().depth(); double playerZSize = pusher.getBoundingBox().depth(); @@ -103,6 +129,55 @@ public class Collision { } + if (diffX < 0 && diffZ < 0) + return diffX < diffZ ? newBallOffset.withX(0) : newBallOffset.withZ(0); + + return null;*/ + } + + private static Vec pushOutside(Pos pusherPos, BoundingBox pusherBox, Pos pushedPos, BoundingBox pushedBox, CollisionData collisionData) { + double ballXSize = pushedBox.width(); + double playerXSize = pusherBox.width(); + double ballZSize = pushedBox.depth(); + double playerZSize = pusherBox.depth(); + double ballHeight = pushedBox.height(); + double playerHeight = pusherBox.height(); + Pos ballCenterPos = pushedPos; + Pos playerCenterPos = pusherPos; + + Pos ballPos = ballCenterPos.sub(ballXSize / 2, 0, ballZSize / 2); // corner + Pos playerPos = playerCenterPos.sub(playerXSize / 2, 0, playerZSize / 2); + Vec ballDistance = ballCenterPos.sub(playerCenterPos).asVec(); // center distance + + if (collisionData != null) // TODO move this + collisionData.distance = ballDistance; + + if (ballDistance.y() > 0 && ballPos.y() > playerPos.y() + playerHeight) return null; // doesn't collide on y+ + else if (playerPos.y() > ballPos.y() + ballHeight) return null; // doesn't collide on y- + + Vec newBallOffset = new Vec(0); + double diffX = 0, diffZ = 0; + + if (ballDistance.x() > 0) { + diffX = ballPos.x() - (playerPos.x() + playerXSize); + if (diffX < 0) // collides on x+ + newBallOffset = newBallOffset.withX(-diffX); + } else { + diffX = playerPos.x() - (ballPos.x() + ballXSize); + if (diffX < 0) // collides on x- + newBallOffset = newBallOffset.withX(diffX); + } + + if (ballDistance.z() > 0) { + diffZ = ballPos.z() - (playerPos.z() + playerZSize); + if (diffZ < 0) // collides on z+ + newBallOffset = newBallOffset.withZ(-diffZ); + } else { + diffZ = playerPos.z() - (ballPos.z() + ballZSize); + if (diffZ < 0) // collides on z- + newBallOffset = newBallOffset.withZ(diffZ); + } + if (diffX < 0 && diffZ < 0) return diffX < diffZ ? newBallOffset.withX(0) : newBallOffset.withZ(0); diff --git a/src/main/java/net/pivipi/physics/Physics.java b/src/main/java/net/pivipi/physics/Physics.java index 2e517e7..95502b0 100644 --- a/src/main/java/net/pivipi/physics/Physics.java +++ b/src/main/java/net/pivipi/physics/Physics.java @@ -1,14 +1,22 @@ package net.pivipi.physics; +import java.util.ArrayList; +import java.util.List; import java.util.Set; +import net.minestom.server.collision.BoundingBox; import net.minestom.server.collision.VisibleSweepResult; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Player; +import net.minestom.server.instance.block.Block; import net.minestom.server.network.packet.server.play.ParticlePacket; import net.minestom.server.particle.Particle; +import net.pivipi.ball.Ball; +import net.pivipi.physics.aabb.AABB; +import net.pivipi.physics.aabb.AABBEntity; +import net.pivipi.physics.aabb.AABBPlayer; public class Physics { private final double gravity = 9.8; @@ -23,23 +31,32 @@ public class Physics { private final double jumpStrength = 20; private final double groundFriction = 0.5; private final double airFriction = 0.1; - private final int groundY = 64; + private final AABB groundAABB = new AABB(new Vec(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE), new Vec(Double.MAX_VALUE, 64, Double.MAX_VALUE)); private final double flame = 20; // flame starts at speed private final double flameFreq = 100; // ms per flame private final double flameIncrement = 0.5; // ms per flame decrement per speed unit private final float flameSpread = 0.2f; + private final Pos[] blocksNearby = new Pos[] { + new Pos(0, 0, 0), // bottom edge + new Pos(0, 1, 0), // top edge + new Pos(0.5, 0.5, 0), // x+ edge + new Pos(-0.5, 0.5, 0), // x- edge + new Pos(0, 0.5, 0.5), // z+ edge + new Pos(0, 0.5, -0.5), // z- edge + }; + private Vec velocity = new Vec(0, 0, 0); - private final Entity entity; + private final AABBEntity entity; private int p; - public Physics(Entity entity) { + public Physics(AABBEntity entity) { this.entity = entity; } - public void process(double delta, Set players) { + public void process(double delta, Set players) { velocity = applyPhysics(delta, players); entity.teleport(entity.getPosition().add(velocity.mul(delta))); @@ -58,40 +75,81 @@ public class Physics { } } - private Vec applyPhysics(double delta, Set players) { + private Vec applyPhysics(double delta, Set players) { velocity = velocity.sub(0, gravity * delta, 0).mul(1 - (airFriction * delta), 1, 1 - (airFriction * delta)); + AABB aabb = entity.getAabb().velocity(velocity.mul(delta)); - if (Collision.collidesWithGround(groundY, entity)) { - entity.teleport(entity.getPosition().withY(groundY)); + double groundToi = groundAABB.timeOfImpact(aabb); + //System.out.println(velocity.mul(delta)); + //System.out.println(aabb.getMin(false)); + if (groundToi < 1) { + if (groundToi > 0) + entity.move(velocity.mul(delta).mul(groundToi)); + else entity.teleport(entity.getPosition().withY(65)); velocity = velocity.mul(1 - (groundFriction * delta), -blockBounciness, 1 - (groundFriction * delta)); - } else { - for (Player player : players) { - boolean collides = Collision.collidesWithEntity(player, entity); - if (collides) { - handlePlayerTouch(player); - - break; - } - } + aabb.velocity(velocity); } + players.forEach(player -> { + Vec offset = aabb.resolve(player.getAabb()); + if (offset != null) { + entity.move(offset); + } + }); + return velocity; } - private void handlePlayerTouch(Player player) { + private void handleBlockTouch(Pos blockRelativePos, int edge) { + //Pos blockPos = entity.getPosition().sub(entity.getBoundingBox().width() / 2, 0, entity.getBoundingBox().height() / 2).add(blockRelativePos); + Pos blockPos = entity.getPosition().add(blockRelativePos);//.withX(x -> (int)(x - entity.getBoundingBox().width() / 2)).withZ(z -> (int)(z - entity.getBoundingBox().depth() / 2)).withY(y -> (int)(y)); + //Pos blockPos = ballEdgePos.withX(x -> (int)(x)).withY(y -> (int)(y)).withZ(z -> (int)(z)); + Block block = entity.getInstance().getBlock(blockPos); + if (block.equals(Block.AIR)) return; + CollisionData collisionData = new CollisionData(); - Vec offset = Collision.pushOutside(player, entity, collisionData); // TODO predict the collision + CollisionDetector.pushOutsideBlock(blockPos, new BoundingBox(1, 1, 1), entity, collisionData); + Vec offset = collisionData.distance; + + if (block != Block.AIR) { + //entity.teleport(entity.getPosition().add(collisionData.distance)); + switch (edge) { + case 0: + case 1: + System.out.println(edge); + offset = offset.mul(0, 1, 0);//.withY(y -> ballEdgePos.y() - blockPos.y()); + //velocity = velocity.mul(1, -blockBounciness, 1); + break; + case 2: + offset = offset.add(0.5, 0, 0); + case 3: + System.out.println(edge); + offset = offset.mul(1, 0, 0);//.withX(x -> ballEdgePos.x() - blockPos.x()); + //velocity = velocity.mul(-blockBounciness, 1, 1); + break; + case 4: + System.out.println("addin"); + offset = offset.add(0, 0, 0.5); + case 5: + System.out.println(edge); + offset = offset.mul(0, 0, 1);//.withZ(z -> ballEdgePos.z() - blockPos.z()); + //velocity = velocity.mul(1, 1, -blockBounciness); + break; + } + System.out.println(offset); + entity.teleport(entity.getPosition().add(offset)); + } + } + + private void handlePlayerTouch(Player player, Vec offset) { + Vec distance = entity.getPosition().sub(entity.getPosition()).asVec(); if (offset != null) { Pos movementPos = player.getPosition().sub(player.getPreviousPosition()); - boolean oppositeX = (collisionData.distance.x() > 0 ? velocity.x() < 0 : velocity.x() > 0); - boolean oppositeZ = (collisionData.distance.z() > 0 ? velocity.z() < 0 : velocity.z() > 0); - double headOffsetY = player.getBoundingBox().height() - collisionData.distance.y(); - - System.out.println(offset); - System.out.println(oppositeX); - System.out.println(velocity.x()); + boolean oppositeX = (distance.x() > 0 ? velocity.x() < 0 : velocity.x() > 0); + boolean oppositeZ = (distance.z() > 0 ? velocity.z() < 0 : velocity.z() > 0); + double headOffsetY = player.getBoundingBox().height() - distance.y(); if (headOffsetY < 0.6) { // landed on head, magic value head height if (movementPos.y() > 0) { @@ -101,18 +159,13 @@ public class Physics { } else velocity = velocity.mul(1, player.isSneaking() ? -playerSneakingHeadBounciness : -playerHeadBounciness, 1); entity.teleport(entity.getPosition().withY(y -> y + headOffsetY)); } else { - System.out.println("tping"); entity.teleport(entity.getPosition().add(offset.mul(1.1))); // magic value to make some space in case of desync double bodyBounciness = player.isSneaking() ? -playerSneakingBodyBounciness : -playerBodyBounciness; - System.out.println(velocity); - velocity = velocity .withX(x -> oppositeX ? x * bodyBounciness : x + movementPos.x() * playerCarryStrength) - .withY(y -> collisionData.distance.y() < 1.0 ? movementPos.y() * jumpStrength : y) // magic value legs + .withY(y -> distance.y() < 1.0 ? movementPos.y() * jumpStrength : y) // magic value legs .withZ(z -> oppositeZ ? z * bodyBounciness : z + movementPos.z() * playerCarryStrength); - - System.out.println(velocity); } } diff --git a/src/main/java/net/pivipi/physics/aabb/AABB.java b/src/main/java/net/pivipi/physics/aabb/AABB.java new file mode 100644 index 0000000..7693a07 --- /dev/null +++ b/src/main/java/net/pivipi/physics/aabb/AABB.java @@ -0,0 +1,154 @@ +package net.pivipi.physics.aabb; + +import net.kyori.adventure.bossbar.BossBar.Overlay; +import net.minestom.server.collision.BoundingBox; +import net.minestom.server.collision.SweepResult; +import net.minestom.server.collision.VisibleSweepResult; +import net.minestom.server.coordinate.Vec; +import net.pivipi.physics.CollisionData; + +public class AABB { + Vec min, max; + Vec velocity = Vec.ZERO; + + public AABB(Vec min, Vec max) { + this.min = min; + this.max = max; + } + + public Vec getMin(boolean swept) { + if (swept) min = min.min(min.add(velocity)); + return min; + } + + public Vec getMax(boolean swept) { + if (swept) max = max.min(max.add(velocity)); + return max; + } + + public Vec getVelocity() { + return velocity; + } + + public AABB velocity(Vec velocity) { + this.velocity = velocity; + return this; + } + + /** + * check if collides target + * @param aabb the target + * @param swept is target swept + * @return + */ + public boolean collides(AABB aabb, boolean swept) { + Vec bMin = aabb.getMin(swept); + Vec bMax = aabb.getMax(swept); + + return (min.x() <= bMax.x() && max.x() >= bMin.x() && + min.y() <= bMax.y() && max.y() >= bMin.y() && + min.z() <= bMax.z() && max.z() >= bMin.z()); + } + + /** + * time of impact with target + * @param moving another target (moving or not) + * @return percent of velocity moved, Double.NEGATIVE_INFINITY if already collides, Double.POSITIVE_INFINITY otherwise + */ + public double timeOfImpact(AABB moving) { + if (this.collides(moving, false)) return Double.NEGATIVE_INFINITY; + + SweepResult sweepResult = new SweepResult(1, 0, 0, 0, null, 0, 0, 0); + Vec bb = max.sub(min); + Vec bb2 = moving.max.sub(moving.min); + Vec relativeVelocity = moving.velocity.sub(velocity); + + boolean collides = new BoundingBox(bb.x(), bb.y(), bb.z()).intersectBoxSwept(moving.min, relativeVelocity, min, new BoundingBox(bb2.x(), bb2.y(), bb2.z()), sweepResult); + if (!collides) return Double.POSITIVE_INFINITY; + + return new VisibleSweepResult(sweepResult).res; + + /* Vec relativeVelocity = moving.velocity.sub(velocity); + double enterX = Double.NEGATIVE_INFINITY, exitX = Double.POSITIVE_INFINITY; + double enterY = Double.NEGATIVE_INFINITY, exitY = Double.POSITIVE_INFINITY; + double enterZ = Double.NEGATIVE_INFINITY, exitZ = Double.POSITIVE_INFINITY; + boolean overlap = true; + + if (relativeVelocity.x() != 0) { + enterX = (moving.min.x() - max.x()) / relativeVelocity.x(); + exitX = (moving.max.x() - min.x()) / relativeVelocity.x(); + } else { + overlap = overlap && !(max.x() < moving.min.x() || moving.max.x() < min.x()); + } + + if (relativeVelocity.y() != 0) { + enterY = (moving.min.y() - max.y()) / relativeVelocity.y(); + exitY = (moving.max.y() - min.y()) / relativeVelocity.y(); + } else { + overlap = overlap && !(max.y() < moving.min.y() || moving.max.y() < min.y()); + } + + if (relativeVelocity.z() != 0) { + enterZ = (moving.min.z() - max.z()) / relativeVelocity.z(); + exitZ = (moving.max.z() - min.z()) / relativeVelocity.z(); + } else { + overlap = overlap && !(max.z() < moving.min.z() || moving.max.z() < min.z()); + } + + //if (overlap) return Double.NEGATIVE_INFINITY; + + double entry = Math.max(Math.max(enterX, enterY), enterZ); + double exit = Math.min(Math.min(exitX, exitY), exitZ); + + return entry > exit ? Double.POSITIVE_INFINITY : entry; // TODO simplify*/ + } + + /** + * don't push myself inside + * @param aabb the object, it can be moving + * @return offset to move me by or null if no overlap + */ + public Vec resolveSwept(AABB aabb) { + double toi = timeOfImpact(aabb); + return toi < 0 || toi > 1 ? null : velocity.mul(toi); + } + + /** + * push myself outside + * @param aabb the static object + * @return offset to move me by or null if no overlap + */ + public Vec resolve(AABB aabb) { + Vec bMin = aabb.getMin(false); + Vec bMax = aabb.getMax(false); + Vec offset = Vec.ZERO; + + Vec overlap = new Vec( + Math.min(max.x(), bMax.x()) - Math.max(min.x(), bMin.x()), + Math.min(max.y(), bMax.y()) - Math.max(min.y(), bMin.y()), + Math.min(max.z(), bMax.z()) - Math.max(min.z(), bMin.z())); + + if (overlap.x() <= 0 || overlap.y() <= 0 || overlap.z() <= 0) + return null; + + if (overlap.x() < overlap.y() && overlap.x() < overlap.z()) { + if (min.x() < bMin.x()) + offset = offset.withX(x -> x - overlap.x()); + else + offset = offset.withX(x -> x + overlap.x()); + } else if (overlap.y() < overlap.x() && overlap.y() < overlap.z()) { + if (min.y() < bMin.y()) + offset = offset.withY(y -> y - overlap.y()); + else + offset = offset.withY(y -> y + overlap.y()); + } else { + if (min.z() < bMin.z()) + offset = offset.withZ(z -> z - overlap.z()); + else + offset = offset.withZ(z -> z + overlap.z()); + } + + return offset; + } + +} diff --git a/src/main/java/net/pivipi/physics/aabb/AABBEntity.java b/src/main/java/net/pivipi/physics/aabb/AABBEntity.java new file mode 100644 index 0000000..aee0d56 --- /dev/null +++ b/src/main/java/net/pivipi/physics/aabb/AABBEntity.java @@ -0,0 +1,29 @@ +package net.pivipi.physics.aabb; + +import org.jetbrains.annotations.NotNull; + +import net.minestom.server.collision.BoundingBox; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; + +public class AABBEntity extends Entity { + protected AABB aabb = new AABB(Vec.ZERO, Vec.ZERO); + + public AABBEntity(@NotNull EntityType entityType) { + super(entityType); + // TODO Auto-generated constructor stub + } + + public AABB getAabb() { + aabb.min = this.getPosition().sub(this.getBoundingBox().width() / 2, 0, this.getBoundingBox().depth() / 2).asVec(); + aabb.max = this.getPosition().add(this.getBoundingBox().width() / 2, this.getBoundingBox().height(), this.getBoundingBox().depth() / 2).asVec(); + aabb.velocity = this.getVelocity(); + return aabb; + } + + public void move(Vec offset) { + this.teleport(this.getPosition().add(offset)); + } +} diff --git a/src/main/java/net/pivipi/physics/aabb/AABBPlayer.java b/src/main/java/net/pivipi/physics/aabb/AABBPlayer.java new file mode 100644 index 0000000..16fb89b --- /dev/null +++ b/src/main/java/net/pivipi/physics/aabb/AABBPlayer.java @@ -0,0 +1,44 @@ +package net.pivipi.physics.aabb; + +import java.util.UUID; + +import org.jetbrains.annotations.NotNull; + +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.Player; +import net.minestom.server.network.PlayerProvider; +import net.minestom.server.network.player.PlayerConnection; + +public class AABBPlayer extends Player { + protected AABB aabb = new AABB(Vec.ZERO, Vec.ZERO); + + private Pos lastPosition = Pos.ZERO; + private long lastUpdate; + private double delta; + + private Pos movement; + + public AABBPlayer(@NotNull UUID uuid, @NotNull String username, @NotNull PlayerConnection playerConnection) { + super(uuid, username, playerConnection); + // TODO Auto-generated constructor stub + } + + public AABB getAabb() { + aabb.min = this.getPosition().sub(this.getBoundingBox().width() / 2, 0, this.getBoundingBox().depth() / 2).asVec(); + aabb.max = this.getPosition().add(this.getBoundingBox().width() / 2, this.getBoundingBox().height(), this.getBoundingBox().depth() / 2).asVec(); + aabb.velocity = this.getVelocity().mul(delta).add(movement); + return aabb; + } + + @Override + public void update(long time) { + super.update(time); + + this.movement = this.getPosition().sub(lastPosition); + this.lastPosition = this.getPosition(); + + this.delta = (time - lastUpdate) / 1000.0; + this.lastUpdate = time; + } +} diff --git a/src/main/java/net/pivipi/physics/aabb/BlockAABB.java b/src/main/java/net/pivipi/physics/aabb/BlockAABB.java new file mode 100644 index 0000000..0b409d6 --- /dev/null +++ b/src/main/java/net/pivipi/physics/aabb/BlockAABB.java @@ -0,0 +1,11 @@ +package net.pivipi.physics.aabb; + +import net.minestom.server.coordinate.Vec; + +public class BlockAABB extends AABB { + + public BlockAABB(Vec pos) { + super(pos, pos.add(1)); + } + +} diff --git a/src/main/java/net/pivipi/world/Stadium.java b/src/main/java/net/pivipi/world/Stadium.java index 0e13d32..d081ec7 100644 --- a/src/main/java/net/pivipi/world/Stadium.java +++ b/src/main/java/net/pivipi/world/Stadium.java @@ -5,8 +5,9 @@ import java.util.Set; import net.minestom.server.entity.Player; import net.pivipi.ball.Ball; +import net.pivipi.physics.aabb.AABBPlayer; public class Stadium { - public final Set players = new HashSet(); + public final Set players = new HashSet(); public Ball ball; }