diff --git a/client/src/main/java/nl/andrewl/aos2_client/Client.java b/client/src/main/java/nl/andrewl/aos2_client/Client.java index bfb270f..95504f6 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/Client.java +++ b/client/src/main/java/nl/andrewl/aos2_client/Client.java @@ -3,13 +3,10 @@ package nl.andrewl.aos2_client; import nl.andrewl.aos2_client.render.ChunkMesh; import nl.andrewl.aos2_client.render.ChunkRenderer; import nl.andrewl.aos2_client.render.WindowUtils; -import nl.andrewl.aos_core.model.Chunk; -import org.joml.Vector3i; +import nl.andrewl.aos_core.model.World; import java.io.IOException; import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Random; import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.opengl.GL46.*; @@ -22,81 +19,79 @@ public class Client implements Runnable { Client client = new Client(serverAddress, serverPort, username); client.run(); - - -// var windowInfo = WindowUtils.initUI(); -// long windowHandle = windowInfo.windowHandle(); -// -// Camera cam = new Camera(); -// cam.setOrientationDegrees(90, 90); -// cam.setPosition(-3, 3, 0); -// glfwSetCursorPosCallback(windowHandle, cam); -// -// Chunk chunk = Chunk.random(new Vector3i(0, 0, 0), new Random(1)); -// Chunk chunk2 = Chunk.random(new Vector3i(1, 0, 0), new Random(1)); -// Chunk chunk3 = Chunk.random(new Vector3i(1, 0, 1), new Random(1)); -// Chunk chunk4 = Chunk.random(new Vector3i(0, 0, 1), new Random(1)); -// -// chunk.setBlockAt(0, 0, 0, (byte) 0); -// -// for (int x = 0; x < Chunk.SIZE; x++) { -// for (int z = 0; z < Chunk.SIZE; z++) { -// chunk.setBlockAt(x, Chunk.SIZE - 1, z, (byte) 0); -// } -// } -// -// ChunkRenderer chunkRenderer = new ChunkRenderer(windowInfo.width(), windowInfo.height()); -// chunkRenderer.addChunkMesh(new ChunkMesh(chunk)); -// chunkRenderer.addChunkMesh(new ChunkMesh(chunk2)); -// chunkRenderer.addChunkMesh(new ChunkMesh(chunk3)); -// chunkRenderer.addChunkMesh(new ChunkMesh(chunk4)); -// -// while (!glfwWindowShouldClose(windowHandle)) { -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -// -// chunkRenderer.draw(cam); -// -// glfwSwapBuffers(windowHandle); -// glfwPollEvents(); -// -// if (glfwGetKey(windowHandle, GLFW_KEY_W) == GLFW_PRESS) cam.move(Camera.FORWARD); -// if (glfwGetKey(windowHandle, GLFW_KEY_S) == GLFW_PRESS) cam.move(Camera.BACKWARD); -// if (glfwGetKey(windowHandle, GLFW_KEY_A) == GLFW_PRESS) cam.move(Camera.LEFT); -// if (glfwGetKey(windowHandle, GLFW_KEY_D) == GLFW_PRESS) cam.move(Camera.RIGHT); -// if (glfwGetKey(windowHandle, GLFW_KEY_SPACE) == GLFW_PRESS) cam.move(Camera.UP); -// if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) cam.move(Camera.DOWN); -// } -// -// chunkRenderer.free(); -// WindowUtils.clearUI(windowHandle); } private InetAddress serverAddress; private int serverPort; private String username; private CommunicationHandler communicationHandler; - private volatile boolean running; + private ChunkRenderer chunkRenderer; + + private World world; public Client(InetAddress serverAddress, int serverPort, String username) { this.serverAddress = serverAddress; this.serverPort = serverPort; this.username = username; - this.communicationHandler = new CommunicationHandler(); + this.communicationHandler = new CommunicationHandler(this); + this.world = new World(); } @Override public void run() { - running = false; + var windowInfo = WindowUtils.initUI(); + long windowHandle = windowInfo.windowHandle(); + chunkRenderer = new ChunkRenderer(windowInfo.width(), windowInfo.height()); + try { communicationHandler.establishConnection(serverAddress, serverPort, username); System.out.println("Established connection to the server."); } catch (IOException e) { e.printStackTrace(); - running = false; + return; // Exit without starting the game. } - while (running) { - // Do game stuff - System.out.println("Running!"); + + System.out.println("Waiting for all world data to arrive..."); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); } + for (var chunk : world.getChunkMap().values()) { + chunkRenderer.addChunkMesh(new ChunkMesh(chunk)); + } + + Camera cam = new Camera(); + cam.setOrientationDegrees(90, 90); + cam.setPosition(0, 48, 0); + glfwSetCursorPosCallback(windowHandle, cam); + + + while (!glfwWindowShouldClose(windowHandle)) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + chunkRenderer.draw(cam); + + glfwSwapBuffers(windowHandle); + glfwPollEvents(); + + if (glfwGetKey(windowHandle, GLFW_KEY_W) == GLFW_PRESS) cam.move(Camera.FORWARD); + if (glfwGetKey(windowHandle, GLFW_KEY_S) == GLFW_PRESS) cam.move(Camera.BACKWARD); + if (glfwGetKey(windowHandle, GLFW_KEY_A) == GLFW_PRESS) cam.move(Camera.LEFT); + if (glfwGetKey(windowHandle, GLFW_KEY_D) == GLFW_PRESS) cam.move(Camera.RIGHT); + if (glfwGetKey(windowHandle, GLFW_KEY_SPACE) == GLFW_PRESS) cam.move(Camera.UP); + if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) cam.move(Camera.DOWN); + } + + chunkRenderer.free(); + WindowUtils.clearUI(windowHandle); + } + + public World getWorld() { + return world; + } + + public ChunkRenderer getChunkRenderer() { + return chunkRenderer; } } diff --git a/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java b/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java index 625b981..8bab550 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java +++ b/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java @@ -1,6 +1,7 @@ package nl.andrewl.aos2_client; import nl.andrewl.aos_core.Net; +import nl.andrewl.aos_core.model.Chunk; import nl.andrewl.aos_core.net.*; import nl.andrewl.aos_core.net.udp.DatagramInit; import nl.andrewl.record_net.Message; @@ -19,12 +20,16 @@ import java.net.Socket; * methods for sending messages and processing those we receive. */ public class CommunicationHandler { + private final Client client; private Socket socket; private DatagramSocket datagramSocket; - private ExtendedDataInputStream in; private ExtendedDataOutputStream out; private int clientId; + public CommunicationHandler(Client client) { + this.client = client; + } + public int establishConnection(InetAddress address, int port, String username) throws IOException { System.out.printf("Connecting to server at %s, port %d, with username \"%s\"...%n", address, port, username); if (socket != null && !socket.isClosed()) { @@ -32,7 +37,7 @@ public class CommunicationHandler { } socket = new Socket(address, port); socket.setSoTimeout(1000); - in = Net.getInputStream(socket.getInputStream()); + ExtendedDataInputStream in = Net.getInputStream(socket.getInputStream()); out = Net.getOutputStream(socket.getOutputStream()); Net.write(new ConnectRequestMessage(username), out); Message response = Net.read(in); @@ -42,8 +47,8 @@ public class CommunicationHandler { } if (response instanceof ConnectAcceptMessage acceptMessage) { this.clientId = acceptMessage.clientId(); - new Thread(new TcpReceiver(in, this::handleMessage)).start(); establishDatagramConnection(); + new Thread(new TcpReceiver(in, this::handleMessage)).start(); new Thread(new UdpReceiver(datagramSocket, this::handleUdpMessage)).start(); return acceptMessage.clientId(); } else { @@ -109,6 +114,10 @@ public class CommunicationHandler { private void handleMessage(Message msg) { System.out.println("Received message: " + msg); + if (msg instanceof ChunkDataMessage chunkDataMessage) { + Chunk chunk = chunkDataMessage.toChunk(); + client.getWorld().addChunk(chunk); + } } private void handleUdpMessage(Message msg, DatagramPacket packet) { diff --git a/core/src/main/java/nl/andrewl/aos_core/model/Chunk.java b/core/src/main/java/nl/andrewl/aos_core/model/Chunk.java index 1b916dd..07973d3 100644 --- a/core/src/main/java/nl/andrewl/aos_core/model/Chunk.java +++ b/core/src/main/java/nl/andrewl/aos_core/model/Chunk.java @@ -29,6 +29,11 @@ public class Chunk { this.position = new Vector3i(cx, cy, cz); } + public Chunk(int cx, int cy, int cz, byte[] blocks) { + this(cx, cy, cz); + System.arraycopy(blocks, 0, this.blocks, 0, TOTAL_SIZE); + } + public Chunk(Vector3i position) { this.position = new Vector3i(position); } diff --git a/core/src/main/java/nl/andrewl/aos_core/net/ChunkDataMessage.java b/core/src/main/java/nl/andrewl/aos_core/net/ChunkDataMessage.java index 8560519..6ecce41 100644 --- a/core/src/main/java/nl/andrewl/aos_core/net/ChunkDataMessage.java +++ b/core/src/main/java/nl/andrewl/aos_core/net/ChunkDataMessage.java @@ -13,4 +13,8 @@ public record ChunkDataMessage( public ChunkDataMessage(Chunk chunk) { this(chunk.getPosition().x, chunk.getPosition().y, chunk.getPosition().z, chunk.getBlocks()); } + + public Chunk toChunk() { + return new Chunk(cx, cy, cz, blocks); + } } diff --git a/core/src/main/java/nl/andrewl/aos_core/net/TcpReceiver.java b/core/src/main/java/nl/andrewl/aos_core/net/TcpReceiver.java index 1511089..e806d0f 100644 --- a/core/src/main/java/nl/andrewl/aos_core/net/TcpReceiver.java +++ b/core/src/main/java/nl/andrewl/aos_core/net/TcpReceiver.java @@ -32,7 +32,7 @@ public class TcpReceiver implements Runnable { Message msg = Net.read(in); messageConsumer.accept(msg); } catch (SocketException e) { - if (e.getMessage().equals("Socket closed")) { + if (e.getMessage().equals("Socket closed") || e.getMessage().equals("Connection reset")) { running = false; } else { e.printStackTrace(); 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 b5075a3..b97e34d 100644 --- a/server/src/main/java/nl/andrewl/aos2_server/Server.java +++ b/server/src/main/java/nl/andrewl/aos2_server/Server.java @@ -12,6 +12,7 @@ import java.net.*; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Random; import java.util.concurrent.ForkJoinPool; public class Server implements Runnable { @@ -33,12 +34,15 @@ public class Server implements Runnable { this.playerClientHandlers = new HashMap<>(); // Generate world. TODO: do this elsewhere. + Random rand = new Random(1); this.world = new World(); for (int x = -5; x <= 5; x++) { for (int y = 0; y <= 3; y++) { for (int z = -3; z <= 3; z++) { Chunk chunk = new Chunk(x, y, z); - Arrays.fill(chunk.getBlocks(), (byte) 40); + for (int i = 0; i < Chunk.TOTAL_SIZE; i++) { + chunk.getBlocks()[i] = (byte) rand.nextInt(20, 40); + } world.addChunk(chunk); } }