Added client config.

This commit is contained in:
Andrew Lalis 2022-07-17 20:02:18 +02:00
parent 725659a4a4
commit 6950d40bfd
5 changed files with 63 additions and 39 deletions

View File

@ -1,10 +1,12 @@
package nl.andrewl.aos2_client; package nl.andrewl.aos2_client;
import nl.andrewl.aos2_client.config.ClientConfig;
import nl.andrewl.aos2_client.control.InputHandler; import nl.andrewl.aos2_client.control.InputHandler;
import nl.andrewl.aos2_client.control.PlayerInputKeyCallback; import nl.andrewl.aos2_client.control.PlayerInputKeyCallback;
import nl.andrewl.aos2_client.control.PlayerInputMouseClickCallback; import nl.andrewl.aos2_client.control.PlayerInputMouseClickCallback;
import nl.andrewl.aos2_client.control.PlayerViewCursorCallback; import nl.andrewl.aos2_client.control.PlayerViewCursorCallback;
import nl.andrewl.aos2_client.render.GameRenderer; import nl.andrewl.aos2_client.render.GameRenderer;
import nl.andrewl.aos_core.config.Config;
import nl.andrewl.aos_core.model.world.ColorPalette; import nl.andrewl.aos_core.model.world.ColorPalette;
import nl.andrewl.aos_core.net.*; import nl.andrewl.aos_core.net.*;
import nl.andrewl.aos_core.net.udp.ChunkUpdateMessage; import nl.andrewl.aos_core.net.udp.ChunkUpdateMessage;
@ -14,16 +16,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.nio.file.Path;
import java.util.List;
public class Client implements Runnable { public class Client implements Runnable {
private static final Logger log = LoggerFactory.getLogger(Client.class); private static final Logger log = LoggerFactory.getLogger(Client.class);
public static final double FPS = 60; public static final double FPS = 60;
private final InetAddress serverAddress; private final ClientConfig config;
private final int serverPort;
private final String username;
private final CommunicationHandler communicationHandler; private final CommunicationHandler communicationHandler;
private final InputHandler inputHandler; private final InputHandler inputHandler;
private final GameRenderer gameRenderer; private final GameRenderer gameRenderer;
@ -31,33 +31,31 @@ public class Client implements Runnable {
private int clientId; private int clientId;
private final ClientWorld world; private final ClientWorld world;
public Client(InetAddress serverAddress, int serverPort, String username) { public Client(ClientConfig config) {
this.serverAddress = serverAddress; this.config = config;
this.serverPort = serverPort;
this.username = username;
this.communicationHandler = new CommunicationHandler(this); this.communicationHandler = new CommunicationHandler(this);
this.inputHandler = new InputHandler(communicationHandler); this.inputHandler = new InputHandler(communicationHandler);
this.world = new ClientWorld(); this.world = new ClientWorld();
this.gameRenderer = new GameRenderer(world); this.gameRenderer = new GameRenderer(config.display, world);
}
public ClientConfig getConfig() {
return config;
} }
@Override @Override
public void run() { public void run() {
try { try {
log.debug("Connecting to server at {}, port {}, with username \"{}\"...", serverAddress, serverPort, username); this.clientId = communicationHandler.establishConnection();
this.clientId = communicationHandler.establishConnection(serverAddress, serverPort, username);
log.info("Established a connection to the server.");
} catch (IOException e) { } catch (IOException e) {
log.error("Couldn't connect to the server: {}", e.getMessage()); log.error("Couldn't connect to the server: {}", e.getMessage());
return; return;
} }
gameRenderer.setupWindow( gameRenderer.setupWindow(
new PlayerViewCursorCallback(gameRenderer.getCamera(), communicationHandler), new PlayerViewCursorCallback(config.input, gameRenderer.getCamera(), communicationHandler),
new PlayerInputKeyCallback(inputHandler), new PlayerInputKeyCallback(inputHandler),
new PlayerInputMouseClickCallback(inputHandler), new PlayerInputMouseClickCallback(inputHandler)
false,
false
); );
long lastFrameAt = System.currentTimeMillis(); long lastFrameAt = System.currentTimeMillis();
@ -107,11 +105,12 @@ public class Client implements Runnable {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
InetAddress serverAddress = InetAddress.getByName(args[0]); List<Path> configPaths = Config.getCommonConfigPaths();
int serverPort = Integer.parseInt(args[1]); if (args.length > 0) {
String username = args[2].trim(); configPaths.add(Path.of(args[0].trim()));
}
Client client = new Client(serverAddress, serverPort, username); ClientConfig clientConfig = Config.loadConfig(ClientConfig.class, configPaths, new ClientConfig());
Client client = new Client(clientConfig);
client.run(); client.run();
} }
} }

View File

@ -33,10 +33,15 @@ public class CommunicationHandler {
this.client = client; this.client = client;
} }
public int establishConnection(InetAddress address, int port, String username) throws IOException { public int establishConnection() throws IOException {
if (socket != null && !socket.isClosed()) { if (socket != null && !socket.isClosed()) {
socket.close(); socket.close();
} }
InetAddress address = InetAddress.getByName(client.getConfig().serverHost);
int port = client.getConfig().serverPort;
String username = client.getConfig().username;
log.info("Connecting to server at {}, port {}, with username \"{}\"...", address, port, username);
socket = new Socket(address, port); socket = new Socket(address, port);
socket.setSoTimeout(1000); socket.setSoTimeout(1000);
ExtendedDataInputStream in = Net.getInputStream(socket.getInputStream()); ExtendedDataInputStream in = Net.getInputStream(socket.getInputStream());
@ -50,6 +55,7 @@ public class CommunicationHandler {
if (response instanceof ConnectAcceptMessage acceptMessage) { if (response instanceof ConnectAcceptMessage acceptMessage) {
this.clientId = acceptMessage.clientId(); this.clientId = acceptMessage.clientId();
establishDatagramConnection(); establishDatagramConnection();
log.info("Connection to server established. My client id is {}.", clientId);
new Thread(new TcpReceiver(in, client::onMessageReceived)).start(); new Thread(new TcpReceiver(in, client::onMessageReceived)).start();
new Thread(new UdpReceiver(datagramSocket, (msg, packet) -> client.onMessageReceived(msg))).start(); new Thread(new UdpReceiver(datagramSocket, (msg, packet) -> client.onMessageReceived(msg))).start();
return acceptMessage.clientId(); return acceptMessage.clientId();

View File

@ -0,0 +1,19 @@
package nl.andrewl.aos2_client.config;
public class ClientConfig {
public String serverHost = "localhost";
public int serverPort = 25565;
public String username = "player";
public InputConfig input = new InputConfig();
public DisplayConfig display = new DisplayConfig();
public static class InputConfig {
public float mouseSensitivity = 0.005f;
}
public static class DisplayConfig {
public boolean fullscreen = false;
public boolean captureCursor = true;
public float fov = 70;
}
}

View File

@ -2,6 +2,7 @@ package nl.andrewl.aos2_client.control;
import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.CommunicationHandler; import nl.andrewl.aos2_client.CommunicationHandler;
import nl.andrewl.aos2_client.config.ClientConfig;
import nl.andrewl.aos_core.net.udp.ClientOrientationState; import nl.andrewl.aos_core.net.udp.ClientOrientationState;
import org.lwjgl.glfw.GLFWCursorPosCallbackI; import org.lwjgl.glfw.GLFWCursorPosCallbackI;
@ -20,14 +21,15 @@ public class PlayerViewCursorCallback implements GLFWCursorPosCallbackI {
*/ */
private static final int ORIENTATION_UPDATE_LIMIT = 20; private static final int ORIENTATION_UPDATE_LIMIT = 20;
private final ClientConfig.InputConfig config;
private final Camera camera; private final Camera camera;
private final CommunicationHandler comm; private final CommunicationHandler comm;
private float lastMouseCursorX; private float lastMouseCursorX;
private float lastMouseCursorY; private float lastMouseCursorY;
private float mouseCursorSensitivity = 0.005f;
private long lastOrientationUpdateSentAt = 0L; private long lastOrientationUpdateSentAt = 0L;
public PlayerViewCursorCallback(Camera camera, CommunicationHandler comm) { public PlayerViewCursorCallback(ClientConfig.InputConfig config, Camera camera, CommunicationHandler comm) {
this.config = config;
this.camera = camera; this.camera = camera;
this.comm = comm; this.comm = comm;
} }
@ -43,7 +45,10 @@ public class PlayerViewCursorCallback implements GLFWCursorPosCallbackI {
float dy = y - lastMouseCursorY; float dy = y - lastMouseCursorY;
lastMouseCursorX = x; lastMouseCursorX = x;
lastMouseCursorY = y; lastMouseCursorY = y;
camera.setOrientation(camera.getOrientation().x - dx * mouseCursorSensitivity, camera.getOrientation().y - dy * mouseCursorSensitivity); camera.setOrientation(
camera.getOrientation().x - dx * config.mouseSensitivity,
camera.getOrientation().y - dy * config.mouseSensitivity
);
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (lastOrientationUpdateSentAt + ORIENTATION_UPDATE_LIMIT < now) { if (lastOrientationUpdateSentAt + ORIENTATION_UPDATE_LIMIT < now) {
ForkJoinPool.commonPool().submit(() -> comm.sendDatagramPacket(new ClientOrientationState(comm.getClientId(), camera.getOrientation().x, camera.getOrientation().y))); ForkJoinPool.commonPool().submit(() -> comm.sendDatagramPacket(new ClientOrientationState(comm.getClientId(), camera.getOrientation().x, camera.getOrientation().y)));

View File

@ -2,6 +2,7 @@ package nl.andrewl.aos2_client.render;
import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.ClientWorld; import nl.andrewl.aos2_client.ClientWorld;
import nl.andrewl.aos2_client.config.ClientConfig;
import nl.andrewl.aos2_client.render.chunk.ChunkRenderer; import nl.andrewl.aos2_client.render.chunk.ChunkRenderer;
import nl.andrewl.aos2_client.render.gui.GUIRenderer; import nl.andrewl.aos2_client.render.gui.GUIRenderer;
import nl.andrewl.aos2_client.render.gui.GUITexture; import nl.andrewl.aos2_client.render.gui.GUITexture;
@ -28,6 +29,7 @@ public class GameRenderer {
private static final float Z_NEAR = 0.01f; private static final float Z_NEAR = 0.01f;
private static final float Z_FAR = 500f; private static final float Z_FAR = 500f;
private final ClientConfig.DisplayConfig config;
private ChunkRenderer chunkRenderer; private ChunkRenderer chunkRenderer;
private GUIRenderer guiRenderer; private GUIRenderer guiRenderer;
private ModelRenderer modelRenderer; private ModelRenderer modelRenderer;
@ -39,11 +41,11 @@ public class GameRenderer {
private long windowHandle; private long windowHandle;
private int screenWidth = 800; private int screenWidth = 800;
private int screenHeight = 600; private int screenHeight = 600;
private float fov = 90f;
private final Matrix4f perspectiveTransform; private final Matrix4f perspectiveTransform;
public GameRenderer(ClientWorld world) { public GameRenderer(ClientConfig.DisplayConfig config, ClientWorld world) {
this.config = config;
this.world = world; this.world = world;
this.camera = new Camera(); this.camera = new Camera();
this.perspectiveTransform = new Matrix4f(); this.perspectiveTransform = new Matrix4f();
@ -52,9 +54,7 @@ public class GameRenderer {
public void setupWindow( public void setupWindow(
GLFWCursorPosCallbackI viewCursorCallback, GLFWCursorPosCallbackI viewCursorCallback,
GLFWKeyCallbackI inputKeyCallback, GLFWKeyCallbackI inputKeyCallback,
GLFWMouseButtonCallbackI mouseButtonCallback, GLFWMouseButtonCallbackI mouseButtonCallback
boolean fullscreen,
boolean grabCursor
) { ) {
GLFWErrorCallback.createPrint(System.err).set(); GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) throw new IllegalStateException("Could not initialize GLFW."); if (!glfwInit()) throw new IllegalStateException("Could not initialize GLFW.");
@ -66,7 +66,7 @@ public class GameRenderer {
GLFWVidMode primaryMonitorSettings = glfwGetVideoMode(monitorId); GLFWVidMode primaryMonitorSettings = glfwGetVideoMode(monitorId);
if (primaryMonitorSettings == null) throw new IllegalStateException("Could not get information about the primary monitory."); if (primaryMonitorSettings == null) throw new IllegalStateException("Could not get information about the primary monitory.");
log.debug("Primary monitor settings: Width: {}, Height: {}", primaryMonitorSettings.width(), primaryMonitorSettings.height()); log.debug("Primary monitor settings: Width: {}, Height: {}", primaryMonitorSettings.width(), primaryMonitorSettings.height());
if (fullscreen) { if (config.fullscreen) {
screenWidth = primaryMonitorSettings.width(); screenWidth = primaryMonitorSettings.width();
screenHeight = primaryMonitorSettings.height(); screenHeight = primaryMonitorSettings.height();
windowHandle = glfwCreateWindow(screenWidth, screenHeight, "Ace of Shades 2", monitorId, 0); windowHandle = glfwCreateWindow(screenWidth, screenHeight, "Ace of Shades 2", monitorId, 0);
@ -82,7 +82,7 @@ public class GameRenderer {
glfwSetKeyCallback(windowHandle, inputKeyCallback); glfwSetKeyCallback(windowHandle, inputKeyCallback);
glfwSetCursorPosCallback(windowHandle, viewCursorCallback); glfwSetCursorPosCallback(windowHandle, viewCursorCallback);
glfwSetMouseButtonCallback(windowHandle, mouseButtonCallback); glfwSetMouseButtonCallback(windowHandle, mouseButtonCallback);
if (grabCursor) { if (config.captureCursor) {
glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(windowHandle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
} }
glfwSetInputMode(windowHandle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); glfwSetInputMode(windowHandle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
@ -125,11 +125,6 @@ public class GameRenderer {
updatePerspective(); updatePerspective();
} }
public void setFov(float fov) {
this.fov = fov;
updatePerspective();
}
public float getAspectRatio() { public float getAspectRatio() {
return (float) screenWidth / (float) screenHeight; return (float) screenWidth / (float) screenHeight;
} }
@ -138,7 +133,7 @@ public class GameRenderer {
* Updates the rendering perspective used to render the game. * Updates the rendering perspective used to render the game.
*/ */
private void updatePerspective() { private void updatePerspective() {
perspectiveTransform.setPerspective(fov, getAspectRatio(), Z_NEAR, Z_FAR); perspectiveTransform.setPerspective(config.fov, getAspectRatio(), Z_NEAR, Z_FAR);
float[] data = new float[16]; float[] data = new float[16];
perspectiveTransform.get(data); perspectiveTransform.get(data);
if (chunkRenderer != null) chunkRenderer.setPerspective(data); if (chunkRenderer != null) chunkRenderer.setPerspective(data);