This commit is contained in:
Minecon724 2024-07-17 19:07:42 +02:00
parent a0a4619755
commit 7cdff81b36
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
7 changed files with 131 additions and 27 deletions

View file

@ -1,15 +1,15 @@
package net.pivipi.ball; package net.pivipi.ball;
import net.minestom.server.coordinate.Vec; import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType; import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.entity.metadata.other.FallingBlockMeta; import net.minestom.server.entity.metadata.other.FallingBlockMeta;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.pivipi.entity.PhysicsEntity;
import net.pivipi.game.Stadium; import net.pivipi.game.Stadium;
import net.pivipi.physics.Physics; import net.pivipi.physics.Physics;
public class Ball extends Entity { public class Ball extends PhysicsEntity {
private long lastTick; private long lastTick;
private Player holder; private Player holder;

View file

@ -77,8 +77,7 @@ public class BallKicker { // TODO apply physics settings here
private void onSwing(PlayerHandAnimationEvent event) { private void onSwing(PlayerHandAnimationEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
CollisionData collisionData = new CollisionData(); CollisionData collisionData = Collision.pushOutside(player, stadium.ball, false);
Collision.pushOutside(player, stadium.ball, false, collisionData);
double distance = collisionData.distance.withY(0).distance(0, 0, 0); double distance = collisionData.distance.withY(0).distance(0, 0, 0);
if (collisionData.distance.y() < verticalReach && distance < reach) { if (collisionData.distance.y() < verticalReach && distance < reach) {

View file

@ -0,0 +1,54 @@
package net.pivipi.entity;
import net.minestom.server.coordinate.Vec;
public class AABB {
Vec min, max;
Vec velocity;
public AABB(Vec min, Vec max, Vec velocity) {
this.min = min;
this.max = max;
this.velocity = velocity;
}
/**
* gets the position of the lower corner
* @return
*/
public Vec getMin() {
return min;
}
/**
* gets the position of the lower corner + velocity
* @return
*/
public Vec getMinSwept() {
return min.add(velocity);
}
/**
* gets the position of the upper corner
* @return
*/
public Vec getMax() {
return min;
}
/**
* gets the position of the upper corner + velocity
* @return
*/
public Vec getMaxSwept() {
return max.add(velocity);
}
/**
* gets the velocity that is blocks per second
* @return
*/
public Vec getVelocity() {
return velocity;
}
}

View file

@ -0,0 +1,21 @@
package net.pivipi.entity;
import org.jetbrains.annotations.NotNull;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
public class PhysicsEntity extends Entity {
public PhysicsEntity(@NotNull EntityType entityType) {
super(entityType);
// TODO Auto-generated constructor stub
}
public AABB getAabb() {
Vec min = this.getPosition().sub(this.getBoundingBox().width() / 2, 0, this.getBoundingBox().depth() / 2).asVec();
Vec max = this.getPosition().add(this.getBoundingBox().width() / 2, this.getBoundingBox().height(), this.getBoundingBox().depth() / 2).asVec();
return new AABB(min, max, this.velocity);
}
}

View file

@ -8,6 +8,14 @@ import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
public class Collision { public class Collision {
/**
*
* @param pos static object's pos
* @param boundingBox static object's bounding box
* @param moving moving entity
* @param movement moving entity movement
* @return
*/
private static CollisionData willCollide(Pos pos, BoundingBox boundingBox, Entity moving, Vec movement) { private static CollisionData willCollide(Pos pos, BoundingBox boundingBox, Entity moving, Vec movement) {
SweepResult sweepResult = new SweepResult(1, 0, 0, 0, null, 0, 0, 0); SweepResult sweepResult = new SweepResult(1, 0, 0, 0, null, 0, 0, 0);
boolean collides = boundingBox.intersectBoxSwept(moving.getPosition(), movement, pos, moving.getBoundingBox(), sweepResult); boolean collides = boundingBox.intersectBoxSwept(moving.getPosition(), movement, pos, moving.getBoundingBox(), sweepResult);
@ -43,6 +51,10 @@ public class Collision {
return willCollide(new Pos(Double.MIN_VALUE, 0, Double.MIN_VALUE), new BoundingBox(Double.MAX_VALUE, 64, Double.MAX_VALUE), moving, movement); return willCollide(new Pos(Double.MIN_VALUE, 0, Double.MIN_VALUE), new BoundingBox(Double.MAX_VALUE, 64, Double.MAX_VALUE), moving, movement);
} }
public static CollisionData willCollideWithBlock(Pos blockPos, Entity moving, Vec movement) {
return willCollide(blockPos, new BoundingBox(1, 1, 1), moving, movement);
}
public static boolean collidesWithEntity(Entity entity1, Entity entity2) { public static boolean collidesWithEntity(Entity entity1, Entity entity2) {
return entity1.getBoundingBox().intersectEntity(entity1.getPosition(), entity2); return entity1.getBoundingBox().intersectEntity(entity1.getPosition(), entity2);
} }
@ -61,8 +73,8 @@ public class Collision {
* @param pushed the entity that's being pushed like a ball * @param pushed the entity that's being pushed like a ball
* @return offset you must apply to push the entity outside, null if doesn't collide * @return offset you must apply to push the entity outside, null if doesn't collide
*/ */
public static Vec pushOutside(Entity pusher, Entity pushed, boolean y, CollisionData collisionData) { public static CollisionData pushOutside(Entity pusher, Entity pushed, boolean y) {
return pushOutside(pusher.getBoundingBox(), pusher.getPosition(), pushed, y, collisionData); return pushOutside(pusher.getBoundingBox(), pusher.getPosition(), pushed, y);
} }
/** /**
@ -71,8 +83,8 @@ public class Collision {
* @param pushed the entity that's being pushed like a ball * @param pushed the entity that's being pushed like a ball
* @return offset you must apply to push the entity outside, null if doesn't collide * @return offset you must apply to push the entity outside, null if doesn't collide
*/ */
public static Vec pushOutside(Pos blockPos, Entity pushed, boolean y, CollisionData collisionData) { public static CollisionData pushOutside(Pos blockPos, Entity pushed, boolean y) {
return pushOutside(new BoundingBox(1, 1, 1), blockPos, pushed, y, collisionData); return pushOutside(new BoundingBox(1, 1, 1), blockPos, pushed, y);
} }
@ -130,10 +142,9 @@ public class Collision {
* @param pusherBox the entity that's pushing like a player or a block, its bounding box * @param pusherBox the entity that's pushing like a player or a block, its bounding box
* @param pusherPos the position, bottom center * @param pusherPos the position, bottom center
* @param pushed the entity that's being pushed like a ball * @param pushed the entity that's being pushed like a ball
* @param collisionData puts data in this object * @return collision data
* @return offset you must apply to push the entity outside, null if doesn't collide
*/ */
private static Vec pushOutside(BoundingBox pusherBox, Pos pusherPos, Entity pushed, boolean y, CollisionData collisionData) { private static CollisionData pushOutside(BoundingBox pusherBox, Pos pusherPos, Entity pushed, boolean y) {
double ballXSize = pushed.getBoundingBox().width(); double ballXSize = pushed.getBoundingBox().width();
double playerXSize = pusherBox.width(); double playerXSize = pusherBox.width();
double ballZSize = pushed.getBoundingBox().depth(); double ballZSize = pushed.getBoundingBox().depth();
@ -148,9 +159,8 @@ public class Collision {
Pos playerPos = playerCenterPos.sub(playerXSize / 2, 0, playerZSize / 2); Pos playerPos = playerCenterPos.sub(playerXSize / 2, 0, playerZSize / 2);
Vec ballDistance = ballCenterPos.sub(playerCenterPos).asVec(); Vec ballDistance = ballCenterPos.sub(playerCenterPos).asVec();
if (collisionData != null) { CollisionData collisionData = new CollisionData();
collisionData.distance = ballDistance; collisionData.distance = ballDistance;
}
double diffX = ballDistance.x() > 0 double diffX = ballDistance.x() > 0
? ballPos.x() - (playerPos.x() + playerXSize) ? ballPos.x() - (playerPos.x() + playerXSize)
@ -180,12 +190,8 @@ public class Collision {
offset = newBallOffset.mul(1, 0, 0); offset = newBallOffset.mul(1, 0, 0);
} }
if (collisionData != null) {
collisionData.distance = ballDistance;
collisionData.offset = offset; collisionData.offset = offset;
} return collisionData;
return offset;
} }
} }

View file

@ -29,7 +29,7 @@ public class CollisionData {
public Vec collidedPosition; public Vec collidedPosition;
/** /**
* I don't know what this is but it looks useful (only when swept) * the direction and speed where an object should bounce (only when swept)
*/ */
public Vec normal; public Vec normal;

View file

@ -5,10 +5,11 @@ import java.util.Set;
import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec; import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.server.play.ParticlePacket; import net.minestom.server.network.packet.server.play.ParticlePacket;
import net.minestom.server.particle.Particle; import net.minestom.server.particle.Particle;
import net.pivipi.entity.AABB;
import net.pivipi.entity.PhysicsEntity;
import net.pivipi.game.PhysicsSettings; import net.pivipi.game.PhysicsSettings;
public class Physics { public class Physics {
@ -23,10 +24,10 @@ public class Physics {
private Vec velocity = new Vec(0, 0, 0); private Vec velocity = new Vec(0, 0, 0);
private final Entity entity; private final PhysicsEntity entity;
private int p; private int p;
public Physics(Entity entity) { public Physics(PhysicsEntity entity) {
this.entity = entity; this.entity = entity;
} }
@ -58,25 +59,48 @@ public class Physics {
velocity = velocity.mul(1 - (settings.groundFriction * delta), -settings.blockBounciness, 1 - (settings.groundFriction * delta)); velocity = velocity.mul(1 - (settings.groundFriction * delta), -settings.blockBounciness, 1 - (settings.groundFriction * delta));
} else { } else {
for (Player player : players) { for (Player player : players) {
CollisionData collisionData = new CollisionData(); CollisionData collisionData = Collision.pushOutside(player, entity, false); // TODO predict the collision
Vec offset = Collision.pushOutside(player, entity, false, collisionData); // TODO predict the collision
if (offset != null) { if (collisionData.offset != null) {
collisionData.entity = player; collisionData.entity = player;
collisions.add(collisionData); collisions.add(collisionData);
} }
} }
AABB aabb = entity.getAabb();
int minX = aabb.getMin().blockX();
int minY = aabb.getMin().blockY();
int minZ = aabb.getMin().blockZ();
int maxX = aabb.getMax().blockX();
int maxY = aabb.getMax().blockY();
int maxZ = aabb.getMax().blockZ();
for (int x=minX; x<=maxX; x++) {
for (int y=minY; y<=maxY; y++) {
for (int z=minZ; z<=maxZ; z++) {
if (entity.getInstance().getBlock(x, y, z).isSolid()) {
CollisionData cd = Collision.pushOutside(new Pos(x, y, z), entity, true);
collisions.add(cd);
}
}
}
}
} }
for (CollisionData collisionData : collisions) { for (CollisionData collisionData : collisions) {
if (collisionData.entity instanceof Player) { if (collisionData.entity instanceof Player) {
handlePlayerTouch((Player) collisionData.entity, collisionData); handlePlayerTouch((Player) collisionData.entity, collisionData);
} else {
handleBlockTouch(collisionData);
} }
} }
return velocity; return velocity;
} }
private void handleBlockTouch(CollisionData collisionData) {
}
private void handlePlayerTouch(Player player, CollisionData collisionData) { private void handlePlayerTouch(Player player, CollisionData collisionData) {
Vec offset = collisionData.offset; Vec offset = collisionData.offset;