diff --git a/core/pom.xml b/core/pom.xml
index 0e9a9bf..aca274b 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -41,6 +41,12 @@
zero-allocation-hashing
0.15
+
+
+ org.yaml
+ snakeyaml
+ 1.30
+
org.slf4j
diff --git a/core/src/main/java/nl/andrewl/aos_core/config/Config.java b/core/src/main/java/nl/andrewl/aos_core/config/Config.java
new file mode 100644
index 0000000..becf25a
--- /dev/null
+++ b/core/src/main/java/nl/andrewl/aos_core/config/Config.java
@@ -0,0 +1,58 @@
+package nl.andrewl.aos_core.config;
+
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class Config {
+ private static final Yaml yaml = new Yaml();
+
+ private Config() {}
+
+ /**
+ * Loads a configuration YAML object from the first available path.
+ * @param configType The type of the configuration object.
+ * @param paths The paths to load from.
+ * @param fallback A default configuration object to use if no config could
+ * be loaded from any of the paths.
+ * @return The configuration object.
+ * @param The type of the configuration object.
+ */
+ public static T loadConfig(Class configType, List paths, T fallback) {
+ for (var path : paths) {
+ if (Files.exists(path) && Files.isRegularFile(path) && Files.isReadable(path)) {
+ try (var reader = Files.newBufferedReader(path)) {
+ return yaml.loadAs(reader, configType);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return fallback;
+ }
+
+ public static T loadConfig(Class configType, List paths) {
+ var cfg = loadConfig(configType, paths, null);
+ if (cfg == null) {
+ throw new RuntimeException("Could not load config from any of the supplied paths.");
+ }
+ return cfg;
+ }
+
+ public static T loadConfig(Class configType, T fallback, Path... paths) {
+ return loadConfig(configType, List.of(paths), fallback);
+ }
+
+ public static List getCommonConfigPaths() {
+ List paths = new ArrayList<>();
+ paths.add(Path.of("config.yaml"));
+ paths.add(Path.of("config.yml"));
+ paths.add(Path.of("cfg.yaml"));
+ paths.add(Path.of("cfg.yml"));
+ return paths;
+ }
+}
diff --git a/server/src/main/java/nl/andrewl/aos2_server/Server.java b/server/src/main/java/nl/andrewl/aos2_server/Server.java
index 2648033..72223d5 100644
--- a/server/src/main/java/nl/andrewl/aos2_server/Server.java
+++ b/server/src/main/java/nl/andrewl/aos2_server/Server.java
@@ -1,7 +1,8 @@
package nl.andrewl.aos2_server;
+import nl.andrewl.aos2_server.config.ServerConfig;
+import nl.andrewl.aos_core.config.Config;
import nl.andrewl.aos_core.model.world.World;
-import nl.andrewl.aos_core.model.world.WorldIO;
import nl.andrewl.aos_core.model.world.Worlds;
import nl.andrewl.aos_core.net.UdpReceiver;
import nl.andrewl.aos_core.net.udp.ClientInputState;
@@ -15,6 +16,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.*;
import java.nio.file.Path;
+import java.util.List;
import java.util.concurrent.ForkJoinPool;
public class Server implements Runnable {
@@ -23,18 +25,19 @@ public class Server implements Runnable {
private final ServerSocket serverSocket;
private final DatagramSocket datagramSocket;
private volatile boolean running;
-
+ private final ServerConfig config;
private final PlayerManager playerManager;
private final World world;
private final WorldUpdater worldUpdater;
- public Server() throws IOException {
- this.serverSocket = new ServerSocket(25565, 5);
+ public Server(ServerConfig config) throws IOException {
+ this.config = config;
+ this.serverSocket = new ServerSocket(config.port, config.connectionBacklog);
this.serverSocket.setReuseAddress(true);
- this.datagramSocket = new DatagramSocket(25565);
+ this.datagramSocket = new DatagramSocket(config.port);
this.datagramSocket.setReuseAddress(true);
this.playerManager = new PlayerManager();
- this.worldUpdater = new WorldUpdater(this, 20);
+ this.worldUpdater = new WorldUpdater(this, config.ticksPerSecond);
this.world = Worlds.testingWorld();
}
@@ -107,6 +110,10 @@ public class Server implements Runnable {
}
}
+ public ServerConfig getConfig() {
+ return config;
+ }
+
public World getWorld() {
return world;
}
@@ -116,6 +123,11 @@ public class Server implements Runnable {
}
public static void main(String[] args) throws IOException {
- new Server().run();
+ List configPaths = Config.getCommonConfigPaths();
+ if (args.length > 0) {
+ configPaths.add(Path.of(args[0].trim()));
+ }
+ ServerConfig cfg = Config.loadConfig(ServerConfig.class, configPaths, new ServerConfig());
+ new Server(cfg).run();
}
}
diff --git a/server/src/main/java/nl/andrewl/aos2_server/ServerPlayer.java b/server/src/main/java/nl/andrewl/aos2_server/ServerPlayer.java
index c246970..f35e5c1 100644
--- a/server/src/main/java/nl/andrewl/aos2_server/ServerPlayer.java
+++ b/server/src/main/java/nl/andrewl/aos2_server/ServerPlayer.java
@@ -1,5 +1,6 @@
package nl.andrewl.aos2_server;
+import nl.andrewl.aos2_server.config.ServerConfig;
import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.world.World;
import nl.andrewl.aos_core.net.udp.ChunkUpdateMessage;
@@ -24,17 +25,6 @@ public class ServerPlayer extends Player {
public static final float WIDTH = 0.75f;
public static final float RADIUS = WIDTH / 2f;
- public static final float GRAVITY = 9.81f * 3;
- public static final float SPEED_NORMAL = 4f;
- public static final float SPEED_CROUCH = 1.5f;
- public static final float SPEED_SPRINT = 9f;
- public static final float MOVEMENT_ACCELERATION = 2f;
- public static final float MOVEMENT_DECELERATION = 1f;
- public static final float JUMP_SPEED = 8f;
-
- public static final int BLOCK_REMOVE_COOLDOWN = 250;
- public static final int BLOCK_PLACE_COOLDOWN = 100;
-
private ClientInputState lastInputState;
private long lastBlockRemovedAt = 0;
private long lastBlockPlacedAt = 0;
@@ -62,7 +52,7 @@ public class ServerPlayer extends Player {
public void tick(float dt, World world, Server server) {
long now = System.currentTimeMillis();
// Check for breaking blocks.
- if (lastInputState.hitting() && now - lastBlockRemovedAt > BLOCK_REMOVE_COOLDOWN) {
+ if (lastInputState.hitting() && now - lastBlockRemovedAt > server.getConfig().actions.blockRemoveCooldown * 1000) {
Vector3f eyePos = new Vector3f(position);
eyePos.y += getEyeHeight();
var hit = world.getLookingAtPos(eyePos, viewVector, 10);
@@ -73,7 +63,7 @@ public class ServerPlayer extends Player {
}
}
// Check for placing blocks.
- if (lastInputState.interacting() && now - lastBlockPlacedAt > BLOCK_PLACE_COOLDOWN) {
+ if (lastInputState.interacting() && now - lastBlockPlacedAt > server.getConfig().actions.blockPlaceCooldown * 1000) {
Vector3f eyePos = new Vector3f(position);
eyePos.y += getEyeHeight();
var hit = world.getLookingAtPos(eyePos, viewVector, 10);
@@ -85,21 +75,21 @@ public class ServerPlayer extends Player {
server.getPlayerManager().broadcastUdpMessage(ChunkUpdateMessage.fromWorld(placePos, world));
}
}
- tickMovement(dt, world);
+ tickMovement(dt, world, server.getConfig().physics);
}
- private void tickMovement(float dt, World world) {
+ private void tickMovement(float dt, World world, ServerConfig.PhysicsConfig config) {
updated = false; // Reset the updated flag. This will be set to true if the player was updated in this tick.
boolean grounded = isGrounded(world);
- tickHorizontalVelocity(grounded);
+ tickHorizontalVelocity(config, grounded);
if (isGrounded(world)) {
if (lastInputState.jumping()) {
- velocity.y = JUMP_SPEED * (lastInputState.sprinting() ? 1.25f : 1f);
+ velocity.y = config.jumpVerticalSpeed * (lastInputState.sprinting() ? 1.25f : 1f);
updated = true;
}
} else {
- velocity.y -= GRAVITY * dt;
+ velocity.y -= config.gravity * dt;
updated = true;
}
@@ -113,7 +103,7 @@ public class ServerPlayer extends Player {
}
}
- private void tickHorizontalVelocity(boolean doDeceleration) {
+ private void tickHorizontalVelocity(ServerConfig.PhysicsConfig config, boolean doDeceleration) {
Vector3f horizontalVelocity = new Vector3f(
velocity.x == velocity.x ? velocity.x : 0f,
0,
@@ -127,15 +117,15 @@ public class ServerPlayer extends Player {
if (acceleration.lengthSquared() > 0) {
acceleration.normalize();
acceleration.rotateAxis(orientation.x, 0, 1, 0);
- acceleration.mul(MOVEMENT_ACCELERATION);
+ acceleration.mul(config.movementAcceleration);
horizontalVelocity.add(acceleration);
final float maxSpeed;
if (lastInputState.crouching()) {
- maxSpeed = SPEED_CROUCH;
+ maxSpeed = config.crouchingSpeed;
} else if (lastInputState.sprinting()) {
- maxSpeed = SPEED_SPRINT;
+ maxSpeed = config.sprintingSpeed;
} else {
- maxSpeed = SPEED_NORMAL;
+ maxSpeed = config.walkingSpeed;
}
if (horizontalVelocity.length() > maxSpeed) {
horizontalVelocity.normalize(maxSpeed);
@@ -144,7 +134,7 @@ public class ServerPlayer extends Player {
} else if (doDeceleration && horizontalVelocity.lengthSquared() > 0) {
Vector3f deceleration = new Vector3f(horizontalVelocity)
.negate().normalize()
- .mul(Math.min(horizontalVelocity.length(), MOVEMENT_DECELERATION));
+ .mul(Math.min(horizontalVelocity.length(), config.movementDeceleration));
horizontalVelocity.add(deceleration);
if (horizontalVelocity.length() < 0.1f) {
horizontalVelocity.set(0);
diff --git a/server/src/main/java/nl/andrewl/aos2_server/config/ServerConfig.java b/server/src/main/java/nl/andrewl/aos2_server/config/ServerConfig.java
new file mode 100644
index 0000000..3808993
--- /dev/null
+++ b/server/src/main/java/nl/andrewl/aos2_server/config/ServerConfig.java
@@ -0,0 +1,24 @@
+package nl.andrewl.aos2_server.config;
+
+public class ServerConfig {
+ public int port = 25565;
+ public int connectionBacklog = 5;
+ public float ticksPerSecond = 20.0f;
+ public PhysicsConfig physics = new PhysicsConfig();
+ public ActionsConfig actions = new ActionsConfig();
+
+ public static class PhysicsConfig {
+ public float gravity = 9.81f * 3;
+ public float walkingSpeed = 4;
+ public float crouchingSpeed = 1.5f;
+ public float sprintingSpeed = 9;
+ public float movementAcceleration = 2;
+ public float movementDeceleration = 1;
+ public float jumpVerticalSpeed = 8;
+ }
+
+ public static class ActionsConfig {
+ public float blockRemoveCooldown = 0.25f;
+ public float blockPlaceCooldown = 0.1f;
+ }
+}