Various shit.

master
Nicole Collings 2020-04-06 17:18:57 -07:00
parent 4febca7ef8
commit a59e1d2a82
51 changed files with 875 additions and 549 deletions

View File

@ -1,8 +1,8 @@
-- Register base models (if not on main menu)
if zepha.register_blockmodel then runfile(_PATH .. "models/_index") end
-- Load Libraries
runfile(_PATH .. "dump")
runfile(_PATH .. "math")
runfile(_PATH .. "vector")
runfile(_PATH .. "gui")
runfile(_PATH .. "gui")
-- Register base models (if not on main menu)
if zepha.register_blockmodel then runfile(_PATH .. "models/_index") end

View File

@ -10,9 +10,9 @@ set(ZEPHA_SRC
game/graph/Camera.cpp
game/graph/Camera.h
game/graph/Texture.cpp
game/graph/Texture.h
game/scene/world/graph/MeshGenerator.cpp
game/scene/world/graph/MeshGenerator.h
game/graph/Texture.h
game/scene/world/graph/ChunkMeshGenerator.cpp
game/scene/world/graph/ChunkMeshGenerator.h
util/Timer.cpp
util/Timer.h
def/LocalDefinitionAtlas.cpp
@ -81,9 +81,9 @@ set(ZEPHA_SRC
game/graph/frustum/FrustumAABB.cpp
game/graph/frustum/FrustumAABB.h
server/world/ServerWorld.cpp
server/world/ServerWorld.h
server/world/WorldGenStream.cpp
server/world/WorldGenStream.h
server/world/ServerWorld.h
server/world/ServerGenStream.cpp
server/world/ServerGenStream.h
game/scene/world/WorldInterpolationStream.cpp
game/scene/world/WorldInterpolationStream.h
util/Space.h
@ -143,8 +143,8 @@ set(ZEPHA_SRC
game/scene/ConnectScene.h
util/net/Address.h
game/scene/net/ServerConnection.cpp
game/scene/net/ServerConnection.h
game/scene/world/MeshDetails.h
game/scene/net/ServerConnection.h
game/scene/world/ChunkMeshDetails.h
game/hud/components/GuiComponent.cpp
game/hud/components/GuiComponent.h
game/hud/components/basic/GuiContainer.cpp
@ -320,6 +320,6 @@ set(ZEPHA_SRC
game/inventory/InventoryList.h
lua/api/modules/time.h
util/net/PacketView.cpp
util/net/PacketView.h lua/api/modules/create_structure.h util/Any.h)
util/net/PacketView.h lua/api/modules/create_structure.h util/Any.h game/scene/world/graph/MeshFarMap.cpp game/scene/world/graph/MeshFarMap.h def/gen/MapGenProps.cpp def/gen/MapGenProps.h def/gen/FarMapGen.cpp def/gen/FarMapGen.h def/gen/FarMapJob.h game/scene/world/graph/FarMeshGenerator.cpp game/scene/world/graph/FarMeshGenerator.h game/scene/world/FarMapMeshDetails.h)
add_library (Zepha_Core ${ZEPHA_SRC})

View File

@ -4,10 +4,11 @@
#pragma once
#include "LocalDefinitionAtlas.h"
#include "gen/LocalBiomeAtlas.h"
#include "gen/MapGenProps.h"
#include "model/ModelStore.h"
#include "gen/LocalBiomeAtlas.h"
#include "texture/TextureAtlas.h"
#include "LocalDefinitionAtlas.h"
#include "../lua/parser/LocalLuaParser.h"
class ClientGame {

View File

@ -5,8 +5,9 @@
#include "ServerGame.h"
#include "../server/conn/ClientList.h"
ServerGame::ServerGame(const std::string& subgame) :
subgamePath("subgames/" + subgame + "/") {
ServerGame::ServerGame(const std::string& subgame, unsigned int seed) :
subgamePath("subgames/" + subgame + "/"),
biomes(seed) {
if (subgame.empty()) {
std::cout << Log::err << "No subgame specified." << Log::endl;

View File

@ -15,7 +15,7 @@ class ClientList;
class ServerGame {
public:
ServerGame(const std::string& subgame);
ServerGame(const std::string& subgame, unsigned int seed);
void init(ServerWorld& world);
void update(double delta, ClientList& clients);

55
src/def/gen/FarMapGen.cpp Normal file
View File

@ -0,0 +1,55 @@
//
// Created by aurailus on 2020-04-05.
//
#include "FarMapGen.h"
FarMapGen::FarMapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes, std::shared_ptr<MapGenProps> props) :
seed(seed),
defs(defs),
props(props),
biomes(biomes) {}
MeshFarMap FarMapGen::generateFarMap(glm::ivec3 mbPos, unsigned short downScale) {
auto job = new FarMapJob();
job->downScale = downScale;
buildDensityMap(job, mbPos);
delete job;
}
void FarMapGen::buildDensityMap(FarMapJob *job, glm::ivec3 mbPos) {
job->temperature = {}; job->humidity = {}; job->roughness = {};
job->temperature.fill([&](glm::ivec3 pos) {
return props->temperature.GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f); }, 4);
job->humidity.fill([&](glm::ivec3 pos) {
return props->humidity.GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f); }, 4);
job->roughness.fill([&](glm::ivec3 pos) {
return props->roughness.GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f); }, 4);
NoiseSample volume = {}, heightmap = {};
volume.fill([&](glm::ivec3 pos) {
auto& biome = biomes.getBiomeAt(job->temperature.get(pos), job->humidity.get(pos), job->roughness.get(pos));
return biome.volume[biome.volume.size() - 1]->GetValue(mbPos.x * 4 + pos.x / 4.f, mbPos.y * 4 + pos.y / 4.f, mbPos.z * 4 + pos.z / 4.f);
}, {4, 4});
heightmap.fill([&](glm::ivec3 pos) {
auto& biome = biomes.getBiomeAt(job->temperature.get(pos), job->humidity.get(pos), job->roughness.get(pos));
return biome.heightmap[biome.heightmap.size() - 1]->GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f);
}, 4);
int sampleWid = 64 / job->downScale;
float factor = (job->downScale == 2 ? 0.5f : job->downScale == 4 ? 1 : 2);
glm::ivec3 lp;
for (int m = 0; m < pow(sampleWid, 3); m++) {
Vec::indAssignVec(m, lp, sampleWid);
job->density[m] = (volume.get(glm::vec3(lp) * factor) + heightmap.get(glm::vec3(lp) * factor)) - (static_cast<float>(lp.y) * factor + mbPos.y * 64);
}
}

36
src/def/gen/FarMapGen.h Normal file
View File

@ -0,0 +1,36 @@
//
// Created by aurailus on 2020-04-05.
//
#pragma once
#include "FarMapJob.h"
#include "BiomeAtlas.h"
#include "NoiseSample.h"
#include "MapGenProps.h"
#include "../../util/Vec.h"
#include "../DefinitionAtlas.h"
#include "../../game/scene/world/graph/MeshFarMap.h"
class FarMapGen {
FarMapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes, std::shared_ptr<MapGenProps> props);
MeshFarMap generateFarMap(glm::ivec3 mbPos, unsigned short downScale);
private:
// Build the density map for a job.
void buildDensityMap(FarMapJob* job, glm::ivec3 mbPos);
// Build the elevation map for a job.
void buildElevationMap(FarMapJob& job);
// Generate blocks and structures on a chunk, respectively. generateStructures can create partials.
// void generateBlocks(chunk_partial& chunk);
// void generateStructures(chunk_partials_map& chunks, chunk_partial& chunk);
unsigned int seed = 0;
DefinitionAtlas& defs;
BiomeAtlas& biomes;
std::shared_ptr<MapGenProps> props;
};

18
src/def/gen/FarMapJob.h Normal file
View File

@ -0,0 +1,18 @@
//
// Created by aurailus on 2020-04-05.
//
#pragma once
#include <vector>
#include <glm/vec3.hpp>
#include "NoiseSample.h"
struct FarMapJob {
std::vector<float> density {};
std::vector<float> depth {};
unsigned short downScale;
NoiseSample temperature, humidity, roughness;
};

View File

@ -8,41 +8,11 @@
#include <random>
#include <cmath>
MapGen::MapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes) :
MapGen::MapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes, std::shared_ptr<MapGenProps> props) :
seed(seed),
defs(defs),
biomes(biomes) {
temperatureBase.SetSeed(seed);
temperatureBase.SetFrequency(0.02);
temperatureBase.SetOctaveCount(4);
temperatureTurbulence.SetSourceModule(0, temperatureBase);
temperatureTurbulence.SetRoughness(4);
temperatureTurbulence.SetFrequency(0.2);
temperature.SetSourceModule(0, temperatureTurbulence);
temperature.SetScale(0.35);
temperature.SetBias(0.25);
humidityBase.SetSeed(seed + 5);
humidityBase.SetFrequency(0.02);
humidityBase.SetOctaveCount(4);
humidityTurbulence.SetSourceModule(0, humidityBase);
humidityTurbulence.SetRoughness(4);
humidityTurbulence.SetFrequency(0.2);
humidity.SetSourceModule(0, humidityTurbulence);
humidity.SetScale(0.5);
humidity.SetBias(0.5);
roughnessBase.SetSeed(seed + 10);
roughnessBase.SetFrequency(0.02);
roughnessBase.SetOctaveCount(4);
roughnessTurbulence.SetSourceModule(0, roughnessBase);
roughnessTurbulence.SetRoughness(4);
roughnessTurbulence.SetFrequency(0.2);
roughness.SetSourceModule(0, roughnessTurbulence);
roughness.SetScale(0.5);
roughness.SetBias(0.5);
}
props(props),
biomes(biomes) {}
MapGen::chunk_partials_map MapGen::generateMapBlock(glm::ivec3 mbPos) {
chunk_partials_map chunks {};
@ -84,11 +54,11 @@ void MapGen::buildDensityMap(MapGenJob* job, glm::ivec3 worldPos) {
job->temperature = {}; job->humidity = {}; job->roughness = {};
job->temperature.fill([&](glm::ivec3 pos) {
return temperature.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
return props->temperature.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
job->humidity.fill([&](glm::ivec3 pos) {
return humidity.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
return props->humidity.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
job->roughness.fill([&](glm::ivec3 pos) {
return roughness.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
return props->roughness.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
NoiseSample volume = {}, heightmap = {};

View File

@ -5,17 +5,16 @@
#pragma once
#include "MapGenJob.h"
#include "MapGenProps.h"
#include "../../util/Vec.h"
#include "../../world/chunk/BlockChunk.h"
using namespace noise;
class MapGen {
public:
typedef std::pair<MapGenJob*, BlockChunk*> chunk_partial;
typedef std::unordered_map<glm::ivec3, chunk_partial, Vec::ivec3> chunk_partials_map;
MapGen(unsigned int seed, DefinitionAtlas& atlas, BiomeAtlas& biome);
MapGen(unsigned int seed, DefinitionAtlas& atlas, BiomeAtlas& biome, std::shared_ptr<MapGenProps> props);
chunk_partials_map generateMapBlock(glm::ivec3 mbPos);
// Combine two chunk partials, or a chunk and a chunk partial.
@ -43,15 +42,5 @@ private:
DefinitionAtlas& defs;
BiomeAtlas& biomes;
module::Perlin temperatureBase;
module::Turbulence temperatureTurbulence;
module::ScaleBias temperature;
module::Perlin humidityBase;
module::Turbulence humidityTurbulence;
module::ScaleBias humidity;
module::Perlin roughnessBase;
module::Turbulence roughnessTurbulence;
module::ScaleBias roughness;
std::shared_ptr<MapGenProps> props;
};

View File

@ -5,13 +5,11 @@
#pragma once
#include <array>
#include <vector>
#include <memory>
#include <glm/vec3.hpp>
#include "NoiseSample.h"
#include "../../util/Space.h"
struct MapGenJob {
class MapGenJob {
public:
std::array<float, 4096> density {};
std::array<float, 4096> depth {};

View File

@ -0,0 +1,37 @@
//
// Created by aurailus on 2020-04-05.
//
#include "MapGenProps.h"
MapGenProps::MapGenProps(unsigned int seed) : seed(seed) {
temperatureBase.SetSeed(seed);
temperatureBase.SetFrequency(0.02);
temperatureBase.SetOctaveCount(4);
temperatureTurbulence.SetSourceModule(0, temperatureBase);
temperatureTurbulence.SetRoughness(4);
temperatureTurbulence.SetFrequency(0.2);
temperature.SetSourceModule(0, temperatureTurbulence);
temperature.SetScale(0.35);
temperature.SetBias(0.25);
humidityBase.SetSeed(seed + 5);
humidityBase.SetFrequency(0.02);
humidityBase.SetOctaveCount(4);
humidityTurbulence.SetSourceModule(0, humidityBase);
humidityTurbulence.SetRoughness(4);
humidityTurbulence.SetFrequency(0.2);
humidity.SetSourceModule(0, humidityTurbulence);
humidity.SetScale(0.5);
humidity.SetBias(0.5);
roughnessBase.SetSeed(seed + 10);
roughnessBase.SetFrequency(0.02);
roughnessBase.SetOctaveCount(4);
roughnessTurbulence.SetSourceModule(0, roughnessBase);
roughnessTurbulence.SetRoughness(4);
roughnessTurbulence.SetFrequency(0.2);
roughness.SetSourceModule(0, roughnessTurbulence);
roughness.SetScale(0.5);
roughness.SetBias(0.5);
}

28
src/def/gen/MapGenProps.h Normal file
View File

@ -0,0 +1,28 @@
//
// Created by aurailus on 2020-04-05.
//
#pragma once
#include <noise/noise.h>
using namespace noise;
class MapGenProps {
public:
MapGenProps(unsigned int seed);
unsigned int seed;
module::Perlin temperatureBase;
module::Turbulence temperatureTurbulence;
module::ScaleBias temperature;
module::Perlin humidityBase;
module::Turbulence humidityTurbulence;
module::ScaleBias humidity;
module::Perlin roughnessBase;
module::Turbulence roughnessTurbulence;
module::ScaleBias roughness;
};

View File

@ -4,7 +4,8 @@
#include "ServerBiomeAtlas.h"
ServerBiomeAtlas::ServerBiomeAtlas() {
ServerBiomeAtlas::ServerBiomeAtlas(unsigned int seed) :
seed(seed) {
//Invalid Biome
BiomeDef* invalid = new BiomeDef("invalid", INVALID, -1, -1, -1, 0, 0, 0, {}, {}, {}, {});
registerBiome(invalid);

View File

@ -9,7 +9,8 @@
class ServerBiomeAtlas : public BiomeAtlas {
public:
ServerBiomeAtlas();
ServerBiomeAtlas(unsigned int seed);
void registerBiome(BiomeDef* def) override;
unsigned int seed;
};

View File

@ -20,6 +20,8 @@ public:
ServerConnection connection {};
ClientGame defs;
unsigned int seed = 0;
std::string desiredState = "this";
double fps = 0;

View File

@ -142,5 +142,5 @@ void GuiInventoryList::drawContents() {
}
GuiInventoryList::~GuiInventoryList() {
list->setGuiCallback(nullptr);
if (list != nullptr) list->setGuiCallback(nullptr);
}

View File

@ -51,6 +51,27 @@ void ConnectScene::update() {
handleConnecting();
break;
case State::PROPERTIES: {
components.get<GuiRect>("loadBar")->setScale({state.renderer.window.getSize().x * 0.1, 32});
ENetEvent e;
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
PacketView p(e.packet);
if (p.type == PacketType::SERVER_INFO) {
auto statusText = components.get<GuiText>("statusText");
statusText->setText(statusText->getText() + "Received server properties.\n");
state.seed = p.d.read<unsigned int>();
connectState = State::IDENTIFIER_LIST;
Packet resp(PacketType::BLOCK_IDENTIFIER_LIST);
resp.sendTo(connection.getPeer(), PacketChannel::CONNECT);
}
}
break;
}
case State::IDENTIFIER_LIST: {
components.get<GuiRect>("loadBar")->setScale({state.renderer.window.getSize().x * 0.2, 32});
@ -161,7 +182,7 @@ void ConnectScene::update() {
}
void ConnectScene::handleConnecting() {
Packet resp(PacketType::BLOCK_IDENTIFIER_LIST);
Packet resp(PacketType::SERVER_INFO);
auto statusText = components.get<GuiText>("statusText");
switch (connection.getConnectionStatus()) {
@ -189,7 +210,7 @@ void ConnectScene::handleConnecting() {
break;
case ServerConnection::State::CONNECTED:
connectState = State::IDENTIFIER_LIST;
connectState = State::PROPERTIES;
statusText->setText(statusText->getText() + " Connected!~\n");
resp.sendTo(connection.getPeer(), PacketChannel::CONNECT);

View File

@ -12,6 +12,7 @@ public:
enum class State {
CONNECTING,
FAILED_CONNECT,
PROPERTIES,
IDENTIFIER_LIST,
MODS,
MEDIA,

View File

@ -8,7 +8,7 @@
#include <glm/vec3.hpp>
#include "../../graph/meshtypes/ChunkMesh.h"
struct MeshDetails {
struct ChunkMeshDetails {
std::vector<ChunkVertex> vertices;
std::vector<unsigned int> indices;

View File

@ -0,0 +1,15 @@
//
// Created by aurailus on 2020-04-06.
//
#pragma once
#include <vector>
#include <glm/vec3.hpp>
struct FarMapMeshDetails {
// std::vector<FarMapVertex> vertices;
std::vector<unsigned int> indices;
glm::vec3 pos {0, 0, 0};
};

View File

@ -38,7 +38,7 @@ void LocalWorld::update(double delta) {
}
void LocalWorld::loadChunkPacket(std::unique_ptr<PacketView> p) {
worldGenStream->pushBack(std::move(p));
worldGenStream->queuePacket(std::move(p));
}
void LocalWorld::commitChunk(std::shared_ptr<BlockChunk> c) {
@ -162,7 +162,7 @@ void LocalWorld::finishChunks() {
auto finishedChunks = worldGenStream->update();
lastGenUpdates = 0;
for (const auto &chunk : finishedChunks) {
for (const auto &chunk : *finishedChunks) {
commitChunk(chunk);
lastGenUpdates++;
}

View File

@ -6,8 +6,8 @@
#include "../../../world/LocalDimension.h"
MeshGenStream::MeshGenStream(ClientGame &defs, LocalDimension &dimension) :
defs(defs),
MeshGenStream::MeshGenStream(ClientGame& game, LocalDimension &dimension) :
game(game),
dimension(dimension) {
queuedTasks.reserve(static_cast<unsigned long>(TOTAL_QUEUE_SIZE));
@ -28,18 +28,14 @@ MeshGenStream::MeshGenStream(ClientGame &defs, LocalDimension &dimension) :
noiseSampler[2].fill([&](glm::ivec3 pos) -> float { return offsetTurbulence.GetValue(pos.x, pos.y, pos.z + 8); }, {16, 16});
threads.reserve(THREADS);
for (int i = 0; i < THREADS; i++) {
threads.emplace_back(defs, noiseSampler);
}
for (int i = 0; i < THREADS; i++) threads.emplace_back(game, noiseSampler);
}
MeshGenStream::Thread::Thread(ClientGame &defs, std::array<NoiseSample, 3>& offsetSamplers) :
defs(defs), offsetSamplers(offsetSamplers) {
thread = std::thread(MeshGenStream::threadFunction, this);
}
game(defs), offsetSamplers(offsetSamplers), thread(MeshGenStream::threadFunction, this) {}
std::vector<MeshDetails*> MeshGenStream::update() {
std::vector<MeshDetails*> finishedChunks;
std::vector<ChunkMeshDetails*> MeshGenStream::update() {
std::vector<ChunkMeshDetails*> finishedChunks;
for (Thread& t : threads) {
for (Unit& u : t.tasks) {
@ -48,7 +44,7 @@ std::vector<MeshDetails*> MeshGenStream::update() {
if (u.thisChunk != nullptr) {
u.thisChunk = nullptr;
finishedChunks.push_back(u.meshDetails);
u.meshDetails = new MeshDetails();
u.meshDetails = new ChunkMeshDetails();
}
if (!queuedTasks.empty()) {
@ -83,12 +79,11 @@ void MeshGenStream::threadFunction(MeshGenStream::Thread *thread) {
while (thread->keepAlive) {
bool hasNoTasks = true;
for (Unit& u : thread->tasks) {
for (auto i = 0; i < thread->tasks.size(); i++) {
auto& u = thread->tasks[i];
if (!u.busy) continue;
// bool hi = glm::distance(glm::vec3{0, 0, 0}, glm::vec3(u.thisChunk->pos)) < 8;
MeshGenerator m(u.meshDetails, thread->defs, u.thisChunk, u.adjacentChunks, thread->offsetSamplers, true);
ChunkMeshGenerator m(u.meshDetails, thread->game.defs, thread->game.biomes, u.thisChunk, u.adjacentChunks, thread->offsetSamplers);
hasNoTasks = false;
u.busy = false;
}

View File

@ -8,8 +8,8 @@
#include <glm/vec3.hpp>
#include <thread>
#include <unordered_set>
#include "MeshDetails.h"
#include "graph/MeshGenerator.h"
#include "ChunkMeshDetails.h"
#include "graph/ChunkMeshGenerator.h"
#include "../../../world/chunk/BlockChunk.h"
#include "../../../def/LocalDefinitionAtlas.h"
#include "../../../util/Vec.h"
@ -23,7 +23,7 @@ public:
static const int THREADS = 2;
static const int TOTAL_QUEUE_SIZE = THREADS * THREAD_QUEUE_SIZE;
explicit MeshGenStream(ClientGame& defs, LocalDimension& dimension);
explicit MeshGenStream(ClientGame& game, LocalDimension& dimension);
~MeshGenStream();
bool spaceInQueue();
@ -34,13 +34,13 @@ public:
//Will return a vector of MeshDetails pointers containing finished meshes.
//Frees up the threads and starts new tasks.
std::vector<MeshDetails*> update();
std::vector<ChunkMeshDetails*> update();
struct Unit {
std::shared_ptr<BlockChunk> thisChunk = nullptr;
std::array<std::shared_ptr<BlockChunk>, 6> adjacentChunks {};
MeshDetails* meshDetails = new MeshDetails();
ChunkMeshDetails* meshDetails = new ChunkMeshDetails();
bool busy = false;
};
@ -48,7 +48,7 @@ public:
struct Thread {
explicit Thread(ClientGame &defs, std::array<NoiseSample, 3>& offsetSampler);
ClientGame &defs;
ClientGame &game;
std::array<NoiseSample, 3>& offsetSamplers;
std::thread thread {};
@ -62,7 +62,7 @@ private:
static void threadFunction(Thread* thread);
LocalDimension& dimension;
ClientGame& defs;
ClientGame& game;
std::array<NoiseSample, 3> noiseSampler;
std::vector<glm::vec3> queuedTasks;

View File

@ -4,40 +4,66 @@
#include "WorldInterpolationStream.h"
WorldInterpolationStream::WorldInterpolationStream(unsigned int seed, ClientGame& defs) {
// gen(seed, defs.defs) {
queuedTasks.reserve(1024);
#include "../../../def/ClientGame.h"
WorldInterpolationStream::WorldInterpolationStream(unsigned int seed, ClientGame& game) :
props(std::make_shared<MapGenProps>(seed)),
gen(seed, game.defs, game.biomes, props) {
threads.reserve(THREADS);
for (int i = 0; i < THREADS; i++) {
// threads.emplace_back(&gen);
threads.emplace_back();
for (int i = 0; i < THREADS; i++) threads.emplace_back(&gen);
}
void WorldInterpolationStream::queuePacket(std::unique_ptr<PacketView> p) {
queuedPacketTasks.push_back(std::move(p));
}
bool WorldInterpolationStream::queuePosition(glm::vec3 pos){
if (!queuedInterpMap.count(pos)) {
queuedInterpTasks.push_back(pos);
queuedInterpMap.insert(pos);
return true;
}
return false;
}
bool WorldInterpolationStream::pushBack(std::unique_ptr<PacketView> p) {
queuedTasks.push_back(std::move(p));
return true;
}
std::vector<std::shared_ptr<BlockChunk>> WorldInterpolationStream::update() {
std::vector<std::shared_ptr<BlockChunk>> finishedChunks;
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> WorldInterpolationStream::update() {
auto finishedChunks = std::make_unique<std::vector<std::shared_ptr<BlockChunk>>>();
auto finishedMapBlocks = std::make_unique<std::vector<std::shared_ptr<MeshFarMap>>>();
for (auto& t : threads) {
for (auto& u : t.tasks) {
if (!u.unlocked) continue;
if (u.locked) continue;
if (u.chunk != nullptr) {
finishedChunks.push_back(std::shared_ptr<BlockChunk>(u.chunk));
finishedChunks->push_back(u.chunk);
u.chunk = nullptr;
u.job = JobType::EMPTY;
}
else if (u.mapblock != nullptr) {
finishedMapBlocks->push_back(u.mapblock);
u.mapblock = nullptr;
u.job = JobType::EMPTY;
}
if (!queuedTasks.empty()) {
auto it = queuedTasks.begin();
u.packet = std::move(*it);
queuedTasks.erase(it);
//Lock it to allow the thread to edit it.
u.unlocked = false;
if (!queuedPacketTasks.empty()) {
auto it = queuedPacketTasks.begin();
auto packet = std::move(*it);
queuedPacketTasks.erase(it);
u.job = JobType::PACKET;
u.packet = std::move(packet);
u.locked = true;
}
else if (!queuedInterpTasks.empty()) {
auto it = queuedInterpTasks.begin();
glm::vec3 pos = *it;
queuedInterpTasks.erase(it);
queuedInterpMap.erase(pos);
u.job = JobType::FARMAP;
u.mapBlockPos = pos;
u.locked = true;
}
}
}
@ -45,41 +71,36 @@ std::vector<std::shared_ptr<BlockChunk>> WorldInterpolationStream::update() {
return finishedChunks;
}
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
WorldInterpolationStream::Thread::Thread() {
//WorldInterpolationStream::Thread::Thread(MapGen *gen) : gen(gen) {
WorldInterpolationStream::Thread::Thread(MapGen *gen) : gen(gen) {
thread = std::thread(WorldInterpolationStream::threadFunction, this);
thread.detach();
}
#pragma clang diagnostic pop
void WorldInterpolationStream::threadFunction(WorldInterpolationStream::Thread *thread) {
while (!thread->kill) {
while (thread->keepAlive) {
bool noJobs = true;
for (Unit& u : thread->tasks) {
if (!u.unlocked) {
noJobs = false;
u.chunk = new BlockChunk;
u.chunk->deserialize(*u.packet);
u.unlocked = true;
break;
bool empty = true;
for (Job& u : thread->tasks) {
if (u.locked) {
if (u.job == JobType::PACKET) {
empty = false;
u.chunk = std::make_shared<BlockChunk>();
u.chunk->deserialize(*u.packet);
u.locked = false;
break;
}
else if (u.job == JobType::FARMAP) {
std::cout << "Farmap no exist yet" << std::endl;
}
}
}
if (noJobs) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
WorldInterpolationStream::~WorldInterpolationStream() {
for (auto& t : threads) {
t.keepAlive = false;
t.kill = true;
t.thread.join();
}
}

View File

@ -4,50 +4,69 @@
#pragma once
#include <list>
#include <thread>
#include <unordered_set>
#include "../../../def/ClientGame.h"
#include "graph/MeshFarMap.h"
#include "../../../def/gen/MapGen.h"
#include "../../../world/chunk/BlockChunk.h"
class ClientGame;
class WorldInterpolationStream {
public:
static const int THREAD_QUEUE_SIZE = 128;
static const int THREADS = 2;
static const int THREADS = 4;
static const int THREAD_QUEUE_SIZE = 32;
WorldInterpolationStream(unsigned int seed, ClientGame& defs);
WorldInterpolationStream(unsigned int seed, ClientGame& game);
~WorldInterpolationStream();
//Add `p` to the pre-thread queue.
bool pushBack(std::unique_ptr<PacketView> p);
// Queue parsing of packet `p`.
void queuePacket(std::unique_ptr<PacketView> p);
// Queue interpolation of Mapblock at `pos`.
bool queuePosition(glm::vec3 pos);
// Returns a vector of BlockChunks that have finished processing,
// and gives the threads new data to work with.
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> update();
//Will return a vector of BlockChunk pointers containing finished chunks.
//Frees up the threads and starts new tasks.
std::vector<std::shared_ptr<BlockChunk>> update();
private:
enum class JobType {
EMPTY,
PACKET,
FARMAP
};
struct Unit {
std::unique_ptr<PacketView> packet;
BlockChunk* chunk = nullptr;
struct Job {
bool locked = false;
JobType job = JobType::EMPTY;
std::unique_ptr<PacketView> packet = nullptr;
std::shared_ptr<BlockChunk> chunk = nullptr;
std::shared_ptr<MeshFarMap> mapblock = nullptr;
glm::vec3 mapBlockPos = {0, 0, 0};
bool unlocked = true;
};
struct Thread {
// explicit Thread(MapGen* gen);
explicit Thread();
// MapGen* gen;
explicit Thread(MapGen* gen);
std::thread thread;
bool keepAlive = true;
bool kill = false;
std::vector<Unit> tasks = std::vector<Unit>(THREAD_QUEUE_SIZE);
MapGen* gen;
std::vector<Job> tasks = std::vector<Job>(THREAD_QUEUE_SIZE);
};
std::vector<Thread> threads;
private:
// Function that occurs on the threads.
static void threadFunction(Thread* thread);
// MapGen gen;
std::vector<std::unique_ptr<PacketView>> queuedTasks;
std::shared_ptr<MapGenProps> props;
MapGen gen;
std::vector<Thread> threads;
std::list<std::unique_ptr<PacketView>> queuedPacketTasks;
std::unordered_set<glm::vec3, Vec::vec3> queuedInterpMap;
std::list<glm::vec3> queuedInterpTasks;
};

View File

@ -0,0 +1,127 @@
//
// Created by aurailus on 01/12/18.
//
#include <vector>
#include <glm/gtx/normal.hpp>
#include "ChunkMeshGenerator.h"
#include "../ChunkMeshDetails.h"
#include "../../../../util/Vec.h"
#include "../../../../world/chunk/BlockChunk.h"
ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
std::shared_ptr<BlockChunk> chunk, std::array<std::shared_ptr<BlockChunk>, 6> adjacent, std::array<NoiseSample, 3>& blockOffsets) :
defs(defs),
chunk(chunk),
biomes(biomes),
adjacent(adjacent),
meshDetails(meshDetails) {
meshDetails->vertices.reserve(5000);
meshDetails->indices.reserve(7000);
const auto& blockData = chunk->cGetBlocks();
const auto& biomeData = chunk->cGetBiomes();
unsigned short blockArrayPos = 0;
unsigned int cBlock = blockData[blockArrayPos + 1];
unsigned short biomeArrayPos = 0;
unsigned short cBiome = biomeData[biomeArrayPos + 1];
glm::ivec3 off;
for (unsigned short i = 0; i < 4096; i++) {
if (blockArrayPos + 2 < blockData.size() && i >= blockData[blockArrayPos + 2]) {
blockArrayPos += 2;
cBlock = blockData[blockArrayPos + 1];
}
if (biomeArrayPos + 2 < biomeData.size() && i >= biomeData[biomeArrayPos + 2]) {
biomeArrayPos += 2;
cBiome = biomeData[biomeArrayPos + 1];
}
BlockModel& model = defs.blockFromId(cBlock).model;
glm::vec3 biomeTint = biomes.biomeFromId(cBiome).biomeTint;
if (!model.visible) continue;
Vec::indAssignVec(i, off);
glm::vec3 vis = off;
for (auto& mod : model.meshMods) {
switch (mod.first) {
default: break;
case MeshMod::OFFSET_X:
vis.x += blockOffsets[0].get(off) * mod.second; break;
case MeshMod::OFFSET_Y:
vis.y += blockOffsets[1].get(off) * mod.second; break;
case MeshMod::OFFSET_Z:
vis.z += blockOffsets[2].get(off) * mod.second; break;
}
}
if (!getBlockAt({off.x - 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XNEG)], biomeTint);
if (!getBlockAt({off.x + 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XPOS)], biomeTint);
if (!getBlockAt({off.x, off.y - 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YNEG)], biomeTint);
if (!getBlockAt({off.x, off.y + 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YPOS)], biomeTint);
if (!getBlockAt({off.x, off.y, off.z - 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZNEG)], biomeTint);
if (!getBlockAt({off.x, off.y, off.z + 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZPOS)], biomeTint);
addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint);
}
meshDetails->vertices.shrink_to_fit();
meshDetails->indices.shrink_to_fit();
}
BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3 &pos) {
if (pos.x == 16) return defs.blockFromId(adjacent[0]->getBlock(pos - glm::ivec3 {16, 0, 0}));
if (pos.x == -1) return defs.blockFromId(adjacent[1]->getBlock(pos + glm::ivec3 {16, 0, 0}));
if (pos.y == 16) return defs.blockFromId(adjacent[2]->getBlock(pos - glm::ivec3 {0, 16, 0}));
if (pos.y == -1) return defs.blockFromId(adjacent[3]->getBlock(pos + glm::ivec3 {0, 16, 0}));
if (pos.z == 16) return defs.blockFromId(adjacent[4]->getBlock(pos - glm::ivec3 {0, 0, 16}));
if (pos.z == -1) return defs.blockFromId(adjacent[5]->getBlock(pos + glm::ivec3 {0, 0, 16}));
return defs.blockFromId(chunk->getBlock(pos));
}
void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint) {
for (const MeshPart& mp : meshParts) {
glm::vec3 modData = {};
switch (mp.shaderMod) {
default: break;
case ShaderMod::ROTATE_X:
case ShaderMod::ROTATE_Y:
case ShaderMod::ROTATE_Z:
case ShaderMod::SWAY_ATTACHED:
case ShaderMod::SWAY_FULL_BLOCK:
modData = {Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0};
break;
}
for (const BlockModelVertex &vertex : mp.vertices) {
meshDetails->vertices.push_back({
vertex.pos + offset,
vertex.tex,
(mp.blendInd ? tint : glm::vec3 {1, 1, 1}),
(mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}),
Util::packFloat(vertex.nml),
static_cast<float>(mp.shaderMod),
modData
});
}
for (unsigned int index : mp.indices) {
meshDetails->indices.push_back(indOffset + index);
}
indOffset += mp.vertices.size();
}
}

View File

@ -2,37 +2,33 @@
// Created by aurailus on 01/12/18.
//
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#pragma once
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#define GLM_ENABLE_EXPERIMENTAL
#pragma clang diagnostic pop
#include "../../../../def/ClientGame.h"
#include "../../../../def/gen/NoiseSample.h"
class MeshDetails;
class ChunkMeshDetails;
class BlockChunk;
class MeshGenerator {
class ChunkMeshGenerator {
public:
MeshGenerator(MeshDetails* meshDetails, ClientGame& defs,
std::shared_ptr<BlockChunk> chunk, std::array<std::shared_ptr<BlockChunk>, 6> adjacent,
std::array<NoiseSample, 3>& blockOffsets, bool hi);
ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
std::shared_ptr<BlockChunk> chunk, std::array<std::shared_ptr<BlockChunk>, 6> adjacent, std::array<NoiseSample, 3>& blockOffsets);
private:
BlockDef& getBlockAt(const glm::ivec3 &pos);
void addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint);
unsigned int indOffset = 0;
LocalDefinitionAtlas& defs;
LocalBiomeAtlas& biomes;
ClientGame& defs;
LocalDefinitionAtlas& atlas;
MeshDetails* meshDetails;
unsigned int indOffset = 0;
ChunkMeshDetails* meshDetails;
std::shared_ptr<BlockChunk> chunk;
std::array<std::shared_ptr<BlockChunk>, 6> adjacent;
};
#pragma clang diagnostic pop
};

View File

@ -0,0 +1,126 @@
//
// Created by aurailus on 2020-04-06.
//
#include <vector>
#include <glm/gtx/normal.hpp>
#include "FarMeshGenerator.h"
#include "../FarMapMeshDetails.h"
#include "../../../../util/Vec.h"
#include "../../../../world/chunk/BlockChunk.h"
//FarMeshGenerator::FarMeshGenerator(LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
// std::vector<unsigned int>& blocks, unsigned int width) :
//
// defs(defs),
// width(width),
// blocks(blocks),
// biomes(biomes) {
//
// meshDetails->vertices.reserve(5000);
// meshDetails->indices.reserve(7000);
//
// const auto& blockData = chunk->cGetBlocks();
// const auto& biomeData = chunk->cGetBiomes();
//
// unsigned short blockArrayPos = 0;
// unsigned int cBlock = blockData[blockArrayPos + 1];
// unsigned short biomeArrayPos = 0;
// unsigned short cBiome = biomeData[biomeArrayPos + 1];
//
// glm::ivec3 off;
// for (unsigned short i = 0; i < 4096; i++) {
// if (blockArrayPos + 2 < blockData.size() && i >= blockData[blockArrayPos + 2]) {
// blockArrayPos += 2;
// cBlock = blockData[blockArrayPos + 1];
// }
// if (biomeArrayPos + 2 < biomeData.size() && i >= biomeData[biomeArrayPos + 2]) {
// biomeArrayPos += 2;
// cBiome = biomeData[biomeArrayPos + 1];
// }
//
// BlockModel& model = defs.blockFromId(cBlock).model;
// glm::vec3 biomeTint = biomes.biomeFromId(cBiome).biomeTint;
//
// if (!model.visible) continue;
//
// Vec::indAssignVec(i, off);
// glm::vec3 vis = off;
//
// for (auto& mod : model.meshMods) {
// switch (mod.first) {
// default: break;
//
// case MeshMod::OFFSET_X:
// vis.x += blockOffsets[0].get(off) * mod.second; break;
// case MeshMod::OFFSET_Y:
// vis.y += blockOffsets[1].get(off) * mod.second; break;
// case MeshMod::OFFSET_Z:
// vis.z += blockOffsets[2].get(off) * mod.second; break;
// }
// }
//
// if (!getBlockAt({off.x - 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XNEG)], biomeTint);
// if (!getBlockAt({off.x + 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XPOS)], biomeTint);
// if (!getBlockAt({off.x, off.y - 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YNEG)], biomeTint);
// if (!getBlockAt({off.x, off.y + 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YPOS)], biomeTint);
// if (!getBlockAt({off.x, off.y, off.z - 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZNEG)], biomeTint);
// if (!getBlockAt({off.x, off.y, off.z + 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZPOS)], biomeTint);
//
// addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint);
// }
//
// meshDetails->vertices.shrink_to_fit();
// meshDetails->indices.shrink_to_fit();
//}
//
//BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3 &pos) {
// if (pos.x == 16) return defs.blockFromId(adjacent[0]->getBlock(pos - glm::ivec3 {16, 0, 0}));
// if (pos.x == -1) return defs.blockFromId(adjacent[1]->getBlock(pos + glm::ivec3 {16, 0, 0}));
//
// if (pos.y == 16) return defs.blockFromId(adjacent[2]->getBlock(pos - glm::ivec3 {0, 16, 0}));
// if (pos.y == -1) return defs.blockFromId(adjacent[3]->getBlock(pos + glm::ivec3 {0, 16, 0}));
//
// if (pos.z == 16) return defs.blockFromId(adjacent[4]->getBlock(pos - glm::ivec3 {0, 0, 16}));
// if (pos.z == -1) return defs.blockFromId(adjacent[5]->getBlock(pos + glm::ivec3 {0, 0, 16}));
//
// return defs.blockFromId(chunk->getBlock(pos));
//}
//
//void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint) {
// for (const MeshPart& mp : meshParts) {
// glm::vec3 modData = {};
//
// switch (mp.shaderMod) {
// default: break;
//
// case ShaderMod::ROTATE_X:
// case ShaderMod::ROTATE_Y:
// case ShaderMod::ROTATE_Z:
// case ShaderMod::SWAY_ATTACHED:
// case ShaderMod::SWAY_FULL_BLOCK:
// modData = {Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0};
// break;
// }
//
// for (const BlockModelVertex &vertex : mp.vertices) {
// meshDetails->vertices.push_back({
// vertex.pos + offset,
// vertex.tex,
// (mp.blendInd ? tint : glm::vec3 {1, 1, 1}),
// (mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}),
// Util::packFloat(vertex.nml),
// static_cast<float>(mp.shaderMod),
// modData
// });
// }
//
// for (unsigned int index : mp.indices) {
// meshDetails->indices.push_back(indOffset + index);
// }
//
// indOffset += mp.vertices.size();
// }
//}

View File

@ -0,0 +1,33 @@
//
// Created by aurailus on 2020-04-06.
//
#pragma once
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#define GLM_ENABLE_EXPERIMENTAL
#pragma clang diagnostic pop
#include "../../../../def/ClientGame.h"
#include "../../../../def/gen/NoiseSample.h"
class FarMapMeshDetails;
//class FarMeshGenerator {
//public:
// FarMeshGenerator(LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
// std::vector<unsigned int>& blocks, unsigned int width);
//private:
// BlockDef& getBlockAt(const glm::ivec3 &pos);
// void addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint);
//
// LocalDefinitionAtlas& defs;
// LocalBiomeAtlas& biomes;
//
// unsigned int indOffset = 0;
// FarMapMeshDetails* meshDetails;
//
// unsigned int width;
// std::vector<unsigned int>& blocks;
//};

View File

@ -0,0 +1,5 @@
//
// Created by aurailus on 2020-03-26.
//
#include "MeshFarMap.h"

View File

@ -0,0 +1,9 @@
//
// Created by aurailus on 2020-03-26.
//
#pragma once
class MeshFarMap {
};

View File

@ -1,152 +0,0 @@
//
// Created by aurailus on 01/12/18.
//
#include <vector>
#include <glm/gtx/normal.hpp>
#include "MeshGenerator.h"
#include "../MeshDetails.h"
#include "../../../../util/Vec.h"
#include "../../../../util/Timer.h"
#include "../../../../world/chunk/BlockChunk.h"
MeshGenerator::MeshGenerator(MeshDetails* meshDetails, ClientGame& defs, std::shared_ptr<BlockChunk> chunk,
std::array<std::shared_ptr<BlockChunk>, 6> adjacent,
std::array<NoiseSample, 3>& blockOffsets, bool hi) :
defs(defs),
chunk(chunk),
atlas(defs.defs),
adjacent(adjacent),
meshDetails(meshDetails) {
meshDetails->vertices.reserve(5000);
meshDetails->indices.reserve(7000);
Timer t("ChunkMesh Generation");
glm::ivec3 off;
glm::vec3 vis;
glm::vec3 check;
const auto& blocks = chunk->cGetBlocks();
const auto& biomes = chunk->cGetBiomes();
unsigned short blockArrayPos = 0;
unsigned int cBlock = blocks[blockArrayPos + 1];
unsigned short biomeArrayPos = 0;
unsigned short cBiome = biomes[biomeArrayPos + 1];
for (unsigned short i = 0; i < 4096; i++) {
if (blockArrayPos + 2 < blocks.size() && i >= blocks[blockArrayPos + 2]) {
blockArrayPos += 2;
cBlock = blocks[blockArrayPos + 1];
}
if (biomeArrayPos + 2 < biomes.size() && i >= biomes[biomeArrayPos + 2]) {
biomeArrayPos += 2;
cBiome = biomes[biomeArrayPos + 1];
}
BlockModel& model = hi ? atlas.blockFromId(cBlock).model : atlas.blockFromId(cBlock).farModel;
glm::vec3 biomeTint = defs.biomes.biomeFromId(cBiome).biomeTint;
if (model.visible) {
Vec::indAssignVec(i, off);
vis = off;
for (auto& mod : model.meshMods) {
switch (mod.first) {
default: break;
case MeshMod::OFFSET_X: {
vis.x += blockOffsets[0].get(off) * mod.second;
break;
}
case MeshMod::OFFSET_Y: {
vis.y += blockOffsets[1].get(off) * mod.second;
break;
}
case MeshMod::OFFSET_Z: {
vis.z += blockOffsets[2].get(off) * mod.second;
break;
}
}
}
if (model.visible) {
check = off; check.x -= 1;
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XNEG)], biomeTint);
check = off; check.x += 1;
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XPOS)], biomeTint);
check = off; check.y -= 1;
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YNEG)], biomeTint);
check = off; check.y += 1;
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YPOS)], biomeTint);
check = off; check.z -= 1;
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZNEG)], biomeTint);
check = off; check.z += 1;
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZPOS)], biomeTint);
addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint);
}
}
}
meshDetails->vertices.shrink_to_fit();
meshDetails->indices.shrink_to_fit();
}
BlockDef& MeshGenerator::getBlockAt(const glm::ivec3 &pos) {
if (pos.x < 0 || pos.x >= 16 || pos.y < 0 || pos.y >= 16 || pos.z < 0 || pos.z >= 16) {
if (pos.x == 16) return atlas.blockFromId(adjacent[0]->getBlock(pos - glm::ivec3 {16, 0, 0}));
if (pos.x == -1) return atlas.blockFromId(adjacent[1]->getBlock(pos + glm::ivec3 {16, 0, 0}));
if (pos.y == 16) return atlas.blockFromId(adjacent[2]->getBlock(pos - glm::ivec3 {0, 16, 0}));
if (pos.y == -1) return atlas.blockFromId(adjacent[3]->getBlock(pos + glm::ivec3 {0, 16, 0}));
if (pos.z == 16) return atlas.blockFromId(adjacent[4]->getBlock(pos - glm::ivec3 {0, 0, 16}));
if (pos.z == -1) return atlas.blockFromId(adjacent[5]->getBlock(pos + glm::ivec3 {0, 0, 16}));
}
return atlas.blockFromId(chunk->getBlock(pos));
}
void MeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint) {
for (const MeshPart& mp : meshParts) {
glm::vec3 modData = {};
switch (mp.shaderMod) {
default: break;
case ShaderMod::ROTATE_X:
case ShaderMod::ROTATE_Y:
case ShaderMod::ROTATE_Z:
case ShaderMod::SWAY_ATTACHED:
case ShaderMod::SWAY_FULL_BLOCK: {
modData = {Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0};
break;
}
}
for (const BlockModelVertex &vertex : mp.vertices) {
meshDetails->vertices.push_back({
vertex.pos + offset,
vertex.tex,
(mp.blendInd ? tint : glm::vec3 {1, 1, 1}),
(mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}),
Util::packFloat(vertex.nml),
static_cast<float>(mp.shaderMod),
modData
});
}
for (unsigned int index : mp.indices) {
meshDetails->indices.push_back(indOffset + index);
}
indOffset += mp.vertices.size();
}
}

View File

@ -11,13 +11,14 @@
#include "../util/net/PacketView.h"
Server::Server(unsigned short port, const std::string& subgame) :
seed(27),
port(port),
config(defs),
defs(subgame),
defs(subgame, seed),
clientList(defs),
handler(port, 32),
refs(defs.defs, &clientList),
world(10, defs, clientList) {
world(seed, defs, clientList) {
defs.init(world);
world.init();

View File

@ -27,6 +27,9 @@ public:
private:
bool alive = true;
unsigned int seed = 0;
unsigned short port = 0;
ServerGame defs;
ServerWorld world;
NetHandler handler;
@ -38,7 +41,5 @@ private:
double elapsedSeconds = 0;
double deltaTime = 0;
unsigned short port = 0;
};

View File

@ -8,17 +8,17 @@
#include "../../util/net/PacketView.h"
#include "../../util/net/Serializer.h"
ServerConfig::ServerConfig(ServerGame &defs) : defs(defs) {}
ServerConfig::ServerConfig(ServerGame &defs) : game(defs) {}
void ServerConfig::init() {
blockIdentifierList.reserve(static_cast<unsigned long>(defs.defs.size()));
for (unsigned int i = 0; i < defs.defs.size(); i++) {
blockIdentifierList.push_back(defs.defs.fromId(i).identifier);
blockIdentifierList.reserve(static_cast<unsigned long>(game.defs.size()));
for (unsigned int i = 0; i < game.defs.size(); i++) {
blockIdentifierList.push_back(game.defs.fromId(i).identifier);
}
biomeIdentifierList.reserve(static_cast<unsigned long>(defs.biomes.size()));
for (unsigned int i = 0; i < defs.biomes.size(); i++) {
biomeIdentifierList.push_back(defs.biomes.biomeFromId(i).identifier);
biomeIdentifierList.reserve(static_cast<unsigned long>(game.biomes.size()));
for (unsigned int i = 0; i < game.biomes.size(); i++) {
biomeIdentifierList.push_back(game.biomes.biomeFromId(i).identifier);
}
}
@ -29,6 +29,14 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
return true;
}
case PacketType::SERVER_INFO: {
Serializer()
.append(game.biomes.seed)
.packet(PacketType::SERVER_INFO)
.sendTo(client.peer, PacketChannel::CONNECT);
break;
}
case PacketType::BLOCK_IDENTIFIER_LIST: {
Serializer()
.append(blockIdentifierList)
@ -46,7 +54,7 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
}
case PacketType::MODS: {
defs.parser.sendModsPacket(client.peer);
game.parser.sendModsPacket(client.peer);
break;
}
@ -56,7 +64,7 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
Serializer s {};
for (ServerTexture& texture : defs.assets.textures) {
for (ServerTexture& texture : game.assets.textures) {
if (packetSize + 20 + texture.data.length() > MAX_PACKET_SIZE && packetSize != 0) {
s.append(static_cast<int>(AssetType::END));
Packet p(PacketType::MEDIA);
@ -77,7 +85,7 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
packetSize += texture.data.length() + 20;
}
for (SerializedModel& model : defs.assets.models) {
for (SerializedModel& model : game.assets.models) {
if (packetSize + 16 + model.data.length() > MAX_PACKET_SIZE && packetSize != 0) {
s.append(static_cast<int>(AssetType::END));
Packet p(PacketType::MEDIA);

View File

@ -17,7 +17,7 @@ public:
//Bool: Create player
bool handlePacket(ServerClient &client, PacketView& p);
private:
ServerGame& defs;
ServerGame& game;
std::vector<std::string> blockIdentifierList {};
std::vector<std::string> biomeIdentifierList {};
};

View File

@ -0,0 +1,80 @@
//
// Created by aurailus on 06/03/19.
//
#include "ServerGenStream.h"
#include "../../def/ServerGame.h"
ServerGenStream::ServerGenStream(unsigned int seed, ServerGame& game) :
props(std::make_shared<MapGenProps>(seed)),
gen(seed, game.defs, game.biomes, props) {
threads.reserve(THREADS);
for (int i = 0; i < THREADS; i++) threads.emplace_back(&gen);
}
bool ServerGenStream::queue(glm::vec3 pos) {
if (!queuedMap.count(pos)) {
queuedTasks.push_back(pos);
queuedMap.insert(pos);
return true;
}
return false;
}
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> ServerGenStream::update() {
auto finishedChunks = std::make_unique<std::vector<std::shared_ptr<BlockChunk>>>();
for (auto& t : threads) {
for (auto& u : t.tasks) {
if (u.locked) continue;
if (!u.chunks.empty()) {
for (auto chunk : u.chunks)
finishedChunks->push_back(std::shared_ptr<BlockChunk>(chunk.second.second));
u.chunks.clear();
}
if (!queuedTasks.empty()) {
auto it = queuedTasks.begin();
glm::vec3 pos = *it;
queuedTasks.erase(it);
queuedMap.erase(pos);
u.pos = pos;
u.locked = true;
}
}
}
return finishedChunks;
}
ServerGenStream::Thread::Thread(MapGen *gen) : gen(gen) {
thread = std::thread(ServerGenStream::threadFunction, this);
thread.detach();
}
void ServerGenStream::threadFunction(ServerGenStream::Thread *thread) {
while (!thread->kill) {
bool empty = true;
for (Job& u : thread->tasks) {
if (u.locked) {
empty = false;
u.chunks = thread->gen->generateMapBlock(u.pos);
u.locked = false;
break;
}
}
if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
ServerGenStream::~ServerGenStream() {
for (auto& t : threads) {
t.kill = true;
t.thread.join();
}
}

View File

@ -0,0 +1,56 @@
//
// Created by aurailus on 06/03/19.
//
#pragma once
#include <list>
#include <thread>
#include <unordered_set>
#include <glm/vec3.hpp>
#include "../../def/gen/MapGen.h"
class ServerGame;
class ServerGenStream {
public:
static const int THREADS = 4;
static const int THREAD_QUEUE_SIZE = 6;
explicit ServerGenStream(unsigned int seed, ServerGame& game);
~ServerGenStream();
// Add the MapBlock position `pos` to the generation queue.
bool queue(glm::vec3 pos);
// Returns a vector of BlockChunks that have finished generating,
// and gives the threads new data to work with.
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> update();
private:
struct Job {
bool locked = false;
glm::ivec3 pos {};
MapGen::chunk_partials_map chunks {};
};
struct Thread {
explicit Thread(MapGen* gen);
std::thread thread;
bool kill = false;
MapGen* gen;
std::vector<Job> tasks = std::vector<Job>(THREAD_QUEUE_SIZE);
};
// Function that occurs on the threads.
static void threadFunction(Thread* thread);
std::shared_ptr<MapGenProps> props;
MapGen gen;
std::vector<Thread> threads;
std::list<glm::vec3> queuedTasks;
std::unordered_set<glm::vec3, Vec::vec3> queuedMap;
};

View File

@ -2,17 +2,14 @@
// Created by aurailus on 05/03/19.
//
#include <algorithm>
#include <glm/glm.hpp>
#include <unordered_map>
#include "WorldGenStream.h"
#include "../conn/ServerClient.h"
#include "../../world/chunk/BlockChunk.h"
#include "../../util/Vec.h"
#include "ServerWorld.h"
#include "ServerGenStream.h"
#include "../conn/ServerClient.h"
ServerWorld::ServerWorld(unsigned int seed, ServerGame& defs, ClientList& clients) :
clientList(clients),
seed(seed),
@ -37,23 +34,12 @@ ServerWorld::ServerWorld(unsigned int seed, ServerGame& defs, ClientList& client
}
void ServerWorld::init() {
genStream = std::make_unique<WorldGenStream>(seed, defs);
genStream = std::make_unique<ServerGenStream>(seed, defs);
}
void ServerWorld::update(double delta) {
dimension.update(clientList.clients);
while (!generateQueueList.empty()) {
auto it = generateQueueList.begin();
glm::vec3 pos = *it;
if (genStream->tryToQueue(pos)) {
generateQueueList.erase(it);
generateQueueMap.erase(pos);
}
else break;
}
auto finished = genStream->update();
generatedChunks = static_cast<int>(finished->size());
@ -147,11 +133,9 @@ void ServerWorld::changedChunks(ServerClient& client) {
}
bool ServerWorld::generateMapBlock(glm::ivec3 pos) {
if(!generateQueueMap.count(pos) && (!dimension.getMapBlock(pos) || !dimension.getMapBlock(pos)->generated)) {
generateQueueMap.insert(pos);
generateQueueList.push_back(pos);
return true;
}
if(!dimension.getMapBlock(pos) || !dimension.getMapBlock(pos)->generated)
return genStream->queue(pos);
return false;
}

View File

@ -6,7 +6,7 @@
#include <unordered_set>
#include "WorldGenStream.h"
#include "ServerGenStream.h"
#include "../conn/ClientList.h"
#include "../../def/ServerGame.h"
#include "../../game/scene/world/World.h"
@ -36,10 +36,7 @@ private:
static bool isInBounds(glm::ivec3 pos, std::pair<glm::ivec3, glm::ivec3>& bounds);
std::unique_ptr<WorldGenStream> genStream = nullptr;
std::unordered_set<glm::vec3, Vec::vec3> generateQueueMap;
std::vector<glm::vec3> generateQueueList;
std::unique_ptr<ServerGenStream> genStream = nullptr;
unsigned int seed;
ServerGame& defs;

View File

@ -1,92 +0,0 @@
//
// Created by aurailus on 06/03/19.
//
#include "WorldGenStream.h"
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
WorldGenStream::WorldGenStream(unsigned int seed, ServerGame& atlas) : gen(seed, atlas.defs, atlas.biomes) {
queuedTasks.reserve((unsigned long) TOTAL_QUEUE_SIZE);
threads.reserve(THREADS);
for (int i = 0; i < THREADS; i++) {
threads.emplace_back(&gen);
}
}
bool WorldGenStream::tryToQueue(glm::vec3 pos) {
unsigned long sizeOfQueue = queuedTasks.size();
if (sizeOfQueue < TOTAL_QUEUE_SIZE && !queuedMap.count(pos)) {
queuedTasks.push_back(pos);
queuedMap.insert(pos);
}
return sizeOfQueue + 1 < TOTAL_QUEUE_SIZE;
}
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> WorldGenStream::update() {
auto finishedChunks = std::make_unique<std::vector<std::shared_ptr<BlockChunk>>>();
for (auto& t : threads) {
for (auto& u : t.tasks) {
if (!u.unlocked) continue;
if (!u.chunks.empty()) {
for (auto chunk : u.chunks) {
finishedChunks->push_back(std::shared_ptr<BlockChunk>(chunk.second.second));
}
u.chunks.clear();
}
if (!queuedTasks.empty()) {
auto it = queuedTasks.begin();
glm::vec3 pos = *it;
queuedTasks.erase(it);
queuedMap.erase(pos);
u.pos = pos;
//Lock it in to allow the thread to edit it.
u.unlocked = false;
}
}
}
return finishedChunks;
}
WorldGenStream::Thread::Thread(MapGen *gen) {
this->gen = gen;
thread = std::thread(WorldGenStream::threadFunction, this);
thread.detach();
}
void WorldGenStream::threadFunction(WorldGenStream::Thread *thread) {
while (thread->keepAlive) {
bool empty = true;
for (Unit& u : thread->tasks) {
if (!u.unlocked) {
empty = false;
u.chunks = thread->gen->generateMapBlock(u.pos);
u.unlocked = true;
break;
}
}
if (empty) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
}
WorldGenStream::~WorldGenStream() {
for (auto& t : threads) {
t.keepAlive = false;
t.thread.join();
}
}
#pragma clang diagnostic pop

View File

@ -1,62 +0,0 @@
//
// Created by aurailus on 06/03/19.
//
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
#pragma once
#include <glm/vec3.hpp>
#include <thread>
#include <unordered_set>
#include "../../util/Vec.h"
#include "../../def/gen/MapGen.h"
#include "../../world/chunk/BlockChunk.h"
#include "../../def/ServerGame.h"
class WorldGenStream {
public:
static const int THREAD_QUEUE_SIZE = 6;
static const int THREADS = 4;
static const int TOTAL_QUEUE_SIZE = THREADS * THREAD_QUEUE_SIZE;
explicit WorldGenStream(unsigned int seed, ServerGame& defs);
~WorldGenStream();
//Attempt to add `pos` to the pre-thread queue.
//Will return a boolean stating if there is more space left in the queue.
bool tryToQueue(glm::vec3 pos);
//Will return a vector of BlockChunk pointers containing finished chunks.
//Frees up the threads and starts new units.
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> update();
struct Unit {
glm::ivec3 pos {};
MapGen::chunk_partials_map chunks {};
bool unlocked = true;
};
struct Thread {
explicit Thread(MapGen* gen);
MapGen* gen;
std::thread thread;
bool keepAlive = true;
std::vector<Unit> tasks = std::vector<Unit>(THREAD_QUEUE_SIZE);
};
std::vector<Thread> threads;
private:
static void threadFunction(Thread* thread);
MapGen gen;
std::vector<glm::vec3> queuedTasks;
std::unordered_set<glm::vec3, Vec::vec3> queuedMap;
};
#pragma clang diagnostic pop

View File

@ -29,11 +29,11 @@ namespace Vec {
glm::ivec3 {0, 0, 1}, glm::ivec3 {0, 0, -1}
};
static inline void indAssignVec(int ind, glm::ivec3& vec) {
vec.z = ind / (16 * 16);
ind -= ((int)vec.z * 16 * 16);
vec.y = ind / 16;
vec.x = ind % 16;
static inline void indAssignVec(int ind, glm::ivec3& vec, unsigned int wid = 16) {
vec.z = ind / (wid * wid);
ind -= ((int)vec.z * wid * wid);
vec.y = ind / wid;
vec.x = ind % wid;
}
};

View File

@ -73,7 +73,7 @@ void LocalDimension::finishMeshes() {
lastMeshUpdates = 0;
auto finishedMeshes = meshGenStream->update();
for (MeshDetails* meshDetails : finishedMeshes) {
for (ChunkMeshDetails* meshDetails : finishedMeshes) {
if (!meshDetails->vertices.empty()) {
auto meshChunk = std::make_shared<MeshChunk>();

View File

@ -17,6 +17,6 @@ zepha.register_entity("zeus:default:test", {
}
})
if (zepha.server) {
local entity = zepha.add_entity("zeus:default:test", V(0, 0, 0))
}
##if (zepha.server) {
## local entity = zepha.add_entity("zeus:default:test", V(0, 0, 0))
##}

View File

@ -1,7 +1,7 @@
zepha.register_item("zeus:materials:flint", {
name = "Flint",
textures = {
"zeus:materials:flint_outlined",
"zeus:materials:flint",
}
})

View File

@ -1,7 +1,7 @@
zepha.register_item("zeus:materials:plant_fibre", {
name = "Plant Fibre",
textures = {
"zeus:materials:plant_fibre_outlined"
"zeus:materials:plant_fibre"
},
groups = {
organic = 1,

View File

@ -1,7 +1,7 @@
zepha.register_item("zeus:materials:plant_twine", {
name = "Plant Twine",
textures = {
"zeus:materials:plant_twine_outlined"
"zeus:materials:plant_twine"
},
groups = {
rope = 1,

View File

@ -1,7 +1,7 @@
zepha.register_item("zeus:materials:rock", {
name = "Rock",
textures = {
"zeus:materials:rock_outlined"
"zeus:materials:rock"
},
groups = {
rock = 1,

View File

@ -1,7 +1,7 @@
zepha.register_item("zeus:materials:stick", {
name = "Stick",
textures = {
"zeus:materials:stick_outlined",
"zeus:materials:stick",
## "zeus:materials:stick_1_outlined",
## "zeus:materials:stick_2_outlined",
## "zeus:materials:stick_3_outlined"