From ef262325d8b3a898c7c8a10a6329a8a5b9917b3a Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 7 Jul 2024 19:19:27 +0200 Subject: [PATCH] woadssda --- notes.txt | 4 - src/main/java/net/pivipi/ball/BallKicker.java | 90 +++++-------------- .../java/net/pivipi/physics/Collision.java | 69 ++++++++++++++ .../net/pivipi/physics/CollisionData.java | 10 +++ src/main/java/net/pivipi/physics/Physics.java | 63 ++++++++++--- 5 files changed, 151 insertions(+), 85 deletions(-) delete mode 100644 notes.txt create mode 100644 src/main/java/net/pivipi/physics/CollisionData.java diff --git a/notes.txt b/notes.txt deleted file mode 100644 index 1c800cb..0000000 --- a/notes.txt +++ /dev/null @@ -1,4 +0,0 @@ -don't forget when detecting collisions with moving players I should first check if they already overlap, if yes then push the ball out -if two players overlap with the ball then I don't know if you can combine the pushing do it if you can't push it away somehow -away I mean so like the ball has the largest possible same angle to both players -look I'm too young college how am I supposed to know things diff --git a/src/main/java/net/pivipi/ball/BallKicker.java b/src/main/java/net/pivipi/ball/BallKicker.java index 3feb300..592da4d 100644 --- a/src/main/java/net/pivipi/ball/BallKicker.java +++ b/src/main/java/net/pivipi/ball/BallKicker.java @@ -1,14 +1,18 @@ package net.pivipi.ball; +import javax.print.attribute.standard.MediaSize.Engineering; + import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Player; import net.minestom.server.event.GlobalEventHandler; +import net.minestom.server.event.player.PlayerHandAnimationEvent; import net.minestom.server.event.player.PlayerMoveEvent; import net.minestom.server.event.player.PlayerStartSneakingEvent; import net.minestom.server.event.player.PlayerStopSneakingEvent; import net.pivipi.physics.Collision; +import net.pivipi.physics.CollisionData; import net.pivipi.world.Stadium; public class BallKicker { // TODO apply physics settings here @@ -17,82 +21,19 @@ public class BallKicker { // TODO apply physics settings here private long lastSneak; private int sneakStreak; - private double headHeight = 0.3; // too low head kicks will be broken too high normal kicks will be broken - private double touchStrength = 1; // when the player walks into a ball - private double headJumpStrength = 5; // when the player jumps with a ball on their head, this is multiplied by touchstrength - private double dragDownStrength = 1; // when the player touches a ball + private double reach = 3; + private double verticalReach = 2; + private double maxKickStrength = 10; // if reach is 0, but you'll never hit the max public BallKicker(Stadium stadium) { this.stadium = stadium; } public void setup(GlobalEventHandler globalEventHandler) { - globalEventHandler.addListener(PlayerMoveEvent.class, event -> onMove(event)); + //globalEventHandler.addListener(PlayerMoveEvent.class, event -> onMove(event)); globalEventHandler.addListener(PlayerStartSneakingEvent.class, event -> onSneak(event)); globalEventHandler.addListener(PlayerStopSneakingEvent.class, event -> onStopSneaking(event)); - } - - private void onMove(PlayerMoveEvent event) { // is width x - Player player = event.getPlayer(); - Vec movementVec = player.getPosition().sub(player.getPreviousPosition()).asVec(); - - double ballXSize = stadium.ball.getBoundingBox().width(); - double playerXSize = player.getBoundingBox().width(); - double ballZSize = stadium.ball.getBoundingBox().depth(); - double playerZSize = player.getBoundingBox().depth(); - double ballHeight = stadium.ball.getBoundingBox().height(); - double playerHeight = player.getBoundingBox().height(); - Pos ballCenterPos = stadium.ball.getPosition(); - Pos playerCenterPos = event.getNewPosition(); - - Pos ballPos = ballCenterPos.sub(ballXSize / 2, 0, ballZSize / 2); - Pos playerPos = playerCenterPos.sub(playerXSize / 2, 0, playerZSize / 2); - Vec ballDistance = ballCenterPos.sub(playerCenterPos).asVec(); - - - if (ballDistance.y() > 0) { - if (ballPos.y() > playerPos.y() + playerHeight) return; - } else { - if (playerPos.y() > ballPos.y() + ballHeight) return; - } - - 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) - newBallOffset = newBallOffset.withZ(-diffZ); - } else { - diffZ = playerPos.z() - (ballPos.z() + ballZSize); - if (diffZ < 0) - newBallOffset = newBallOffset.withZ(diffZ); - ballDistance = ballDistance.withY(-dragDownStrength); - } - - if (diffX < 0 && diffZ < 0) { - if (ballPos.y() - player.getPreviousPosition().y() > playerHeight - headHeight) { // ball on head - System.out.println("jumped"); - double jumpHeight = movementVec.y(); - if (jumpHeight == 0) return; - newBallOffset = new Vec(0, jumpHeight, 0); - ballDistance = ballDistance.withY(headJumpStrength); - } - - stadium.ball.addPos(diffX < diffZ ? newBallOffset.withX(0) : newBallOffset.withZ(0)); - stadium.ball.addVelocity(ballDistance.mul(touchStrength)); - System.out.println(ballDistance); - } + globalEventHandler.addListener(PlayerHandAnimationEvent.class, event -> onSwing(event)); } private void onStopSneaking(PlayerStopSneakingEvent event) { @@ -131,4 +72,17 @@ public class BallKicker { // TODO apply physics settings here sneakStreak = 0; } } + + private void onSwing(PlayerHandAnimationEvent event) { + Player player = event.getPlayer(); + + CollisionData collisionData = new CollisionData(); + Collision.pushOutside(player, stadium.ball, collisionData); + double distance = collisionData.distance.withY(0).distance(0, 0, 0); + + if (collisionData.distance.y() < verticalReach && distance < reach) { + double percent = 1 - distance / reach; + stadium.ball.addVelocity(player.getPosition().direction().withY(y -> y + 1 - collisionData.distance.y()).mul(maxKickStrength * percent)); + } + } } diff --git a/src/main/java/net/pivipi/physics/Collision.java b/src/main/java/net/pivipi/physics/Collision.java index 826f5ed..ca9b6d6 100644 --- a/src/main/java/net/pivipi/physics/Collision.java +++ b/src/main/java/net/pivipi/physics/Collision.java @@ -3,8 +3,10 @@ package net.pivipi.physics; import net.minestom.server.collision.BoundingBox; import net.minestom.server.collision.SweepResult; 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; public class Collision { /** @@ -39,4 +41,71 @@ public class Collision { public static boolean collidesWithGround(double groundY, Entity entity) { return new BoundingBox(10, 1, 10).intersectEntity(entity.getPosition().withY(groundY - 1).sub(5, 0, 5), entity); } + + /** + * + * @param pusher the entity that's pushing like a player + * @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 + */ + public static Vec pushOutside(Entity pusher, Entity pushed) { + return pushOutside(pusher, pushed, null); + } + + /** + * + * @param pusher the entity that's pushing like a player + * @param pushed the entity that's being pushed like a ball + * @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 pushOutside(Entity pusher, Entity pushed, CollisionData collisionData) { + double ballXSize = pushed.getBoundingBox().width(); + double playerXSize = pusher.getBoundingBox().width(); + double ballZSize = pushed.getBoundingBox().depth(); + double playerZSize = pusher.getBoundingBox().depth(); + double ballHeight = pushed.getBoundingBox().height(); + double playerHeight = pusher.getBoundingBox().height(); + Pos ballCenterPos = pushed.getPosition(); + Pos playerCenterPos = pusher.getPosition(); + + 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) + 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); + + return null; + } } diff --git a/src/main/java/net/pivipi/physics/CollisionData.java b/src/main/java/net/pivipi/physics/CollisionData.java new file mode 100644 index 0000000..2cf2ba7 --- /dev/null +++ b/src/main/java/net/pivipi/physics/CollisionData.java @@ -0,0 +1,10 @@ +package net.pivipi.physics; + +import net.minestom.server.coordinate.Vec; + +public class CollisionData { + /** + * distance between centers of entities (but bottom y) + */ + public Vec distance; +} diff --git a/src/main/java/net/pivipi/physics/Physics.java b/src/main/java/net/pivipi/physics/Physics.java index 502906a..fd38ea4 100644 --- a/src/main/java/net/pivipi/physics/Physics.java +++ b/src/main/java/net/pivipi/physics/Physics.java @@ -3,6 +3,7 @@ package net.pivipi.physics; import java.util.Set; 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; @@ -16,6 +17,10 @@ public class Physics { private final double playerSneakingHeadBounciness = 0.2; private final double playerBodyBounciness = 0.2; private final double playerSneakingBodyBounciness = 0; + private final double playerCarryStrength = 2; + private final double headJumpStrength = 5; + private final double headNodStep = 20; + private final double jumpStrength = 20; private final double groundFriction = 0.5; private final double airFriction = 0.1; @@ -27,6 +32,7 @@ public class Physics { private Vec velocity = new Vec(0, 0, 0); private final Entity entity; + private Player holder; private int p; public Physics(Entity entity) { @@ -47,32 +53,23 @@ public class Physics { float offset = 0.5f; int count = (int) (f > delta / 1000 ? f / delta / 1000 : 1); - System.out.println(f); - System.out.println(dist); - System.out.println(count); entity.getInstance().sendGroupedPacket(new ParticlePacket(Particle.FLAME, false, entity.getPosition().x(), entity.getPosition().y() + 0.5, entity.getPosition().z(), offset, offset, offset, flameSpread, count)); } } - public 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)); if (Collision.collidesWithGround(2, entity)) { entity.teleport(entity.getPosition().withY(2)); - velocity = velocity.mul(1 - (groundFriction * delta), 1, 1 - (groundFriction * delta)); - } - - VisibleSweepResult result = Collision.willCollideWithGround(2, entity, velocity.mul(delta)); - if (result != null) { - velocity = velocity.mul(1, -blockBounciness, 1); + velocity = velocity.mul(1 - (groundFriction * delta), -blockBounciness, 1 - (groundFriction * delta)); } else { for (Player player : players) { boolean collides = Collision.collidesWithEntity(player, entity); if (collides) { - if (player.isSneaking()) - velocity = velocity.mul(-playerSneakingBodyBounciness, -playerSneakingHeadBounciness, -playerSneakingBodyBounciness); - else velocity = velocity.mul(-playerBodyBounciness, -playerHeadBounciness, -playerBodyBounciness); + handlePlayerTouch(player); + break; } } @@ -80,6 +77,46 @@ public class Physics { return velocity; } + + private void handlePlayerTouch(Player player) { + CollisionData collisionData = new CollisionData(); + Vec offset = Collision.pushOutside(player, entity, collisionData); // TODO predict the collision + + 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()); + + if (headOffsetY < 0.6) { // landed on head, magic value head height + if (movementPos.y() > 0) { + double headPitchDiff = Math.abs(movementPos.pitch()); + System.out.println(headPitchDiff); + addVelocity(player.getPosition().direction().mul(headPitchDiff / headNodStep).withY(headJumpStrength)); + } 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 + .withZ(z -> oppositeZ ? z * bodyBounciness : z + movementPos.z() * playerCarryStrength); + + System.out.println(velocity); + } + + } + } public void addVelocity(Vec velocity) {