Added config.
This commit is contained in:
		
							parent
							
								
									de6e50264b
								
							
						
					
					
						commit
						725659a4a4
					
				| 
						 | 
				
			
			@ -41,6 +41,12 @@
 | 
			
		|||
            <artifactId>zero-allocation-hashing</artifactId>
 | 
			
		||||
            <version>0.15</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.yaml</groupId>
 | 
			
		||||
            <artifactId>snakeyaml</artifactId>
 | 
			
		||||
            <version>1.30</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.slf4j</groupId>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 <T> The type of the configuration object.
 | 
			
		||||
	 */
 | 
			
		||||
	public static <T> T loadConfig(Class<T> configType, List<Path> 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> T loadConfig(Class<T> configType, List<Path> 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> T loadConfig(Class<T> configType, T fallback, Path... paths) {
 | 
			
		||||
		return loadConfig(configType, List.of(paths), fallback);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static List<Path> getCommonConfigPaths() {
 | 
			
		||||
		List<Path> 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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<Path> 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();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue