Browse Source

world split over server and client

Kajetan Johannes Hammerle 2 years ago
parent
commit
8780546f11

+ 5 - 7
client/Game.cpp

@@ -1,15 +1,13 @@
 #include "client/Game.h"
 #include "client/GameClient.h"
+#include "client/World.h"
 #include "client/gui/StartGUI.h"
 #include "client/rendering/Engine.h"
 #include "common/network/Packets.h"
 #include "common/network/toserver/PlayerUpdatePacket.h"
-#include "rendering/renderer/WorldRenderer.h"
 #include "utils/Logger.h"
 #include "utils/Utils.h"
 
-World Game::world;
-static WorldRenderer worldRenderer{Game::world};
 Controller Game::controller;
 Entity Game::player;
 
@@ -22,7 +20,7 @@ static StartGUI startGUI;
 
 static void tickConnectedState() {
     Game::player.skip = false;
-    Game::world.tick();
+    World::tick();
     GameClient::consumeEvents();
 
     Quaternion q = Game::player.getRotation();
@@ -98,7 +96,7 @@ static void renderConnectState() {
 
 bool Game::init() {
     Block::init();
-    if(worldRenderer.init()) {
+    if(World::init()) {
         return true;
     }
     controller.init();
@@ -106,7 +104,7 @@ bool Game::init() {
     renderState = renderConnectState;
 
     Game::player.setPosition(Vector3(0.0f, 2.0f, 0.0f));
-    world.addEntity(&player);
+    World::addEntity(&player);
     return false;
 }
 
@@ -117,7 +115,7 @@ void Game::tick() {
 void Game::renderWorld() {
     Engine::matrix.update(player.getRenderPosition(Engine::lag),
                           player.getRenderRotation(Engine::lag));
-    worldRenderer.render();
+    World::render();
 }
 
 void Game::renderOverlay() {

+ 0 - 2
client/Game.h

@@ -4,10 +4,8 @@
 #include "client/input/Controller.h"
 #include "common/entities/Entity.h"
 #include "common/network/toclient/EntityUpdatePacket.h"
-#include "common/world/World.h"
 
 namespace Game {
-    extern World world;
     extern Controller controller;
     extern Entity player;
 

+ 1 - 1
client/GameClient.cpp

@@ -37,7 +37,7 @@ struct Receiver {
                 break;
             }
             case Packets::S_WORLD_SEGMENT:
-                WorldPackets::receiveChunk(Game::world, in);
+                WorldPackets::receiveChunk(in);
                 break;
             case Packets::S_ENTITY_UPDATE: handleEntityUpdate(in); break;
             default: LOG_WARNING(INVALID_PACKAGE);

+ 204 - 0
client/World.cpp

@@ -0,0 +1,204 @@
+#include <cmath>
+
+#include "client/World.h"
+#include "client/rendering/Engine.h"
+#include "client/rendering/Mesh.h"
+#include "common/BlockStorage.h"
+#include "rendering/FileTexture.h"
+#include "utils/List.h"
+#include "utils/Logger.h"
+#include "utils/Random.h"
+
+static BlockStorage blocks{7, 7};
+static List<Entity*> entities;
+static Mesh mesh;
+static FileTexture texture;
+static bool dirty = true;
+
+bool World::init() {
+    mesh.init();
+    Error error = texture.load("resources/textures.png", 4);
+    if(error.has()) {
+        LOG_ERROR(error.message);
+    }
+    return error.has();
+}
+
+void World::addEntity(Entity* e) {
+    entities.add(e);
+}
+
+void World::removeEntity(Entity* e) {
+    for(int i = 0; i < entities.getLength(); i++) {
+        if(entities[i] == e) {
+            entities.removeBySwap(i);
+            return;
+        }
+    }
+}
+
+static List<Box> getBoxes(const Box& box) {
+    int minX = floorf(box.getMin()[0]);
+    int minY = floorf(box.getMin()[1]);
+    int minZ = floorf(box.getMin()[2]);
+    int maxX = floorf(box.getMax()[0]);
+    int maxY = floorf(box.getMax()[1]);
+    int maxZ = floorf(box.getMax()[2]);
+
+    List<Box> boxes;
+    for(int x = minX; x <= maxX; x++) {
+        for(int y = minY; y <= maxY; y++) {
+            for(int z = minZ; z <= maxZ; z++) {
+                Block::addBoxes(blocks.get(x, y, z), boxes,
+                                Vector3(static_cast<float>(x),
+                                        static_cast<float>(y),
+                                        static_cast<float>(z)));
+            }
+        }
+    }
+    return boxes;
+}
+
+static Vector3 limitMove(const Entity& e, Vector3 move) {
+    Box box = e.getBox();
+    List<Box> boxes = getBoxes(box.expand(move));
+    if(boxes.getLength() == 0) {
+        return move;
+    }
+    Vector3 realMove;
+
+    constexpr float step = 0.05f;
+    while(move[0] != 0.0f || move[1] != 0.0f || move[2] != 0.0f) {
+        for(int i = 0; i < 3; i++) {
+            Vector3 old = realMove;
+            if(move[i] > step) {
+                realMove[i] += step;
+                move[i] -= step;
+            } else if(move[i] < -step) {
+                realMove[i] -= step;
+                move[i] += step;
+            } else if(move[i] != 0.0f) {
+                realMove[i] += move[i];
+                move[i] = 0.0f;
+            }
+            Box moved = box.offset(realMove);
+            for(const Box& box : boxes) {
+                if(box.collidesWith(moved)) {
+                    move[i] = 0.0f;
+                    realMove = old;
+                    break;
+                }
+            }
+        }
+    }
+    return realMove;
+}
+
+void World::tick() {
+    for(Entity* e : entities) {
+        e->tick();
+        if(!e->skip) {
+            Vector3 move = limitMove(*e, e->getVelocity());
+            e->move(move);
+        }
+    }
+}
+
+static bool isAir(int x, int y, int z) {
+    return blocks.get(x, y, z) == 0;
+}
+
+static void addCube(TypedBuffer<Triangle>& buffer, float x, float y, float z) {
+    Vector3 v000(x, y, z);
+    Vector3 v001(x, y, z + 1);
+    Vector3 v010(x, y + 1, z);
+    Vector3 v011(x, y + 1, z + 1);
+    Vector3 v100(x + 1, y, z);
+    Vector3 v101(x + 1, y, z + 1);
+    Vector3 v110(x + 1, y + 1, z);
+    Vector3 v111(x + 1, y + 1, z + 1);
+
+    Vector2 t1(0.1875f, 0.0f);
+    Vector2 t2(0.25f, 0.0f);
+    Vector2 t3(0.25f, 0.0625f);
+    Vector2 t4(0.1875f, 0.0625f);
+
+    if(isAir(x, y - 1, z)) {
+        Vector2 tb(0.125f, 0.0625f);
+        buffer.add(Triangle(Vertex(v000, Vector2(0.125f, 0.0f)),
+                            Vertex(v100, t1), Vertex(v001, tb)));
+        buffer.add(
+            Triangle(Vertex(v100, t1), Vertex(v101, t4), Vertex(v001, tb)));
+    }
+    if(isAir(x, y + 1, z)) {
+        Vector2 tt(0.3125f, 0.0f);
+        buffer.add(
+            Triangle(Vertex(v010, t2), Vertex(v011, t3), Vertex(v110, tt)));
+        buffer.add(Triangle(Vertex(v110, tt), Vertex(v011, t3),
+                            Vertex(v111, Vector2(0.3125f, 0.0625f))));
+    }
+    if(isAir(x - 1, y, z)) {
+        buffer.add(
+            Triangle(Vertex(v000, t4), Vertex(v001, t3), Vertex(v010, t1)));
+        buffer.add(
+            Triangle(Vertex(v001, t3), Vertex(v011, t2), Vertex(v010, t1)));
+    }
+    if(isAir(x + 1, y, z)) {
+        buffer.add(
+            Triangle(Vertex(v100, t3), Vertex(v110, t2), Vertex(v101, t4)));
+        buffer.add(
+            Triangle(Vertex(v101, t4), Vertex(v110, t2), Vertex(v111, t1)));
+    }
+    if(isAir(x, y, z + 1)) {
+        buffer.add(
+            Triangle(Vertex(v001, t4), Vertex(v101, t3), Vertex(v011, t1)));
+        buffer.add(
+            Triangle(Vertex(v111, t2), Vertex(v011, t1), Vertex(v101, t3)));
+    }
+    if(isAir(x, y, z - 1)) {
+        buffer.add(
+            Triangle(Vertex(v000, t3), Vertex(v010, t2), Vertex(v100, t4)));
+        buffer.add(
+            Triangle(Vertex(v110, t1), Vertex(v100, t4), Vertex(v010, t2)));
+    }
+}
+
+static void rebuildRenderData() {
+    TypedBuffer<Triangle> buffer(100);
+    for(int x = 0; x < blocks.getSize(); x++) {
+        for(int y = 0; y < blocks.getHeight(); y++) {
+            for(int z = 0; z < blocks.getSize(); z++) {
+                if(!isAir(x, y, z)) {
+                    addCube(buffer, x, y, z);
+                }
+            }
+        }
+    }
+    mesh.build(buffer);
+    LOG_DEBUG("world render update");
+}
+
+void World::render() {
+    if(dirty) {
+        rebuildRenderData();
+        dirty = false;
+    }
+    texture.bindTo(0);
+    for(int x = -1; x <= 1; x++) {
+        for(int z = -1; z <= 1; z++) {
+            Engine::matrix
+                .translateTo(blocks.getSize() * x, 0.0f, blocks.getSize() * z)
+                .update();
+            mesh.draw();
+        }
+    }
+}
+
+int World::getHeight() {
+    return blocks.getHeight();
+}
+
+void World::setBlock(int x, int y, int z, Block::Id block) {
+    dirty = true;
+    blocks.set(x, y, z, block);
+}

+ 20 - 0
client/World.h

@@ -0,0 +1,20 @@
+#ifndef WORLD_H
+#define WORLD_H
+
+#include "common/Block.h"
+#include "common/entities/Entity.h"
+
+namespace World {
+    bool init();
+    void render();
+
+    void addEntity(Entity* e);
+    void removeEntity(Entity* e);
+
+    void tick();
+
+    int getHeight();
+    void setBlock(int x, int y, int z, Block::Id block);
+}
+
+#endif

+ 5 - 4
client/packets/WorldPackets.cpp

@@ -1,9 +1,11 @@
 #include "client/packets/WorldPackets.h"
 #include "client/Game.h"
+#include "client/World.h"
+#include "common/BlockStorage.h"
 #include "common/network/Packets.h"
 #include "utils/Logger.h"
 
-void WorldPackets::receiveChunk(World& w, InPacket& in) {
+void WorldPackets::receiveChunk(InPacket& in) {
     LOG_DEBUG("received chunk from server");
     int32 ox;
     int32 oz;
@@ -13,17 +15,16 @@ void WorldPackets::receiveChunk(World& w, InPacket& in) {
     }
     uint16 counter = 0;
     Block::Id b = 0;
-    for(int y = 0; y < w.blocks.getHeight(); y++) {
+    for(int y = 0; y < World::getHeight(); y++) {
         for(int x = 0; x < BlockStorage::SEGMENT; x++) {
             for(int z = 0; z < BlockStorage::SEGMENT; z++) {
                 if(counter == 0 && (in.readU16(b) || in.readU16(counter))) {
                     LOG_WARNING("missing block data in packet");
                     return;
                 }
-                w.blocks.set(ox + x, y, oz + z, b);
+                World::setBlock(ox + x, y, oz + z, b);
                 counter--;
             }
         }
     }
-    w.dirty = true;
 }

+ 1 - 2
client/packets/WorldPackets.h

@@ -1,11 +1,10 @@
 #ifndef WORLD_PACKETS_H
 #define WORLD_PACKETS_H
 
-#include "common/world/World.h"
 #include "network/Packet.h"
 
 namespace WorldPackets {
-    void receiveChunk(World& w, InPacket& in);
+    void receiveChunk(InPacket& in);
 }
 
 #endif

+ 0 - 103
client/rendering/renderer/WorldRenderer.cpp

@@ -1,103 +0,0 @@
-#include "client/rendering/renderer/WorldRenderer.h"
-#include "client/rendering/Engine.h"
-#include "utils/Logger.h"
-
-WorldRenderer::WorldRenderer(const World& world) : world(world) {
-}
-
-bool WorldRenderer::init() {
-    mesh.init();
-    Error error = texture.load("resources/textures.png", 4);
-    if(error.has()) {
-        LOG_ERROR(error.message);
-    }
-    return error.has();
-}
-
-void WorldRenderer::render() {
-    if(world.dirty) {
-        TypedBuffer<Triangle> buffer(100);
-        for(int x = 0; x < world.blocks.getSize(); x++) {
-            for(int y = 0; y < world.blocks.getHeight(); y++) {
-                for(int z = 0; z < world.blocks.getSize(); z++) {
-                    if(world.blocks.get(x, y, z) != 0) {
-                        addCube(buffer, x, y, z);
-                    }
-                }
-            }
-        }
-        mesh.build(buffer);
-        world.dirty = false;
-        LOG_DEBUG("world render update");
-    }
-    texture.bindTo(0);
-    for(int x = -1; x <= 1; x++) {
-        for(int z = -1; z <= 1; z++) {
-            Engine::matrix
-                .translateTo(world.blocks.getSize() * x, 0.0f,
-                             world.blocks.getSize() * z)
-                .update();
-            mesh.draw();
-        }
-    }
-}
-
-bool WorldRenderer::isAir(int x, int y, int z) const {
-    return world.blocks.get(x, y, z) == 0;
-}
-
-void WorldRenderer::addCube(TypedBuffer<Triangle>& buffer, float x, float y,
-                            float z) {
-    Vector3 v000(x, y, z);
-    Vector3 v001(x, y, z + 1);
-    Vector3 v010(x, y + 1, z);
-    Vector3 v011(x, y + 1, z + 1);
-    Vector3 v100(x + 1, y, z);
-    Vector3 v101(x + 1, y, z + 1);
-    Vector3 v110(x + 1, y + 1, z);
-    Vector3 v111(x + 1, y + 1, z + 1);
-
-    Vector2 t1(0.1875f, 0.0f);
-    Vector2 t2(0.25f, 0.0f);
-    Vector2 t3(0.25f, 0.0625f);
-    Vector2 t4(0.1875f, 0.0625f);
-
-    if(isAir(x, y - 1, z)) {
-        Vector2 tb(0.125f, 0.0625f);
-        buffer.add(Triangle(Vertex(v000, Vector2(0.125f, 0.0f)),
-                            Vertex(v100, t1), Vertex(v001, tb)));
-        buffer.add(
-            Triangle(Vertex(v100, t1), Vertex(v101, t4), Vertex(v001, tb)));
-    }
-    if(isAir(x, y + 1, z)) {
-        Vector2 tt(0.3125f, 0.0f);
-        buffer.add(
-            Triangle(Vertex(v010, t2), Vertex(v011, t3), Vertex(v110, tt)));
-        buffer.add(Triangle(Vertex(v110, tt), Vertex(v011, t3),
-                            Vertex(v111, Vector2(0.3125f, 0.0625f))));
-    }
-    if(isAir(x - 1, y, z)) {
-        buffer.add(
-            Triangle(Vertex(v000, t4), Vertex(v001, t3), Vertex(v010, t1)));
-        buffer.add(
-            Triangle(Vertex(v001, t3), Vertex(v011, t2), Vertex(v010, t1)));
-    }
-    if(isAir(x + 1, y, z)) {
-        buffer.add(
-            Triangle(Vertex(v100, t3), Vertex(v110, t2), Vertex(v101, t4)));
-        buffer.add(
-            Triangle(Vertex(v101, t4), Vertex(v110, t2), Vertex(v111, t1)));
-    }
-    if(isAir(x, y, z + 1)) {
-        buffer.add(
-            Triangle(Vertex(v001, t4), Vertex(v101, t3), Vertex(v011, t1)));
-        buffer.add(
-            Triangle(Vertex(v111, t2), Vertex(v011, t1), Vertex(v101, t3)));
-    }
-    if(isAir(x, y, z - 1)) {
-        buffer.add(
-            Triangle(Vertex(v000, t3), Vertex(v010, t2), Vertex(v100, t4)));
-        buffer.add(
-            Triangle(Vertex(v110, t1), Vertex(v100, t4), Vertex(v010, t2)));
-    }
-}

+ 0 - 22
client/rendering/renderer/WorldRenderer.h

@@ -1,22 +0,0 @@
-#ifndef WORLDRENDERER_H
-#define WORLDRENDERER_H
-
-#include "client/rendering/Mesh.h"
-#include "common/world/World.h"
-#include "rendering/FileTexture.h"
-
-class WorldRenderer {
-    const World& world;
-    Mesh mesh;
-    FileTexture texture;
-
-public:
-    WorldRenderer(const World& world);
-    bool init();
-
-    void render();
-    void addCube(TypedBuffer<Triangle>& buffer, float x, float y, float z);
-    bool isAir(int x, int y, int z) const;
-};
-
-#endif

+ 1 - 1
common/world/BlockStorage.cpp → common/BlockStorage.cpp

@@ -1,4 +1,4 @@
-#include "common/world/BlockStorage.h"
+#include "common/BlockStorage.h"
 
 static constexpr Block::Id EMPTY_BLOCK = 65535;
 

+ 0 - 0
common/world/BlockStorage.h → common/BlockStorage.h


+ 3 - 4
meson.build

@@ -2,8 +2,7 @@ project('cubes plus plus', 'cpp')
 
 src_common = [
     'common/Block.cpp', 
-    'common/world/BlockStorage.cpp',
-    'common/world/World.cpp', 
+    'common/BlockStorage.cpp',
     'common/Box.cpp',
     'common/entities/Entity.cpp',
     'common/network/toserver/PlayerUpdatePacket.cpp',
@@ -12,10 +11,10 @@ src_common = [
 
 src_server = ['server/Main.cpp',
     'server/Game.cpp',
+    'server/World.cpp', 
     'server/commands/Commands.cpp',
     'server/commands/DefaultCommands.cpp',
     'server/commands/SnuviCommands.cpp',
-    'server/world/WorldGenerator.cpp',
     'server/snuviscript/Snuvi.cpp',
     'server/GameServer.cpp',
     'server/entities/ServerPlayer.cpp',
@@ -29,11 +28,11 @@ src_client = ['client/Main.cpp',
     'client/rendering/Mesh.cpp',
     'client/Game.cpp',
     'client/GameClient.cpp',
+    'client/World.cpp', 
     'client/rendering/ShaderMatrix.cpp',
     'client/rendering/NoiseTexture.cpp',
     'client/input/Controller.cpp',
     'client/rendering/Renderer.cpp',
-    'client/rendering/renderer/WorldRenderer.cpp',
     'client/rendering/Vertex.cpp',
     'client/rendering/Triangle.cpp',
     'client/gui/BaseGUI.cpp',

+ 0 - 2
server/Game.cpp

@@ -5,7 +5,6 @@
 #include "raw-terminal/RawReader.h"
 #include "server/GameServer.h"
 #include "server/packets/WorldPackets.h"
-#include "server/world/WorldGenerator.h"
 #include "utils/List.h"
 #include "utils/Logger.h"
 
@@ -25,7 +24,6 @@ bool Game::isRunning() {
 
 void Game::init() {
     Block::init();
-    WorldGenerator::generate(world);
 }
 
 static void handleCommands() {

+ 1 - 1
server/Game.h

@@ -1,7 +1,7 @@
 #ifndef GAMESERVER_H
 #define GAMESERVER_H
 
-#include "common/world/World.h"
+#include "server/World.h"
 #include "server/entities/ServerPlayer.h"
 #include "utils/Clock.h"
 

+ 10 - 2
common/world/World.cpp → server/World.cpp

@@ -1,10 +1,18 @@
 #include <cmath>
 
-#include "common/world/World.h"
+#include "server/World.h"
 #include "utils/Logger.h"
 #include "utils/Random.h"
 
-World::World() : blocks(7, 7), dirty(true) {
+World::World() : blocks(7, 7) {
+    for(int x = 0; x < blocks.getSize(); x++) {
+        for(int z = 0; z < blocks.getSize(); z++) {
+            int height = sinf(x * 0.25f) * 2.0f + cosf(z * 0.25f) * 2.0f + 6.0f;
+            for(int y = 0; y < height; y++) {
+                blocks.set(x, y, z, 1);
+            }
+        }
+    }
 }
 
 void World::addEntity(Entity* e) {

+ 1 - 2
common/world/World.h → server/World.h

@@ -1,8 +1,8 @@
 #ifndef WORLD_H
 #define WORLD_H
 
+#include "common/BlockStorage.h"
 #include "common/entities/Entity.h"
-#include "common/world/BlockStorage.h"
 #include "utils/List.h"
 
 class World final {
@@ -10,7 +10,6 @@ class World final {
 
 public:
     BlockStorage blocks;
-    mutable bool dirty;
 
     World();
 

+ 1 - 1
server/packets/WorldPackets.h

@@ -1,7 +1,7 @@
 #ifndef WORLD_PACKETS_H
 #define WORLD_PACKETS_H
 
-#include "common/world/World.h"
+#include "server/World.h"
 #include "server/entities/ServerPlayer.h"
 
 namespace WorldPackets {

+ 0 - 14
server/world/WorldGenerator.cpp

@@ -1,14 +0,0 @@
-#include <cmath>
-
-#include "server/world/WorldGenerator.h"
-
-void WorldGenerator::generate(World& w) {
-    for(int x = 0; x < w.blocks.getSize(); x++) {
-        for(int z = 0; z < w.blocks.getSize(); z++) {
-            int height = sinf(x * 0.25f) * 2.0f + cosf(z * 0.25f) * 2.0f + 6.0f;
-            for(int y = 0; y < height; y++) {
-                w.blocks.set(x, y, z, 1);
-            }
-        }
-    }
-}

+ 0 - 10
server/world/WorldGenerator.h

@@ -1,10 +0,0 @@
-#ifndef WORLD_GENERATOR_H
-#define WORLD_GENERATOR_H
-
-#include "common/world/World.h"
-
-namespace WorldGenerator {
-    void generate(World& world);
-}
-
-#endif