Skip to content

Commit

Permalink
Infinite world: First attempt.
Browse files Browse the repository at this point in the history
  • Loading branch information
Unarelith committed Jan 15, 2020
1 parent 2f790ec commit 959313e
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 210 deletions.
8 changes: 4 additions & 4 deletions client/include/world/ClientWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#ifndef CLIENTWORLD_HPP_
#define CLIENTWORLD_HPP_

#include <memory>
#include <unordered_map>

#include "ClientChunk.hpp"
#include "Network.hpp"
Expand All @@ -36,16 +36,16 @@ class ClientWorld : public World, public gk::Drawable {

// FIXME: Duplicated with ServerWorld
u16 getBlock(int x, int y, int z) const override;
void setBlock(int x, int y, int z, u16 id) override;
void setBlock(int x, int y, int z, u16 id) const override;
u16 getData(int x, int y, int z) const override;
void setData(int x, int y, int z, u16 id) override;
void setData(int x, int y, int z, u16 id) const override;

void setClient(ClientCommandHandler &client) { m_client = &client; }

private:
void draw(gk::RenderTarget &target, gk::RenderStates states) const override;

std::vector<std::unique_ptr<ClientChunk>> m_chunks;
mutable std::unordered_map<gk::Vector3i, std::unique_ptr<ClientChunk>> m_chunks;

gk::Texture &m_texture;

Expand Down
121 changes: 31 additions & 90 deletions client/source/world/ClientWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,14 @@
#include "World.hpp"

ClientWorld::ClientWorld() : m_texture(gk::ResourceHandler::getInstance().get<gk::Texture>("texture-blocks")) {
for(s32 z = 0 ; z < m_depth ; z++) {
for(s32 y = 0 ; y < m_height ; y++) {
for(s32 x = 0 ; x < m_width ; x++) {
m_chunks.emplace_back(new ClientChunk(x - m_width / 2,
y - m_height / 2,
z - m_depth / 2, m_texture));
}
}
}

// FIXME: Duplicated with ServerWorld
for(s32 z = 0 ; z < m_depth ; ++z) {
for(s32 y = 0 ; y < m_height ; ++y) {
for(s32 x = 0 ; x < m_width ; ++x) {
s32 cx = x - m_width / 2;
s32 cy = y - m_height / 2;
s32 cz = z - m_depth / 2;

Chunk *chunk = getChunk(cx, cy, cz);
if(cx > -m_width / 2) chunk->setSurroundingChunk(Chunk::Left, getChunk(cx - 1, cy, cz));
if(cx < m_width / 2 - 1) chunk->setSurroundingChunk(Chunk::Right, getChunk(cx + 1, cy, cz));
if(cy > -m_height / 2) chunk->setSurroundingChunk(Chunk::Bottom, getChunk(cx, cy - 1, cz));
if(cy < m_height / 2 - 1) chunk->setSurroundingChunk(Chunk::Top, getChunk(cx, cy + 1, cz));
if(cz > -m_depth / 2) chunk->setSurroundingChunk(Chunk::Front, getChunk(cx, cy, cz - 1));
if(cz < m_depth / 2 - 1) chunk->setSurroundingChunk(Chunk::Back, getChunk(cx, cy, cz + 1));
}
}
}
}

void ClientWorld::update() {
for (auto &it : m_chunks) {
if (World::isReloadRequested)
it->setChanged(true);
it.second->setChanged(true);

it->update();
it.second->update();
}

World::isReloadRequested = false;
Expand Down Expand Up @@ -97,82 +69,47 @@ void ClientWorld::receiveChunkData(sf::Packet &packet) {
}

ClientChunk *ClientWorld::getChunk(int cx, int cy, int cz) const {
cx += m_width / 2;
cy += m_height / 2;
cz += m_depth / 2;

if (cx < 0 || cx >= m_width || cy < 0 || cy >= m_height || cz < 0 || cz >= m_depth)
auto it = m_chunks.find({cx, cy, cz});
if (it == m_chunks.end())
return nullptr;

return m_chunks.at(cx + cy * m_width + cz * m_width * m_height).get();
return it->second.get();
}

BlockData *ClientWorld::getBlockData(int x, int y, int z) const {
int cx = (x + CHUNK_WIDTH * (m_width / 2)) / CHUNK_WIDTH;
int cy = (y + CHUNK_HEIGHT * (m_height / 2)) / CHUNK_HEIGHT;
int cz = (z + CHUNK_DEPTH * (m_depth / 2)) / CHUNK_DEPTH;

if (cx < 0 || cx >= m_width || cy < 0 || cy >= m_height || cz < 0 || cz >= m_depth)
return 0;

Chunk *chunk = m_chunks.at(cx + cy * m_width + cz * m_width * m_height).get();
Chunk *chunk = getChunk(x / CHUNK_WIDTH, y / CHUNK_HEIGHT, z / CHUNK_DEPTH);
if (chunk)
return chunk->getBlockData(x & (CHUNK_WIDTH - 1), y & (CHUNK_HEIGHT - 1), z & (CHUNK_DEPTH - 1));
return 0;

return nullptr;
}

u16 ClientWorld::getBlock(int x, int y, int z) const {
int cx = (x + CHUNK_WIDTH * (m_width / 2)) / CHUNK_WIDTH;
int cy = (y + CHUNK_HEIGHT * (m_height / 2)) / CHUNK_HEIGHT;
int cz = (z + CHUNK_DEPTH * (m_depth / 2)) / CHUNK_DEPTH;

if (cx < 0 || cx >= m_width || cy < 0 || cy >= m_height || cz < 0 || cz >= m_depth)
return 0;

ClientChunk *chunk = m_chunks.at(cx + cy * m_width + cz * m_width * m_height).get();
Chunk *chunk = getChunk(x / CHUNK_WIDTH, y / CHUNK_HEIGHT, z / CHUNK_DEPTH);
if (chunk)
return chunk->getBlock(x & (CHUNK_WIDTH - 1), y & (CHUNK_HEIGHT - 1), z & (CHUNK_DEPTH - 1));

return 0;
}

void ClientWorld::setBlock(int x, int y, int z, u16 id) {
int cx = (x + CHUNK_WIDTH * (m_width / 2)) / CHUNK_WIDTH;
int cy = (y + CHUNK_HEIGHT * (m_height / 2)) / CHUNK_HEIGHT;
int cz = (z + CHUNK_DEPTH * (m_depth / 2)) / CHUNK_DEPTH;

if (cx < 0 || cx >= m_width || cy < 0 || cy >= m_height || cz < 0 || cz >= m_depth)
return;

ClientChunk *chunk = m_chunks.at(cx + cy * m_width + cz * m_width * m_height).get();
void ClientWorld::setBlock(int x, int y, int z, u16 id) const {
Chunk *chunk = getChunk(x / CHUNK_WIDTH, y / CHUNK_HEIGHT, z / CHUNK_DEPTH);
if (chunk)
chunk->setBlock(x & (CHUNK_WIDTH - 1), y & (CHUNK_HEIGHT - 1), z & (CHUNK_DEPTH - 1), id);
}

u16 ClientWorld::getData(int x, int y, int z) const {
int cx = (x + CHUNK_WIDTH * (m_width / 2)) / CHUNK_WIDTH;
int cy = (y + CHUNK_HEIGHT * (m_height / 2)) / CHUNK_HEIGHT;
int cz = (z + CHUNK_DEPTH * (m_depth / 2)) / CHUNK_DEPTH;

if (cx < 0 || cx >= m_width || cy < 0 || cy >= m_height || cz < 0 || cz >= m_depth)
return 0;

ClientChunk *chunk = m_chunks.at(cx + cy * m_width + cz * m_width * m_height).get();
Chunk *chunk = getChunk(x / CHUNK_WIDTH, y / CHUNK_HEIGHT, z / CHUNK_DEPTH);
if (chunk)
return chunk->getData(x & (CHUNK_WIDTH - 1), y & (CHUNK_HEIGHT - 1), z & (CHUNK_DEPTH - 1));

return 0;
}

void ClientWorld::setData(int x, int y, int z, u16 id) {
int cx = (x + CHUNK_WIDTH * (m_width / 2)) / CHUNK_WIDTH;
int cy = (y + CHUNK_HEIGHT * (m_height / 2)) / CHUNK_HEIGHT;
int cz = (z + CHUNK_DEPTH * (m_depth / 2)) / CHUNK_DEPTH;

if (cx < 0 || cx >= m_width || cy < 0 || cy >= m_height || cz < 0 || cz >= m_depth)
return;

ClientChunk *chunk = m_chunks.at(cx + cy * m_width + cz * m_width * m_height).get();
void ClientWorld::setData(int x, int y, int z, u16 id) const {
Chunk *chunk = getChunk(x / CHUNK_WIDTH, y / CHUNK_HEIGHT, z / CHUNK_DEPTH);
if (chunk)
chunk->setData(x & (CHUNK_WIDTH - 1), y & (CHUNK_HEIGHT - 1), z & (CHUNK_DEPTH - 1), id);
chunk->setBlock(x & (CHUNK_WIDTH - 1), y & (CHUNK_HEIGHT - 1), z & (CHUNK_DEPTH - 1), id);
}

void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const {
Expand All @@ -193,9 +130,9 @@ void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const
std::vector<std::pair<ClientChunk*, gk::Transform>> chunks;
for(auto &it : m_chunks) {
states.transform = glm::translate(glm::mat4(1.0f),
glm::vec3(it->x() * CHUNK_WIDTH,
it->y() * CHUNK_HEIGHT,
it->z() * CHUNK_DEPTH));
glm::vec3(it.second->x() * CHUNK_WIDTH,
it.second->y() * CHUNK_HEIGHT,
it.second->z() * CHUNK_DEPTH));

// Is the chunk close enough?
glm::vec4 center = target.getView()->getViewTransform().getMatrix()
Expand Down Expand Up @@ -225,25 +162,29 @@ void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const
}

// If this chunk is not initialized, skip it
if(!it->isInitialized()) {
if(!it.second->isInitialized()) {
// But if it is the closest to the camera, mark it for initialization
if(d < ud) {
ud = d;
ux = it->x();
uy = it->y();
uz = it->z();
ux = it.second->x();
uy = it.second->y();
uz = it.second->z();
}

continue;
}

chunks.emplace_back(&*it, states.transform);
chunks.emplace_back(it.second.get(), states.transform);
}

ClientChunk *chunk = getChunk(ux, uy, uz);
if(ud < 1000 && chunk && !chunk->hasBeenRequested()) {
if(ud <= 1000 && (!chunk || !chunk->hasBeenRequested())) {
auto it = m_chunks.emplace(gk::Vector3i(ux, uy, uz), new ClientChunk(ux, uy, uz, m_texture));
it.first->second->setHasBeenRequested(true);

m_client->sendChunkRequest(ux, uy, uz);
chunk->setHasBeenRequested(true);

DEBUG("Chunk requested at", ux, uy, uz);
}

for (u8 i = 0 ; i < ChunkBuilder::layers ; ++i) {
Expand Down
4 changes: 0 additions & 4 deletions common/include/core/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ namespace {
constexpr int CHUNK_HEIGHT = 32;
constexpr int CHUNK_DEPTH = 16;

constexpr int WORLD_WIDTH = 64;
constexpr int WORLD_HEIGHT = 4;
constexpr int WORLD_DEPTH = 64;

constexpr int SEALEVEL = 4;
}

Expand Down
9 changes: 2 additions & 7 deletions common/include/world/World.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,11 @@ class World {
virtual BlockData *getBlockData(int x, int y, int z) const = 0;

virtual u16 getBlock(int x, int y, int z) const = 0;
virtual void setBlock(int x, int y, int z, u16 id) = 0;
virtual void setBlock(int x, int y, int z, u16 id) const = 0;
virtual u16 getData(int x, int y, int z) const = 0;
virtual void setData(int x, int y, int z, u16 id) = 0;
virtual void setData(int x, int y, int z, u16 id) const = 0;

static bool isReloadRequested;

protected:
const s32 m_width = WORLD_WIDTH;
const s32 m_height = WORLD_HEIGHT;
const s32 m_depth = WORLD_DEPTH;
};

#endif // WORLD_HPP_
10 changes: 4 additions & 6 deletions server/include/world/ServerWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
#ifndef SERVERWORLD_HPP_
#define SERVERWORLD_HPP_

#include <memory>
#include <vector>
#include <unordered_map>

#include "ServerChunk.hpp"
#include "World.hpp"
Expand All @@ -30,7 +29,6 @@ class ServerWorld : public World {

void update(Server &server, std::unordered_map<u16, ServerPlayer> &players);

void sendWorldData(Client &client);
void sendChunkData(Client &client, ServerChunk *chunk);
void sendRequestedData(Client &client, int cx, int cy, int cz);

Expand All @@ -40,12 +38,12 @@ class ServerWorld : public World {

// FIXME: Duplicated with ClientWorld
u16 getBlock(int x, int y, int z) const override;
void setBlock(int x, int y, int z, u16 id) override;
void setBlock(int x, int y, int z, u16 id) const override;
u16 getData(int x, int y, int z) const override;
void setData(int x, int y, int z, u16 id) override;
void setData(int x, int y, int z, u16 id) const override;

private:
std::vector<std::unique_ptr<ServerChunk>> m_chunks;
std::unordered_map<gk::Vector3i, std::unique_ptr<ServerChunk>> m_chunks;

u32 m_lastTick = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion server/source/network/ServerCommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void ServerCommandHandler::setupCallbacks() {
spawnPacket << m_spawnPosition.x << m_spawnPosition.y << m_spawnPosition.z;
m_server.sendToAllClients(spawnPacket);

// m_world.sendWorldData(client);
// m_world.sendWorldData(client); // FIXME

sf::Packet worldSentPacket;
worldSentPacket << Network::Command::WorldSent;
Expand Down
Loading

0 comments on commit 959313e

Please sign in to comment.