From a0a46197554286793e08e7aaef67d8ff738ceb00 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 14 Jul 2024 13:32:25 +0200 Subject: [PATCH] orient programming to object --- pom.xml | 2 +- src/main/java/net/pivipi/LoginHandler.java | 21 ++-- src/main/java/net/pivipi/Stats.java | 12 +- src/main/java/net/pivipi/ball/Ball.java | 2 +- src/main/java/net/pivipi/ball/BallKicker.java | 2 +- src/main/java/net/pivipi/game/Game.java | 104 ++++++++++++++++++ .../java/net/pivipi/game/PhysicsSettings.java | 47 ++++++++ src/main/java/net/pivipi/game/Stadium.java | 42 +++++++ src/main/java/net/pivipi/physics/Physics.java | 33 ++---- src/main/java/net/pivipi/world/Stadium.java | 12 -- 10 files changed, 222 insertions(+), 55 deletions(-) create mode 100644 src/main/java/net/pivipi/game/Game.java create mode 100644 src/main/java/net/pivipi/game/PhysicsSettings.java create mode 100644 src/main/java/net/pivipi/game/Stadium.java delete mode 100644 src/main/java/net/pivipi/world/Stadium.java diff --git a/pom.xml b/pom.xml index b4bb87a..e687014 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ net.minestom minestom-snapshots - d606051f1e + 7dd1792096 org.slf4j diff --git a/src/main/java/net/pivipi/LoginHandler.java b/src/main/java/net/pivipi/LoginHandler.java index 09b5293..7a976ca 100644 --- a/src/main/java/net/pivipi/LoginHandler.java +++ b/src/main/java/net/pivipi/LoginHandler.java @@ -1,6 +1,7 @@ package net.pivipi; import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; import net.minestom.server.entity.attribute.Attribute; @@ -9,23 +10,24 @@ import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; import net.minestom.server.event.player.PlayerDisconnectEvent; import net.minestom.server.event.player.PlayerSpawnEvent; import net.minestom.server.instance.Instance; -import net.pivipi.ball.Ball; import net.pivipi.ball.BallKicker; -import net.pivipi.world.Stadium; +import net.pivipi.game.Game; +import net.pivipi.game.Stadium; public class LoginHandler { private final Instance spawningInstance; - private final Stadium stadium = new Stadium(); + private final Game game; public LoginHandler(Instance spawningInstance) { this.spawningInstance = spawningInstance; + this.game = new Game(new Stadium(spawningInstance, new Vec(-50, 64, -50), new Vec(100))); } public void setup(GlobalEventHandler globalEventHandler) { globalEventHandler.addListener(AsyncPlayerConfigurationEvent.class, event -> onLogin(event)); globalEventHandler.addListener(PlayerDisconnectEvent.class, event -> onQuit(event)); globalEventHandler.addListener(PlayerSpawnEvent.class, event -> onSpawn(event)); - new BallKicker(stadium).setup(globalEventHandler); + new BallKicker(game.stadium).setup(globalEventHandler); } private void onLogin(AsyncPlayerConfigurationEvent event) { @@ -35,11 +37,11 @@ public class LoginHandler { event.setHardcore(true); player.setRespawnPoint(new Pos(0, 67, 0)); - stadium.players.add(player); + game.addPlayer(player); } private void onQuit(PlayerDisconnectEvent event) { - stadium.players.remove(event.getPlayer()); + game.removePlayer(event.getPlayer()); } private void onSpawn(PlayerSpawnEvent event) { @@ -49,11 +51,6 @@ public class LoginHandler { player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(0.2); player.getAttribute(Attribute.GENERIC_JUMP_STRENGTH).setBaseValue(0.36813); // just enough to jump a block - if (stadium.ball == null) { - Ball ball = new Ball(stadium); - ball.setInstance(event.getInstance()); - ball.teleport(new Pos(0, 90, 5)); - stadium.ball = ball; - } + game.startWarmup(); } } diff --git a/src/main/java/net/pivipi/Stats.java b/src/main/java/net/pivipi/Stats.java index 8223e3d..1d0c4f3 100644 --- a/src/main/java/net/pivipi/Stats.java +++ b/src/main/java/net/pivipi/Stats.java @@ -2,6 +2,7 @@ package net.pivipi; import net.kyori.adventure.text.Component; import net.minestom.server.instance.InstanceManager; +import net.minestom.server.timer.ExecutionType; import net.minestom.server.timer.SchedulerManager; import net.minestom.server.timer.TaskSchedule; @@ -19,7 +20,7 @@ public class Stats implements Runnable { public void start(SchedulerManager schedulerManager) { //this.benchmarkManager = MinecraftServer.getBenchmarkManager(); - schedulerManager.scheduleTask(this, TaskSchedule.immediate(), TaskSchedule.tick(tickDelay)); + schedulerManager.scheduleTask(this, TaskSchedule.immediate(), TaskSchedule.tick(tickDelay), ExecutionType.TICK_END); } @Override @@ -29,14 +30,11 @@ public class Stats implements Runnable { lastRun = now; double mspt = (double)delay / tickDelay; - double tps = 1000 / mspt; - - long memAllocated = runtime.totalMemory() / 1024 / 1024; - long memUsed = memAllocated - runtime.freeMemory() / 1024 / 1024; + long memUsed = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024; - Component footer = Component.text("%.3f MSPT | %.3f TPS | %dMB / %dMB".formatted(mspt, tps, memUsed, memAllocated)); + Component footer = Component.text("%.3f MSPT | %dMB".formatted(mspt, memUsed)); - instanceManager.getInstances().forEach(instance -> { + instanceManager.getInstances().forEach(instance -> { // TODO make this async instance.getPlayers().forEach(player -> { player.sendPlayerListFooter(footer); }); diff --git a/src/main/java/net/pivipi/ball/Ball.java b/src/main/java/net/pivipi/ball/Ball.java index 4c19ee3..11f3055 100644 --- a/src/main/java/net/pivipi/ball/Ball.java +++ b/src/main/java/net/pivipi/ball/Ball.java @@ -6,8 +6,8 @@ import net.minestom.server.entity.EntityType; import net.minestom.server.entity.Player; import net.minestom.server.entity.metadata.other.FallingBlockMeta; import net.minestom.server.instance.block.Block; +import net.pivipi.game.Stadium; import net.pivipi.physics.Physics; -import net.pivipi.world.Stadium; public class Ball extends Entity { private long lastTick; diff --git a/src/main/java/net/pivipi/ball/BallKicker.java b/src/main/java/net/pivipi/ball/BallKicker.java index 893c1e3..d140466 100644 --- a/src/main/java/net/pivipi/ball/BallKicker.java +++ b/src/main/java/net/pivipi/ball/BallKicker.java @@ -10,9 +10,9 @@ import net.minestom.server.event.player.PlayerHandAnimationEvent; import net.minestom.server.event.player.PlayerStartSneakingEvent; import net.minestom.server.event.player.PlayerStopSneakingEvent; import net.minestom.server.instance.block.Block; +import net.pivipi.game.Stadium; import net.pivipi.physics.Collision; import net.pivipi.physics.CollisionData; -import net.pivipi.world.Stadium; public class BallKicker { // TODO apply physics settings here public final Stadium stadium; diff --git a/src/main/java/net/pivipi/game/Game.java b/src/main/java/net/pivipi/game/Game.java new file mode 100644 index 0000000..df48f95 --- /dev/null +++ b/src/main/java/net/pivipi/game/Game.java @@ -0,0 +1,104 @@ +package net.pivipi.game; + +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.pivipi.ball.Ball; + +public class Game { + public final Stadium stadium; + + public boolean started; // true even if warmup + public boolean warmup; + public boolean paused; // is game paused + public long startedTime; // fine until year 292272993 but trust me it will pass in an Instant + public long lostTime; // how much ms the game was paused for + public long addedTime; // also called stoppage time, cosmetic since a person decides when to end the match + + private long pauseStart; + + public Game(Stadium stadium) { + this.stadium = stadium; + } + + + public boolean addPlayer(Player player) { + return stadium.players.add(player); + } + + public boolean removePlayer(Player player) { + return stadium.players.remove(player); + } + + /** + * starts warmup + * @return true if the game was not running + */ + public boolean startWarmup() { + if (!started && !warmup) return false; + + this.started = true; + this.warmup = true; + this.startedTime = System.currentTimeMillis(); + + Ball ball = new Ball(stadium); + ball.setInstance(stadium.instance); + ball.teleport(new Pos(stadium.max.sub(stadium.size.div(2)))); + stadium.ball = ball; + + return true; + } + + /** + * starts the game + * @return true if the game was not running or if there was warmup + */ + public boolean start() { + if (started && !warmup) return false; + + this.started = true; + this.warmup = false; + this.startedTime = System.currentTimeMillis(); + // TODO + return true; + } + + /** + * ends the game + * @return true if the game was running + */ + public boolean end() { + if (!started) return false; + + this.started = false; + this.warmup = false; + // TODO + return true; + } + + public boolean pause() { + if (paused) return false; + + pauseStart = System.currentTimeMillis(); + paused = true; + + return true; + } + + public boolean unpause() { + if (!paused) return false; + + lostTime += System.currentTimeMillis() - pauseStart; + paused = false; + + return true; + } + + /** + * suggests how much added time + * basically rounds down lost time to minutes + * @return + */ + public long suggestAddedTime() { + return (lostTime / 60000) * 60000; + } +} diff --git a/src/main/java/net/pivipi/game/PhysicsSettings.java b/src/main/java/net/pivipi/game/PhysicsSettings.java new file mode 100644 index 0000000..e40dfd7 --- /dev/null +++ b/src/main/java/net/pivipi/game/PhysicsSettings.java @@ -0,0 +1,47 @@ +package net.pivipi.game; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; + +public class PhysicsSettings { + public double gravity = 9.8; + public double blockBounciness = 0.5; + public double playerHeadBounciness = 0.5; + public double playerSneakingHeadBounciness = 0.2; + public double playerBodyBounciness = 0.2; + public double playerSneakingBodyBounciness = 0; + public double playerCarryStrength = 2; + public double headJumpStrength = 5; + public double headNodStep = 20; + public double jumpStrength = 20; + public double groundFriction = 0.5; + public double airFriction = 0.1; + + public String setByString(String key, String valueStr) { + + try { + Field field = this.getClass().getDeclaredField(key); + Type type = field.getAnnotatedType().getType(); + Object value; + + if (type.equals(double.class)) { + value = Double.valueOf(valueStr); + } else { + return "This property is not changeable because I can't yet handle type " + type.getTypeName(); + } + + field.setAccessible(true); + field.set(this, value); + + return field.getName() + " is now " + value.toString(); + } catch (NumberFormatException e) { + return "Not a decimal number: " + valueStr; + } catch (NoSuchFieldException e) { + return "Invalid key: " + key; + } catch (IllegalArgumentException e) { + return "Invalid value: " + valueStr; + } catch (IllegalAccessException e) { + return "This property is not changeable"; + } + } +} diff --git a/src/main/java/net/pivipi/game/Stadium.java b/src/main/java/net/pivipi/game/Stadium.java new file mode 100644 index 0000000..4059236 --- /dev/null +++ b/src/main/java/net/pivipi/game/Stadium.java @@ -0,0 +1,42 @@ +package net.pivipi.game; + +import java.util.HashSet; +import java.util.Set; + +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.Player; +import net.minestom.server.instance.Instance; +import net.pivipi.ball.Ball; + +public class Stadium { + public final Set players = new HashSet(); + public Ball ball; // TODO public? + + /** + * the instance where this stadium is + */ + public final Instance instance; + + /** + * the lower corner pos + */ + public final Vec pos; + + /** + * the stadium size + */ + public final Vec size; + + /** + * the max corner pos that is pos + size + */ + public final Vec max; + + + public Stadium(Instance instance, Vec pos, Vec size) { + this.instance = instance; + this.pos = pos; + this.size = size; + this.max = pos.add(size); + } +} diff --git a/src/main/java/net/pivipi/physics/Physics.java b/src/main/java/net/pivipi/physics/Physics.java index 98a7f14..07900aa 100644 --- a/src/main/java/net/pivipi/physics/Physics.java +++ b/src/main/java/net/pivipi/physics/Physics.java @@ -9,27 +9,18 @@ import net.minestom.server.entity.Entity; import net.minestom.server.entity.Player; import net.minestom.server.network.packet.server.play.ParticlePacket; import net.minestom.server.particle.Particle; +import net.pivipi.game.PhysicsSettings; public class Physics { - private final double gravity = 9.8; - private final double blockBounciness = 0.5; - private final double playerHeadBounciness = 0.5; - 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; - private final int groundY = 64; + private PhysicsSettings settings; 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 int groundY = 64; // this should be removed when block collisions + private Vec velocity = new Vec(0, 0, 0); private final Entity entity; @@ -59,12 +50,12 @@ public class Physics { } private Vec applyPhysics(double delta, Set players) { - velocity = velocity.sub(0, gravity * delta, 0).mul(1 - (airFriction * delta), 1, 1 - (airFriction * delta)); + velocity = velocity.sub(0, settings.gravity * delta, 0).mul(1 - (settings.airFriction * delta), 1, 1 - (settings.airFriction * delta)); ArrayList collisions = new ArrayList<>(); if (Collision.collidesWithGround(groundY, entity)) { entity.teleport(entity.getPosition().withY(groundY)); - velocity = velocity.mul(1 - (groundFriction * delta), -blockBounciness, 1 - (groundFriction * delta)); + velocity = velocity.mul(1 - (settings.groundFriction * delta), -settings.blockBounciness, 1 - (settings.groundFriction * delta)); } else { for (Player player : players) { CollisionData collisionData = new CollisionData(); @@ -103,17 +94,17 @@ public class Physics { 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); + addVelocity(player.getPosition().direction().mul(headPitchDiff / settings.headNodStep).withY(settings.headJumpStrength)); + } else velocity = velocity.mul(1, player.isSneaking() ? -settings.playerSneakingHeadBounciness : -settings.playerHeadBounciness, 1); entity.teleport(entity.getPosition().withY(y -> y + headOffsetY)); } else { 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; + double bodyBounciness = player.isSneaking() ? -settings.playerSneakingBodyBounciness : -settings.playerBodyBounciness; 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); + .withX(x -> oppositeX ? x * bodyBounciness : x + movementPos.x() * settings.playerCarryStrength) + .withY(y -> collisionData.distance.y() < 1.0 ? movementPos.y() * settings.jumpStrength : y) // magic value legs + .withZ(z -> oppositeZ ? z * bodyBounciness : z + movementPos.z() * settings.playerCarryStrength); } } diff --git a/src/main/java/net/pivipi/world/Stadium.java b/src/main/java/net/pivipi/world/Stadium.java deleted file mode 100644 index 0e13d32..0000000 --- a/src/main/java/net/pivipi/world/Stadium.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.pivipi.world; - -import java.util.HashSet; -import java.util.Set; - -import net.minestom.server.entity.Player; -import net.pivipi.ball.Ball; - -public class Stadium { - public final Set players = new HashSet(); - public Ball ball; -}