Performance Improvements, better MeshChunk.
parent
4519147c84
commit
e9d7fd0ee9
|
@ -17,12 +17,9 @@ add_library(Zepha_Core
|
|||
client/graph/DrawableGroup.h
|
||||
client/graph/Font.cpp
|
||||
client/graph/Font.h
|
||||
client/graph/mesh/ChunkMesh.cpp
|
||||
client/graph/mesh/ChunkMesh.h
|
||||
client/graph/mesh/ChunkMeshGenerator.cpp
|
||||
client/graph/mesh/ChunkMeshGenerator.h
|
||||
client/graph/mesh/ChunkRenderElem.h
|
||||
client/graph/mesh/ChunkVertex.h
|
||||
client/graph/mesh/EntityMesh.cpp
|
||||
client/graph/mesh/EntityMesh.h
|
||||
client/graph/mesh/EntityVertex.h
|
||||
|
@ -103,7 +100,7 @@ add_library(Zepha_Core
|
|||
client/scene/Scene.h
|
||||
client/scene/SceneManager.cpp
|
||||
client/scene/SceneManager.h
|
||||
client/stream/ChunkMeshDetails.h
|
||||
client/stream/MeshChunkDetails.h
|
||||
client/stream/MeshGenStream.cpp
|
||||
client/stream/MeshGenStream.h
|
||||
client/stream/WorldInterpolationStream.cpp
|
||||
|
@ -326,6 +323,14 @@ add_library(Zepha_Core
|
|||
lua/modules/Message.h
|
||||
lua/NoiseFromLua.cpp
|
||||
lua/NoiseFromLua.h
|
||||
util/Types.h util/PerfTimer.cpp util/PerfTimer.h client/gui/compound/GuiPerfGraph.cpp client/gui/compound/GuiPerfGraph.h client/gui/compound/GuiCellGraph.cpp client/gui/compound/GuiCellGraph.h client/gui/basic/GuiCells.cpp client/gui/basic/GuiCells.h)
|
||||
util/Types.h
|
||||
util/PerfTimer.cpp
|
||||
util/PerfTimer.h
|
||||
client/gui/compound/GuiPerfGraph.cpp
|
||||
client/gui/compound/GuiPerfGraph.h
|
||||
client/gui/compound/GuiCellGraph.cpp
|
||||
client/gui/compound/GuiCellGraph.h
|
||||
client/gui/basic/GuiCells.cpp
|
||||
client/gui/basic/GuiCells.h)
|
||||
|
||||
target_include_directories(Zepha_Core PUBLIC .)
|
|
@ -103,7 +103,7 @@ void ClientNetworkInterpreter::receivedPacket(uptr<PacketView> p) {
|
|||
}
|
||||
|
||||
case Packet::Type::ENTITY_REMOVED: {
|
||||
world.getActiveDimension().l()->serverEntitiesRemoved(p->d);
|
||||
world.getActiveDimension().l()->removeServerEntities(p->d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,12 +65,12 @@ void ServerConnection::processConnecting() {
|
|||
else {
|
||||
enet_peer_reset(peer);
|
||||
if (attempt < attempts) {
|
||||
std::cout << Log::info << "Failed to connect to server, retrying." << Log::endl;
|
||||
std::cout << Log::info << "Failed to init to server, retrying." << Log::endl;
|
||||
connectionTime = std::chrono::high_resolution_clock::now();
|
||||
attempt++;
|
||||
}
|
||||
else {
|
||||
std::cout << Log::err << "Failed to connect to server." << Log::endl;
|
||||
std::cout << Log::err << "Failed to init to server." << Log::endl;
|
||||
state = State::FAILED_CONNECT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
class Renderer;
|
||||
|
||||
class Drawable {
|
||||
public:
|
||||
public:
|
||||
virtual void update(double delta) {};
|
||||
|
||||
virtual void draw(Renderer& renderer) {};
|
||||
|
@ -18,7 +18,7 @@ class Drawable {
|
|||
|
||||
virtual ~Drawable() = default;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
bool visible = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// Created by aurailus on 25/11/18.
|
||||
//
|
||||
|
||||
#include "ChunkMesh.h"
|
||||
|
||||
#include "ChunkVertex.h"
|
||||
|
||||
void ChunkMesh::create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices) {
|
||||
indCount = static_cast<GLsizei>(indices.size());
|
||||
|
||||
genArrays(static_cast<unsigned int>(vertices.size() * sizeof(ChunkVertex)),
|
||||
static_cast<unsigned int>(indices.size() * sizeof(unsigned int)),
|
||||
&vertices.front(), &indices.front());
|
||||
|
||||
unsigned int idx = 0;
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(position));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(texCoords));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendColor));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendMaskCoords));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(normal));
|
||||
createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_CHUNK(light));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(shaderMod));
|
||||
createVertexAttrib(idx, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(modValues));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
//
|
||||
// Created by aurailus on 25/11/18.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
class ChunkVertex;
|
||||
|
||||
class ChunkMesh : public Mesh {
|
||||
public:
|
||||
ChunkMesh() = default;
|
||||
|
||||
ChunkMesh(const ChunkMesh& o) { throw std::runtime_error("No copy constructor for ChunkMeshes"); };
|
||||
|
||||
void create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices);
|
||||
|
||||
~ChunkMesh() = default;
|
||||
};
|
|
@ -15,10 +15,10 @@
|
|||
#include "world/dim/chunk/Chunk.h"
|
||||
#include "game/def/mesh/BlockModel.h"
|
||||
#include "game/atlas/LocalBiomeAtlas.h"
|
||||
#include "client/stream/ChunkMeshDetails.h"
|
||||
#include "client/stream/MeshChunkDetails.h"
|
||||
#include "game/atlas/LocalDefinitionAtlas.h"
|
||||
|
||||
ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs,
|
||||
ChunkMeshGenerator::ChunkMeshGenerator(MeshChunkDetails* meshDetails, LocalDefinitionAtlas& defs,
|
||||
LocalBiomeAtlas& biomes, uptr<Chunk> chk, array<uptr<Chunk>, 6> adj, array<NoiseSample, 3>& blockOffsets) :
|
||||
defs(defs),
|
||||
biomes(biomes),
|
||||
|
|
|
@ -9,12 +9,12 @@ class MeshPart;
|
|||
class BlockDef;
|
||||
class NoiseSample;
|
||||
class LocalBiomeAtlas;
|
||||
class ChunkMeshDetails;
|
||||
class MeshChunkDetails;
|
||||
class LocalDefinitionAtlas;
|
||||
|
||||
class ChunkMeshGenerator {
|
||||
public:
|
||||
ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
ChunkMeshGenerator(MeshChunkDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
uptr<Chunk> chunk, array<uptr<Chunk>, 6> adjacent, array<NoiseSample, 3>& blockOffsets);
|
||||
|
||||
private:
|
||||
|
@ -27,7 +27,7 @@ private:
|
|||
LocalBiomeAtlas& biomes;
|
||||
|
||||
usize indOffset = 0;
|
||||
ChunkMeshDetails* meshDetails;
|
||||
MeshChunkDetails* meshDetails;
|
||||
|
||||
uptr<Chunk> chunk;
|
||||
array<uptr<Chunk>, 6> adjacent;
|
||||
|
|
|
@ -1,20 +1,41 @@
|
|||
//
|
||||
// Created by aurailus on 28/09/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
#include "util/Types.h"
|
||||
|
||||
class Renderer;
|
||||
|
||||
/**
|
||||
* An abstract class for a visual representation of one or more chunks.
|
||||
* Currently used by MeshChunk, but in the future Mesh MapBlocks will use it as well.
|
||||
* Keeps track of the chunk positions that are using this element, and if it should be kept alive.
|
||||
*/
|
||||
|
||||
struct ChunkRenderElem {
|
||||
ChunkRenderElem() = default;
|
||||
ChunkRenderElem(vec3 pos): pos(pos) {};
|
||||
|
||||
/** Sets the element's visual position. */
|
||||
virtual void setPos(vec3 pos) {
|
||||
this->pos = pos;
|
||||
};
|
||||
|
||||
/** Gets the element's visual position. */
|
||||
virtual vec3 getPos() {
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** Draws the element to the screen. */
|
||||
virtual void draw(Renderer& renderer) = 0;
|
||||
|
||||
virtual glm::vec3 getPos() = 0;
|
||||
/**
|
||||
* Specifies if a chunk is using this render element.
|
||||
* Returns a boolean indicating if there are any chunks using the element.
|
||||
*/
|
||||
|
||||
virtual bool updateChunkUse(ivec3 chunk, bool used) = 0;
|
||||
|
||||
// Used to determine if the RenderElem should be deleted.
|
||||
// Bool is if the RenderElem should be kept alive.
|
||||
// True = keep, False = remove
|
||||
virtual bool updateChunkUse(glm::vec3 chunk, bool used) = 0;
|
||||
protected:
|
||||
|
||||
/** The element's visual position. */
|
||||
vec3 pos {};
|
||||
};
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// Created by aurailus on 24/08/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
struct ChunkVertex {
|
||||
glm::vec3 position;
|
||||
glm::vec2 texCoords;
|
||||
glm::vec3 blendColor;
|
||||
glm::vec2 blendMaskCoords;
|
||||
float normal;
|
||||
glm::vec4 light;
|
||||
float shaderMod;
|
||||
glm::vec3 modValues;
|
||||
};
|
||||
|
||||
#define STRIDE_OFFSET_CHUNK(m) sizeof(struct ChunkVertex), (void *)offsetof(struct ChunkVertex, m)
|
|
@ -1,41 +1,5 @@
|
|||
//
|
||||
// Created by aurailus on 24/08/19.
|
||||
//
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
void Mesh::cleanup() {
|
||||
if (VAO != 0) glDeleteVertexArrays(1, &VAO);
|
||||
if (VBO != 0) glDeleteBuffers(1, &VBO);
|
||||
if (IBO != 0) glDeleteBuffers(1, &IBO);
|
||||
|
||||
IBO = 0;
|
||||
VBO = 0;
|
||||
VAO = 0;
|
||||
indCount = 0;
|
||||
}
|
||||
|
||||
void Mesh::genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr) {
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glGenBuffers(1, &IBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iboLength, indicesPtr, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, vboLength, verticesPtr, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
void Mesh::createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer) {
|
||||
glEnableVertexAttribArray(offset);
|
||||
if (type == GL_INT)
|
||||
glVertexAttribIPointer(offset, size, type, stride, pointer);
|
||||
else
|
||||
glVertexAttribPointer(offset, size, type, GL_FALSE, stride, pointer);
|
||||
}
|
||||
|
||||
void Mesh::draw() const {
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
|
@ -44,5 +8,26 @@ void Mesh::draw() const {
|
|||
}
|
||||
|
||||
Mesh::~Mesh() {
|
||||
cleanup();
|
||||
if (VAO != 0) glDeleteVertexArrays(1, &VAO);
|
||||
if (VBO != 0) glDeleteBuffers(1, &VBO);
|
||||
if (IBO != 0) glDeleteBuffers(1, &IBO);
|
||||
}
|
||||
|
||||
void Mesh::genArrays(usize vboLength, usize iboLength, const void* vertices, const void* indices) {
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glGenBuffers(1, &IBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iboLength, indices, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, vboLength, vertices, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
void Mesh::createVertexAttrib(u32 offset, u32 size, GLenum type, u32 stride, const void* pointer) {
|
||||
glEnableVertexAttribArray(offset);
|
||||
if (type == GL_INT) glVertexAttribIPointer(offset, size, type, stride, pointer);
|
||||
else glVertexAttribPointer(offset, size, type, GL_FALSE, stride, pointer);
|
||||
}
|
|
@ -1,28 +1,27 @@
|
|||
//
|
||||
// Created by aurailus on 24/08/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "util/Types.h"
|
||||
|
||||
/** Returns the stride and the offset of the member in the struct. */
|
||||
#define STRIDE_OFFSET(Struct, Member) sizeof(struct Struct), (void*)offsetof(struct Struct, Member)
|
||||
|
||||
/** A renderable mesh. Inherited by other mesh types. */
|
||||
class Mesh {
|
||||
public:
|
||||
Mesh() = default;
|
||||
|
||||
void cleanup();
|
||||
|
||||
public:
|
||||
/** Draws the mesh to the screen. */
|
||||
virtual void draw() const;
|
||||
|
||||
~Mesh();
|
||||
|
||||
protected:
|
||||
void genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr);
|
||||
protected:
|
||||
/** Generates the vertex and index arrays on the GPU. */
|
||||
void genArrays(usize vboLength, usize iboLength, const void* vertices, const void* indices);
|
||||
|
||||
void createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer);
|
||||
/** Creates a vertex attribute on the VBO. */
|
||||
void createVertexAttrib(u32 offset, u32 size, GLenum type, u32 stride, const void* pointer);
|
||||
|
||||
GLuint VAO = 0;
|
||||
GLuint VBO = 0;
|
||||
GLuint IBO = 0;
|
||||
GLsizei indCount = 0;
|
||||
usize indCount = 0;
|
||||
u32 VAO = 0, VBO = 0, IBO = 0;
|
||||
};
|
||||
|
|
|
@ -1,35 +1,36 @@
|
|||
//
|
||||
// Created by aurailus on 15/12/18.
|
||||
//
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <iostream>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "MeshChunk.h"
|
||||
|
||||
#include "client/graph/Renderer.h"
|
||||
#include "client/graph/mesh/ChunkMesh.h"
|
||||
|
||||
void MeshChunk::create(std::vector<ChunkVertex>& vertices, std::vector<unsigned int>& indices) {
|
||||
this->mesh = std::make_shared<ChunkMesh>();
|
||||
mesh->create(vertices, indices);
|
||||
}
|
||||
MeshChunk::MeshChunk(const vec3 pos, const vec<Vertex>& vertices, const vec<u32>& indices) :
|
||||
ChunkRenderElem(pos), mesh(make_unique<Mesh>(vertices, indices)) {}
|
||||
|
||||
void MeshChunk::draw(Renderer& renderer) {
|
||||
glm::mat4 model = glm::mat4(1.0);
|
||||
model = glm::translate(model, pos * static_cast<float>(16));
|
||||
model = glm::translate(model, pos * 16.f);
|
||||
renderer.setModelMatrix(model);
|
||||
mesh->draw();
|
||||
}
|
||||
|
||||
void MeshChunk::setPos(glm::vec3 pos) {
|
||||
this->pos = pos;
|
||||
}
|
||||
|
||||
glm::vec3 MeshChunk::getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool MeshChunk::updateChunkUse(glm::vec3 pos, bool used) {
|
||||
bool MeshChunk::updateChunkUse(ivec3 pos, bool used) {
|
||||
return used;
|
||||
}
|
||||
|
||||
MeshChunk::Mesh::Mesh(const vec<Vertex>& vertices, const vec<u32>& indices) {
|
||||
this->indCount = indices.size();
|
||||
|
||||
genArrays(vertices.size() * sizeof(Vertex), indices.size() * sizeof(u32), &vertices.front(), &indices.front());
|
||||
|
||||
u32 idx = 0;
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET(Vertex, position));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET(Vertex, texCoords));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET(Vertex, blendColor));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET(Vertex, blendMaskCoords));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET(Vertex, normal));
|
||||
createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET(Vertex, light));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET(Vertex, shaderMod));
|
||||
createVertexAttrib(idx, 3, GL_FLOAT, STRIDE_OFFSET(Vertex, modValues));
|
||||
}
|
|
@ -1,34 +1,51 @@
|
|||
//
|
||||
// Created by aurailus on 15/12/18.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Mesh.h"
|
||||
#include "util/Types.h"
|
||||
#include "ChunkRenderElem.h"
|
||||
#include "client/graph/Drawable.h"
|
||||
|
||||
class ChunkMesh;
|
||||
|
||||
class ChunkVertex;
|
||||
/**
|
||||
* A drawable mesh of a single chunk.
|
||||
*/
|
||||
|
||||
class MeshChunk : public ChunkRenderElem, Drawable {
|
||||
public:
|
||||
MeshChunk() = default;
|
||||
public:
|
||||
|
||||
void create(std::vector<ChunkVertex>& vertices, std::vector<unsigned int>& indices);
|
||||
/** A single vertex of a ChunkMesh. */
|
||||
struct Vertex {
|
||||
vec3 position;
|
||||
|
||||
vec2 texCoords;
|
||||
vec3 blendColor;
|
||||
vec2 blendMaskCoords;
|
||||
|
||||
f32 normal;
|
||||
vec4 light;
|
||||
|
||||
f32 shaderMod;
|
||||
vec3 modValues;
|
||||
};
|
||||
|
||||
/** Represents a MeshChunk's underlying mesh. */
|
||||
struct Mesh : public ::Mesh {
|
||||
Mesh(const Mesh&) = delete;
|
||||
Mesh(const vec<Vertex>& vertices, const vec<u32>& indices);
|
||||
};
|
||||
|
||||
/** Creates a new MeshChunk with the data provided. */
|
||||
MeshChunk(const vec3 pos, const vec<Vertex>& vertices, const vec<u32>& indices);
|
||||
|
||||
void draw(Renderer& renderer) override;
|
||||
|
||||
bool updateChunkUse(glm::vec3 chunk, bool used) override;
|
||||
bool updateChunkUse(ivec3 chunk, bool used) override;
|
||||
|
||||
private:
|
||||
|
||||
void setPos(glm::vec3 pos);
|
||||
|
||||
glm::vec3 getPos() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ChunkMesh> mesh = nullptr;
|
||||
glm::vec3 pos{};
|
||||
};
|
||||
/** The underlying mesh used by this chunk. */
|
||||
uptr<Mesh> mesh = nullptr;
|
||||
};
|
||||
|
||||
#pragma clang diagnostic pop
|
|
@ -13,142 +13,142 @@
|
|||
|
||||
DebugGui::DebugGui(u16vec2 buffer, SubgamePtr game, LocalWorld& world, vec<string>& perfSections) :
|
||||
game(game), world(world) {
|
||||
|
||||
|
||||
auto fontRef = game.l()->textures["font"];
|
||||
auto fpsHistogramRef = game.l()->textures["histogram"];
|
||||
auto genericHistogramRef = game.l()->textures["histogram_white"];
|
||||
|
||||
|
||||
Font f(game.l()->textures, fontRef);
|
||||
|
||||
|
||||
auto crosshairText = make_shared<GuiText>("crosshairText");
|
||||
crosshairText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f);
|
||||
add(crosshairText);
|
||||
|
||||
|
||||
auto dataText = make_shared<GuiText>("dataText");
|
||||
dataText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f);
|
||||
add(dataText);
|
||||
|
||||
|
||||
auto interpGraph = make_shared<GuiLabelledGraph>("interpGraph");
|
||||
interpGraph->create({ 244, 64 }, {}, "Interp", 120, 256, genericHistogramRef, f);
|
||||
add(interpGraph);
|
||||
|
||||
|
||||
auto meshGraph = make_shared<GuiLabelledGraph>("meshGraph");
|
||||
meshGraph->create({ 244, 64 }, {}, "Mesh", 120, 32, genericHistogramRef, f);
|
||||
add(meshGraph);
|
||||
|
||||
|
||||
auto genGraph = make_shared<GuiLabelledGraph>("genGraph");
|
||||
genGraph->create({ 244, 64 }, {}, "Gen", 120, 16, genericHistogramRef, f);
|
||||
add(genGraph);
|
||||
|
||||
|
||||
auto packetGraph = make_shared<GuiLabelledGraph>("packetGraph");
|
||||
packetGraph->create({ 244, 64 }, {}, "Packets", 120, 32, genericHistogramRef, f);
|
||||
add(packetGraph);
|
||||
|
||||
|
||||
auto fpsGraph = make_shared<GuiLabelledGraph>("fpsGraph");
|
||||
fpsGraph->create({ 244, 64 }, {}, "FPS", 120, 60, fpsHistogramRef, f);
|
||||
add(fpsGraph);
|
||||
|
||||
|
||||
auto drawsGraph = make_shared<GuiLabelledGraph>("drawsGraph");
|
||||
drawsGraph->create({ 244, 64 }, {}, "Draw Calls", 120, 0, genericHistogramRef, f);
|
||||
add(drawsGraph);
|
||||
|
||||
|
||||
auto gpuGraph = make_shared<GuiLabelledGraph>("gpuGraph");
|
||||
gpuGraph->create({ 244, 64 }, {}, "GPU", 120, 1, genericHistogramRef, f);
|
||||
add(gpuGraph);
|
||||
|
||||
|
||||
auto perfGraph = make_shared<GuiPerfGraph>("perfGraph");
|
||||
perfGraph->create(344, {}, perfSections, "Performance", f);
|
||||
add(perfGraph);
|
||||
|
||||
|
||||
auto chunkStates = make_shared<GuiCellGraph>("chunkStates");
|
||||
chunkStates->create(6, vec4(4), CHUNK_RANGE, "Chunk Compression", f);
|
||||
chunkStates->refresh();
|
||||
add(chunkStates);
|
||||
|
||||
|
||||
positionElements(buffer);
|
||||
}
|
||||
|
||||
void DebugGui::positionElements(u16vec2 buffer) {
|
||||
get<GuiText>("crosshairText")->setPos({ buffer.x / 2 + 22, buffer.y / 2 - 7 });
|
||||
get<GuiText>("dataText")->setPos({ 10, 10 });
|
||||
|
||||
|
||||
get<GuiLabelledGraph>("genGraph")->setPos({ buffer.x - 254, buffer.y - 70 - 160 });
|
||||
get<GuiLabelledGraph>("packetGraph")->setPos({ buffer.x - 254, buffer.y - 70 - 240 });
|
||||
get<GuiLabelledGraph>("meshGraph")->setPos({ buffer.x - 254, buffer.y - 70 - 80 });
|
||||
get<GuiLabelledGraph>("interpGraph")->setPos({ buffer.x - 254, buffer.y - 70 });
|
||||
|
||||
|
||||
get<GuiLabelledGraph>("fpsGraph")->setPos({ buffer.x - 254, 10 });
|
||||
get<GuiLabelledGraph>("drawsGraph")->setPos({ buffer.x - 254, 90 });
|
||||
get<GuiLabelledGraph>("gpuGraph")->setPos({ buffer.x - 254, 90 + 80 });
|
||||
get<GuiLabelledGraph>("perfGraph")->setPos({ buffer.x - 354 - 254, 10 });
|
||||
|
||||
|
||||
get<GuiLabelledGraph>("chunkStates")->setPos({ buffer.x - 264 - 300, buffer.y - 334 });
|
||||
}
|
||||
|
||||
void DebugGui::update(sptr<LocalPlayer> player, f64 delta, u32 interpolatedChunks, u32 generatedChunks,
|
||||
u32 recievedPackets, vec<usize>& perfTimings, u32 drawnMeshChunks, u32 generatedMeshChunks) {
|
||||
|
||||
|
||||
Target target = player->getTarget();
|
||||
|
||||
|
||||
auto& onBiomeDef = game->getBiomes().biomeFromId(
|
||||
world.getActiveDimension()->getBiome(glm::floor(player->getPos())));
|
||||
|
||||
|
||||
// FPS and Draw calls graphs
|
||||
|
||||
|
||||
get<GuiPerfGraph>("perfGraph")->updateTimings(perfTimings);
|
||||
get<GuiLabelledGraph>("fpsGraph")->pushValue(1 / delta);
|
||||
get<GuiLabelledGraph>("drawsGraph")->pushValue(drawnMeshChunks);
|
||||
|
||||
|
||||
int videoMemAvail, videoMemTotal;
|
||||
|
||||
|
||||
glGetIntegerv(0x9048, &videoMemTotal);
|
||||
glGetIntegerv(0x9049, &videoMemAvail);
|
||||
|
||||
|
||||
get<GuiLabelledGraph>("gpuGraph")->pushValue(std::round(
|
||||
(videoMemTotal - videoMemAvail) / static_cast<f32>(videoMemTotal) * 100.0) / 100.0f);
|
||||
|
||||
|
||||
|
||||
|
||||
// Thread information graphs
|
||||
|
||||
|
||||
get<GuiLabelledGraph>("meshGraph")->pushValue(generatedMeshChunks);
|
||||
get<GuiLabelledGraph>("interpGraph")->pushValue(interpolatedChunks);
|
||||
get<GuiLabelledGraph>("genGraph")->pushValue(generatedChunks);
|
||||
get<GuiLabelledGraph>("packetGraph")->pushValue(recievedPackets);
|
||||
|
||||
|
||||
// Textual information
|
||||
|
||||
|
||||
vec3 playerPos = glm::floor(player->getPos());
|
||||
vec3 chunkPos = Space::Chunk::world::fromBlock(playerPos);
|
||||
vec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos);
|
||||
vec3 regionPos = Space::Region::world::fromChunk(chunkPos);
|
||||
|
||||
|
||||
vec3 posOffsetFromChunk = Space::Block::relative::toChunk(playerPos);
|
||||
vec3 posOffsetFromBlock = Space::Block::relative::toMapBlock(playerPos);
|
||||
vec3 posOffsetFromRegion = Space::Block::relative::toRegion(playerPos);
|
||||
|
||||
|
||||
std::ostringstream str;
|
||||
|
||||
|
||||
str << "Dimension: " << world.getActiveDimension()->getIdentifier()
|
||||
<< " [" << world.getActiveDimension()->getInd() << "]" << std::endl << std::endl
|
||||
|
||||
|
||||
<< "Pos: " << playerPos << " (" << player->getPos() << ")" << std::endl
|
||||
<< "Vel: " << player->getVel() << std::endl
|
||||
|
||||
|
||||
<< "Yaw: " << player->getYaw() << ", "
|
||||
<< "Pitch: " << player->getPitch() << std::endl << std::endl
|
||||
|
||||
|
||||
<< "C: " << posOffsetFromChunk << " [" << chunkPos << "]" << std::endl
|
||||
<< "M: " << posOffsetFromBlock << " [" << mapBlockPos << "]" << std::endl
|
||||
<< "R: " << posOffsetFromRegion << " [" << regionPos << "]" << std::endl
|
||||
<< std::endl
|
||||
|
||||
|
||||
<< "Texture Slots: " << game.l()->textures.textureSlotsUsed << " / " << game.l()->textures.maxTextureSlots
|
||||
<< " ("
|
||||
<< round(game.l()->textures.textureSlotsUsed / static_cast<float>(game.l()->textures.maxTextureSlots) * 100)
|
||||
<< "%)" << std::endl << std::endl
|
||||
|
||||
|
||||
<< "Biome: " << onBiomeDef.identifier << " [" << onBiomeDef.index << "]" << std::endl << std::endl;
|
||||
|
||||
|
||||
if (target.type == Target::Type::BLOCK) {
|
||||
string face =
|
||||
target.data.block.face == EVec::TOP ? "Top" :
|
||||
|
@ -158,16 +158,16 @@ void DebugGui::update(sptr<LocalPlayer> player, f64 delta, u32 interpolatedChunk
|
|||
target.data.block.face == EVec::FRONT ? "Front" :
|
||||
target.data.block.face == EVec::BACK ? "Back" :
|
||||
"None (!)";
|
||||
|
||||
|
||||
const auto& def = game->getDefs().blockFromId(world.getActiveDimension()->getBlock(target.data.block.pos));
|
||||
|
||||
|
||||
str << "Pointing At: " << def.identifier << " [" << def.index << "]" << std::endl
|
||||
<< "Pointed Position: " << target.data.block.pos << std::endl
|
||||
<< "Pointed Face: " << face << std::endl;
|
||||
}
|
||||
else if (target.type == Target::Type::ENTITY) {
|
||||
const auto& entity = **world.getActiveDimension().l()->getEntityById(target.data.entity.id).entity;
|
||||
|
||||
|
||||
str << "Pointing At: " << (target.data.entity.id < 0 ? "Local" : "Server")
|
||||
<< " Entity #" << std::fabs(target.data.entity.id) << std::endl
|
||||
<< "Pointed Position: " << entity.getPos() << std::endl << std::endl;
|
||||
|
@ -175,44 +175,48 @@ void DebugGui::update(sptr<LocalPlayer> player, f64 delta, u32 interpolatedChunk
|
|||
else {
|
||||
str << "No Target" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// for (usize i = 0; i < perfTimings.size(); i++) {
|
||||
// str << perfSections[i] << ": " << perfTimings[i] << " ns." << std::endl;
|
||||
// }
|
||||
|
||||
|
||||
get<GuiText>("dataText")->setText(str.str());
|
||||
|
||||
|
||||
// Chunk States
|
||||
|
||||
auto chunkStates = get<GuiCellGraph>("chunkStates");
|
||||
ivec3 off = { 0, 0, 0 };
|
||||
for (off.x = 0; off.x < CHUNK_RANGE; off.x++) {
|
||||
for (off.z = 0; off.z < CHUNK_RANGE; off.z++) {
|
||||
f32 existAmount = 0;
|
||||
f32 compressedAmount = 0;
|
||||
ivec3 check = ivec3(chunkPos) + off -
|
||||
glm::ivec3(floor(CHUNK_RANGE / 2), 0, floor(CHUNK_RANGE / 2));
|
||||
|
||||
for (off.y = 0; off.y < CHUNK_VERT; off.y++) {
|
||||
check.y = static_cast<i32>(chunkPos.y) + off.y - CHUNK_VERT / 2;
|
||||
const auto chunk = world.getActiveDimension()->getChunk(check);
|
||||
if (chunk) {
|
||||
existAmount++;
|
||||
if (chunk->isCompressed()) compressedAmount++;
|
||||
|
||||
if (chunkTimer == 0) {
|
||||
auto chunkStates = get<GuiCellGraph>("chunkStates");
|
||||
ivec3 off = { 0, 0, 0 };
|
||||
for (off.x = 0; off.x < CHUNK_RANGE; off.x++) {
|
||||
for (off.z = 0; off.z < CHUNK_RANGE; off.z++) {
|
||||
f32 existAmount = 0;
|
||||
f32 compressedAmount = 0;
|
||||
ivec3 check = ivec3(chunkPos) + off -
|
||||
glm::ivec3(floor(CHUNK_RANGE / 2), 0, floor(CHUNK_RANGE / 2));
|
||||
|
||||
for (off.y = 0; off.y < CHUNK_VERT; off.y++) {
|
||||
check.y = static_cast<i32>(chunkPos.y) + off.y - CHUNK_VERT / 2;
|
||||
const auto chunk = world.getActiveDimension()->getChunk(check);
|
||||
if (chunk) {
|
||||
existAmount++;
|
||||
if (chunk->isCompressed()) compressedAmount++;
|
||||
}
|
||||
}
|
||||
|
||||
const auto color = glm::mix(CHUNK_UNLOADED,
|
||||
glm::mix(CHUNK_UNCOMPRESSED, CHUNK_COMPRESSED,
|
||||
compressedAmount / CHUNK_VERT),existAmount / CHUNK_VERT);
|
||||
|
||||
chunkStates->setCellColor(u16vec2(off.x, off.z), color);
|
||||
}
|
||||
|
||||
const auto color = glm::mix(CHUNK_UNLOADED,
|
||||
glm::mix(CHUNK_UNCOMPRESSED, CHUNK_COMPRESSED,
|
||||
compressedAmount / CHUNK_VERT),existAmount / CHUNK_VERT);
|
||||
|
||||
chunkStates->setCellColor(u16vec2(off.x, off.z), color);
|
||||
}
|
||||
chunkStates->refresh();
|
||||
}
|
||||
chunkStates->refresh();
|
||||
|
||||
chunkTimer = (chunkTimer + 1) % CHUNK_INTERVAL;
|
||||
|
||||
// Crosshair information
|
||||
|
||||
|
||||
if (target.type == Target::Type::BLOCK) {
|
||||
const auto& def = game->getDefs().blockFromId(world.getActiveDimension()->getBlock(target.data.block.pos));
|
||||
get<GuiText>("crosshairText")->setText(def.name + " (" + def.identifier + ") [" + std::to_string(def.index) + "]");
|
||||
|
|
|
@ -17,35 +17,38 @@ class LocalSubgame;
|
|||
|
||||
class DebugGui : public GuiContainer {
|
||||
public:
|
||||
|
||||
|
||||
enum class Visibility { OFF, FPS_ONLY, ON };
|
||||
|
||||
|
||||
DebugGui(u16vec2 buffer, SubgamePtr game, LocalWorld& world, vec<string>& perfSections);
|
||||
|
||||
|
||||
/** Resizes elements when the screen buffer is resized. */
|
||||
void bufferResized(u16vec2 bufferSize);
|
||||
|
||||
|
||||
/** Sets which elements are visible based on the state provided. */
|
||||
void changeVisibility(Visibility state);
|
||||
|
||||
|
||||
/** Positions all elements based on the buffer size. */
|
||||
void positionElements(u16vec2 buffer);
|
||||
|
||||
|
||||
/** Updates the debug screen with the latest data. */
|
||||
void update(sptr<LocalPlayer> player, f64 delta, u32 interpolatedChunks, u32 generatedChunks,
|
||||
u32 recievedPackets, vec<usize>& perfTimings, u32 drawnMeshChunks, u32 generatedMeshChunks);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
constexpr static vec4 CHUNK_UNLOADED = { 1, 1, 1, 0.15 };
|
||||
constexpr static vec4 CHUNK_COMPRESSED = { 1, 1, 1, 0.75 };
|
||||
constexpr static vec4 CHUNK_UNCOMPRESSED = { 1, 0, 0, 0.75 };
|
||||
|
||||
|
||||
constexpr static i32 CHUNK_VERT = 3;
|
||||
constexpr static i32 CHUNK_RANGE = 48;
|
||||
|
||||
|
||||
SubgamePtr game;
|
||||
LocalWorld& world;
|
||||
|
||||
|
||||
u16 chunkTimer = 0;
|
||||
constexpr static u16 CHUNK_INTERVAL = 5;
|
||||
|
||||
Visibility state = Visibility::ON;
|
||||
};
|
||||
|
|
|
@ -1,56 +1,52 @@
|
|||
//
|
||||
// Created by aurailus on 05/02/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "client/gui/GameGuiBuilder.h"
|
||||
#include "client/gui/compound/GuiInventoryList.h"
|
||||
|
||||
class GameGui {
|
||||
public:
|
||||
public:
|
||||
explicit GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer);
|
||||
|
||||
|
||||
void winResized(glm::ivec2 win);
|
||||
|
||||
|
||||
void update(double delta);
|
||||
|
||||
|
||||
void setVisible(bool visible);
|
||||
|
||||
|
||||
bool isVisible();
|
||||
|
||||
|
||||
void showMenu(std::shared_ptr<LuaGuiElement> root);
|
||||
|
||||
|
||||
void closeMenu();
|
||||
|
||||
|
||||
const bool isInMenu() const;
|
||||
|
||||
|
||||
void setHud(std::shared_ptr<LuaGuiElement> hud);
|
||||
|
||||
|
||||
std::shared_ptr<LuaGuiElement> getHud();
|
||||
|
||||
|
||||
void drawHud(Renderer& renderer);
|
||||
|
||||
|
||||
void drawMenu(Renderer& renderer);
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
SubgamePtr defs;
|
||||
Renderer& renderer;
|
||||
|
||||
glm::ivec2 win{};
|
||||
|
||||
ivec2 win {};
|
||||
bool inMenu = false;
|
||||
|
||||
|
||||
std::shared_ptr<LuaGuiElement> hudRootElem = nullptr;
|
||||
|
||||
|
||||
std::shared_ptr<GuiContainer> menuRoot = std::make_shared<GuiInventoryList>("menuRoot");
|
||||
std::shared_ptr<GuiContainer> menuLuaRoot = std::make_shared<GuiInventoryList>("menuLuaRoot");
|
||||
GameGuiBuilder menuBuilder;
|
||||
std::shared_ptr<GuiContainer> hudRoot = std::make_shared<GuiInventoryList>("hudRoot");
|
||||
std::shared_ptr<GuiContainer> hudLuaRoot = std::make_shared<GuiInventoryList>("hudLuaRoot");
|
||||
GameGuiBuilder hudBuilder;
|
||||
|
||||
|
||||
std::shared_ptr<GuiInventoryList> handList = std::make_shared<GuiInventoryList>("hand");
|
||||
|
||||
|
||||
InventoryRefsPtr refs;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* Initializes a connection to the remote address,
|
||||
* sets up the GUI, and attempts to download subgame assets.
|
||||
*
|
||||
* @param addr - The server address to connect to.
|
||||
* @param addr - The server address to init to.
|
||||
*/
|
||||
|
||||
ConnectScene::ConnectScene(Client& client, Address addr) : Scene(client),
|
||||
|
@ -210,7 +210,7 @@ void ConnectScene::handleConnecting() {
|
|||
|
||||
case ServerConnection::State::FAILED_CONNECT:
|
||||
connectState = State::FAILED_CONNECT;
|
||||
statusText->setText(statusText->getText() + "\nFailed to connect :(\n");
|
||||
statusText->setText(statusText->getText() + "\nFailed to init :(\n");
|
||||
break;
|
||||
|
||||
case ServerConnection::State::ATTEMPTING_CONNECT:
|
||||
|
|
|
@ -12,7 +12,7 @@ GameScene::GameScene(Client& client) : Scene(client),
|
|||
Packet r(Packet::Type::CONNECT_DATA_RECVD);
|
||||
r.sendTo(client.connection.getPeer(), Packet::Channel::CONNECT);
|
||||
|
||||
world.l()->connect();
|
||||
world.l()->init();
|
||||
client.game->init(world, world.l()->getPlayer(), client);
|
||||
world.l()->updatePlayerDimension();
|
||||
|
||||
|
@ -41,7 +41,7 @@ void GameScene::draw() {
|
|||
perf.start("draw:world");
|
||||
renderer.beginChunkDeferredCalls();
|
||||
renderer.enableTexture(&client.game->textures.atlasTexture);
|
||||
world.l()->drawWorld();
|
||||
world.l()->drawChunks();
|
||||
|
||||
perf.start("draw:entities");
|
||||
renderer.beginEntityDeferredCalls();
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
//
|
||||
// Created by aurailus on 23/07/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "client/graph/mesh/ChunkVertex.h"
|
||||
|
||||
struct ChunkMeshDetails {
|
||||
std::vector<ChunkVertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
glm::ivec3 pos {};
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// Created by aurailus on 23/07/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Types.h"
|
||||
#include "client/graph/mesh/MeshChunk.h"
|
||||
|
||||
|
||||
struct MeshChunkDetails {
|
||||
ivec3 pos {};
|
||||
vec<u32> indices;
|
||||
vec<MeshChunk::Vertex> vertices;
|
||||
};
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "MeshGenStream.h"
|
||||
|
||||
#include "ChunkMeshDetails.h"
|
||||
#include "MeshChunkDetails.h"
|
||||
#include "client/graph/mesh/ChunkMeshGenerator.h"
|
||||
#include "world/dim/chunk/Chunk.h"
|
||||
#include "world/dim/LocalDimension.h"
|
||||
|
@ -33,8 +33,8 @@ MeshGenStream::MeshGenStream(SubgamePtr game, LocalDimension& dimension) :
|
|||
for (int i = 0; i < THREADS; i++) threads.emplace_back(*game.l(), noiseSampler);
|
||||
}
|
||||
|
||||
std::vector<ChunkMeshDetails*> MeshGenStream::update() {
|
||||
std::vector<ChunkMeshDetails*> finishedChunks;
|
||||
std::vector<MeshChunkDetails*> MeshGenStream::update() {
|
||||
std::vector<MeshChunkDetails*> finishedChunks;
|
||||
|
||||
for (u16 i = 0; i < THREAD_QUEUE_SIZE; i++) {
|
||||
for (Thread& t : threads) {
|
||||
|
@ -44,7 +44,7 @@ std::vector<ChunkMeshDetails*> MeshGenStream::update() {
|
|||
if (j.meshDetails->vertices.size()) {
|
||||
j.thisChunk = nullptr;
|
||||
finishedChunks.push_back(j.meshDetails);
|
||||
j.meshDetails = new ChunkMeshDetails();
|
||||
j.meshDetails = new MeshChunkDetails();
|
||||
}
|
||||
|
||||
if (!queuedTasks.empty()) {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "util/Vec.h"
|
||||
#include "util/CovariantPtr.h"
|
||||
#include "ChunkMeshDetails.h"
|
||||
#include "MeshChunkDetails.h"
|
||||
#include "world/gen/NoiseSample.h"
|
||||
|
||||
class Chunk;
|
||||
|
@ -22,8 +22,8 @@ class LocalDimension;
|
|||
|
||||
class MeshGenStream {
|
||||
public:
|
||||
static const u16 THREADS = 4;
|
||||
static const u16 THREAD_QUEUE_SIZE = 16;
|
||||
static const u16 THREADS = 6;
|
||||
static const u16 THREAD_QUEUE_SIZE = 12;
|
||||
|
||||
explicit MeshGenStream(SubgamePtr game, LocalDimension& dimension);
|
||||
|
||||
|
@ -33,13 +33,13 @@ public:
|
|||
|
||||
//Will return a vector of MeshDetails pointers containing finished meshes.
|
||||
//Frees up the threads and starts new tasks.
|
||||
std::vector<ChunkMeshDetails*> update();
|
||||
std::vector<MeshChunkDetails*> update();
|
||||
|
||||
struct Job {
|
||||
std::unique_ptr<Chunk> thisChunk = nullptr;
|
||||
std::array<std::unique_ptr<Chunk>, 6> adjacentChunks {};
|
||||
|
||||
ChunkMeshDetails* meshDetails = new ChunkMeshDetails();
|
||||
MeshChunkDetails* meshDetails = new MeshChunkDetails();
|
||||
|
||||
bool busy = false;
|
||||
};
|
||||
|
|
|
@ -91,7 +91,6 @@ void WorldInterpolationStream::Thread::run() {
|
|||
u.chunks.reserve(64);
|
||||
while (!u.packet->d.atEnd()) {
|
||||
string data = u.packet->d.read<string>();
|
||||
// std::cout << Util::toString(Deserializer(data).read<ivec3>()) << std::endl;
|
||||
u.chunks.emplace_back(make_shared<Chunk>());
|
||||
u.chunks.back()->decompressFromString(data);
|
||||
}
|
||||
|
|
|
@ -22,52 +22,52 @@ class PacketView;
|
|||
|
||||
class WorldInterpolationStream {
|
||||
public:
|
||||
static const int THREADS = 4;
|
||||
static const int THREAD_QUEUE_SIZE = 16;
|
||||
|
||||
static const int THREADS = 1;
|
||||
static const int THREAD_QUEUE_SIZE = 1;
|
||||
|
||||
WorldInterpolationStream(LocalSubgame& game, LocalWorld& world, unsigned int seed);
|
||||
|
||||
|
||||
// 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<Chunk>>> update();
|
||||
|
||||
|
||||
~WorldInterpolationStream();
|
||||
|
||||
|
||||
private:
|
||||
// enum class JobType {
|
||||
// EMPTY,
|
||||
// PACKET,
|
||||
// FARMAP
|
||||
// };
|
||||
|
||||
|
||||
struct Job {
|
||||
bool locked = false;
|
||||
// JobType job = JobType::EMPTY;
|
||||
|
||||
|
||||
std::shared_ptr<PacketView> packet = nullptr;
|
||||
std::vector<std::shared_ptr<Chunk>> chunks = {};
|
||||
|
||||
// std::shared_ptr<MeshFarMap> mapblock = nullptr;
|
||||
// glm::vec3 mapBlockPos = {0, 0, 0};
|
||||
};
|
||||
|
||||
|
||||
struct Thread {
|
||||
explicit Thread(LocalSubgame& game, LocalWorld& world, unsigned int seed);
|
||||
|
||||
|
||||
void run();
|
||||
|
||||
|
||||
bool kill = false;
|
||||
|
||||
|
||||
std::vector<Job> jobs = std::vector<Job>(THREAD_QUEUE_SIZE);
|
||||
|
||||
|
||||
std::thread thread;
|
||||
};
|
||||
|
||||
|
||||
std::vector<Thread> threads;
|
||||
std::queue<std::unique_ptr<PacketView>> queuedPacketTasks;
|
||||
// std::unordered_set<glm::vec3, Vec::vec3> queuedInterpMap;
|
||||
|
|
|
@ -184,6 +184,7 @@ noise::module::Module* NoiseFromLua::parseNoise(std::vector<noise::module::Modul
|
|||
auto module = new noise::module::Voronoi();
|
||||
|
||||
module->SetSeed(noise.get_or<float>("seed", 0));
|
||||
// module->EnableDistance(noise.get_or<u32>("distance", false));
|
||||
module->SetDisplacement(noise.get_or<float>("displacement", 0));
|
||||
module->SetFrequency(noise.get_or<float>("frequency", 0));
|
||||
|
||||
|
@ -233,5 +234,19 @@ noise::module::Module* NoiseFromLua::parseNoise(std::vector<noise::module::Modul
|
|||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
|
||||
else if (type == "scale_point") {
|
||||
auto module = new noise::module::ScalePoint();
|
||||
sol::table source = noise["source"];
|
||||
|
||||
auto mod0 = parseNoise(modules, source);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetXScale(noise.get_or<float>("x_scale", 1));
|
||||
module->SetYScale(noise.get_or<float>("y_scale", 1));
|
||||
module->SetZScale(noise.get_or<float>("z_scale", 1));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
throw std::runtime_error("Invalid noise module specified.");
|
||||
}
|
|
@ -12,7 +12,7 @@ void Api::Module::Structure::bind() {
|
|||
|
||||
sol::object Api::Module::Structure::create_structure(sol::table data) {
|
||||
auto origin = data.get<sol::optional<glm::vec3>>("origin");
|
||||
// auto probability = data.get<float>("probability");
|
||||
auto probability = data.get<float>("probability");
|
||||
auto layout = data.get<sol::table>("layout");
|
||||
|
||||
unsigned int yWid = layout.size();
|
||||
|
@ -24,7 +24,7 @@ sol::object Api::Module::Structure::create_structure(sol::table data) {
|
|||
s->dimensions = { xWid, yWid, zWid };
|
||||
s->origin = origin ? glm::ivec3 { *origin } : glm::ivec3 {};
|
||||
s->layout.reserve(xWid * yWid * zWid);
|
||||
// s->probability = probability;
|
||||
s->probability = probability;
|
||||
|
||||
for (unsigned int x = 1; x <= xWid; x++)
|
||||
for (unsigned int y = 1; y <= yWid; y++)
|
||||
|
|
|
@ -12,16 +12,16 @@ namespace Api {
|
|||
if (!data) throw "expected a table as the first argument.";
|
||||
|
||||
auto origin = data->get<sol::optional<glm::vec3>>("origin");
|
||||
auto schematic = data->get<sol::optional<sol::table>>("schematic");
|
||||
auto layout = data->get < sol::optional < sol::table >> ("layout");
|
||||
|
||||
if (!origin) throw std::runtime_error("expected a table as the first argument.");
|
||||
if (!schematic) throw std::runtime_error("expected a table as the first argument.");
|
||||
if (!layout) throw std::runtime_error("expected a table as the first argument.");
|
||||
|
||||
auto s = std::make_shared<Schematic>();
|
||||
|
||||
unsigned int yWid = schematic->size();
|
||||
unsigned int zWid = (*schematic).get<sol::table>(1).size();
|
||||
unsigned int xWid = (*schematic).get<sol::table>(1).get<sol::table>(1).size();
|
||||
unsigned int yWid = layout->size();
|
||||
unsigned int zWid = (*layout).get<sol::table>(1).size();
|
||||
unsigned int xWid = (*layout).get<sol::table>(1).get<sol::table>(1).size();
|
||||
|
||||
s->dimensions = { xWid, yWid, zWid };
|
||||
s->stringData.resize(xWid * yWid * zWid);
|
||||
|
@ -32,7 +32,7 @@ namespace Api {
|
|||
for (unsigned int z = 1; z <= zWid; z++) {
|
||||
for (unsigned int x = 1; x <= xWid; x++) {
|
||||
s->stringData[s->index({ x - 1, y - 1, z - 1 })] =
|
||||
schematic->get<sol::table>(y).get<sol::table>(z).get_or<std::string>(x, "");
|
||||
layout->get<sol::table>(y).get<sol::table>(z).get_or<std::string>(x, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ void Server::update() {
|
|||
const static i64 interval_ns = static_cast<i64>((1000 / 60.f) * 1000000L);
|
||||
Timer loop("");
|
||||
|
||||
world->update(delta);
|
||||
world.s()->update(delta);
|
||||
game.s()->update(delta);
|
||||
|
||||
// Read incoming events.
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
//
|
||||
// Created by aurailus on 09/01/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Types.h"
|
||||
|
@ -12,9 +8,8 @@
|
|||
#include "server/ServerClients.h"
|
||||
#include "world/inv/ServerInventoryRefs.h"
|
||||
|
||||
class ServerPlayer;
|
||||
|
||||
class Packet;
|
||||
class ServerPlayer;
|
||||
|
||||
class Server {
|
||||
public:
|
||||
|
|
|
@ -36,7 +36,7 @@ void ServerClients::createPlayer(sptr<ServerClient> client, DimensionPtr dimensi
|
|||
client->player = make_shared<ServerPlayer>(*client, dimension->getWorld(), game, dimension);
|
||||
|
||||
game.s()->getParser().playerConnected(client->player);
|
||||
client->player->setPos({ 256, -20, 256 }, true);
|
||||
// client->player->setPos({ 256, -20, 256 }, true);
|
||||
|
||||
Serializer()
|
||||
.append(NetField::ID).append(static_cast<u32>(client->player->getId()))
|
||||
|
|
|
@ -44,8 +44,11 @@ std::unique_ptr<std::vector<std::unique_ptr<ServerPacketStream::FinishedJob>>> S
|
|||
inProgressMap.emplace(pos);
|
||||
queuedTasks.pop();
|
||||
|
||||
// std::cout << "going going" << std::endl;
|
||||
auto mapBlock = world.getDimension(pos.w)->getMapBlock(ivec3(pos));
|
||||
if (!mapBlock) continue;
|
||||
// std::cout << Util::toString(pos) << ": gone, " << mapBlock << std::endl;
|
||||
if (mapBlock == nullptr) continue;
|
||||
// std::cout << "mappi: " << Util::toString(j.mapBlock->pos) << std::endl;
|
||||
j.mapBlock = make_unique<MapBlock>(*mapBlock);
|
||||
j.dim = pos.w;
|
||||
j.locked = true;
|
||||
|
@ -62,6 +65,7 @@ void ServerPacketStream::Thread::run() {
|
|||
for (Job& j : jobs) {
|
||||
if (j.locked) {
|
||||
empty = false;
|
||||
std::cout << "run: " << Util::toString(j.mapBlock->pos) << std::endl;
|
||||
|
||||
Serializer s {};
|
||||
for (u16 i = 0; i < 64; i++) {
|
||||
|
|
|
@ -40,17 +40,25 @@ using vec2 = glm::f32vec2;
|
|||
using vec3 = glm::f32vec3;
|
||||
using vec4 = glm::f32vec4;
|
||||
|
||||
using glm::i8vec2;
|
||||
using glm::i8vec3;
|
||||
using glm::i8vec4;
|
||||
using glm::i16vec2;
|
||||
using glm::i16vec3;
|
||||
using glm::i16vec4;
|
||||
using ivec2 = glm::i32vec2;
|
||||
using ivec3 = glm::i32vec3;
|
||||
using ivec4 = glm::i32vec4;
|
||||
using glm::i16vec2, glm::i16vec3, glm::i16vec4;
|
||||
using glm::i8vec2, glm::i8vec3, glm::i8vec4;
|
||||
|
||||
using glm::u8vec2;
|
||||
using glm::u8vec3;
|
||||
using glm::u8vec4;
|
||||
using glm::u16vec2;
|
||||
using glm::u16vec3;
|
||||
using glm::u16vec4;
|
||||
using uvec2 = glm::u32vec2;
|
||||
using uvec3 = glm::u32vec3;
|
||||
using uvec4 = glm::u32vec4;
|
||||
using glm::u16vec2, glm::u16vec3, glm::u16vec4;
|
||||
using glm::u8vec2, glm::u8vec3, glm::u8vec4;
|
||||
|
||||
using std::array;
|
||||
using std::string;
|
||||
|
@ -63,6 +71,7 @@ using sptr = std::shared_ptr<T>;
|
|||
template <typename T>
|
||||
using uptr = std::unique_ptr<T>;
|
||||
|
||||
using std::make_shared, std::make_unique;
|
||||
using std::make_shared;
|
||||
using std::make_unique;
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
#pragma clang diagnostic pop
|
||||
|
|
|
@ -4,14 +4,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
|
||||
#include "util/Log.h"
|
||||
#include "util/Types.h"
|
||||
|
@ -23,7 +19,7 @@ namespace Util {
|
|||
return static_cast<usize>(t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
|
||||
inline static string toFixed(T val, u8 precision = 2) {
|
||||
std::ostringstream out;
|
||||
|
@ -31,17 +27,17 @@ namespace Util {
|
|||
out << std::fixed << val;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
|
||||
static string toString(T val) {
|
||||
return std::to_string(val);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
|
||||
static string toString(T val) {
|
||||
return toFixed<T>(val);
|
||||
}
|
||||
|
||||
|
||||
template <typename V, std::enable_if_t<std::is_trivially_copyable_v<typename V::value_type> &&
|
||||
std::is_same_v<vec<typename V::value_type>, V>, bool> = true>
|
||||
static string toString(V vec) {
|
||||
|
@ -51,7 +47,7 @@ namespace Util {
|
|||
out << " ]";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
template <typename A, std::enable_if_t<std::is_trivially_copyable_v<typename A::value_type> &&
|
||||
std::is_same_v<array<typename A::value_type, A::size_type>, A>, bool> = true>
|
||||
static string toString(A arr) {
|
||||
|
@ -59,7 +55,7 @@ namespace Util {
|
|||
for (usize i = 0; i < arr.size(); i++) out << (i == 0 ? "" : ", ") << arr[i];
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral_v<typename T::value_type> &&
|
||||
std::is_integral_v<typename T::length_type>, bool> = true>
|
||||
static string toString(T vec) {
|
||||
|
@ -67,7 +63,7 @@ namespace Util {
|
|||
for (usize i = 0; i < T::length(); i++) out << (i == 0 ? "" : ", ") << vec[i];
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_floating_point_v<typename T::value_type> &&
|
||||
std::is_integral_v<typename T::length_type>, bool> = true>
|
||||
static string toString(T vec) {
|
||||
|
@ -75,16 +71,16 @@ namespace Util {
|
|||
for (usize i = 0; i < T::length(); i++) out << (i == 0 ? "" : ", ") << toString<typename T::value_type>(vec[i]);
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
inline static f32 packFloat(const vec3& vec) {
|
||||
auto charX = static_cast<u8>((vec.x + 1.0f) * 0.5f * 255.f);
|
||||
auto charY = static_cast<u8>((vec.y + 1.0f) * 0.5f * 255.f);
|
||||
auto charZ = static_cast<u8>((vec.z + 1.0f) * 0.5f * 255.f);
|
||||
|
||||
|
||||
u32 packedInt = (charX << 16) | (charY << 8) | charZ;
|
||||
return static_cast<f32>(static_cast<f64>(packedInt) / static_cast<f64>(1 << 24));
|
||||
}
|
||||
|
||||
|
||||
inline static u32 intFromHexSegment(const string& t) {
|
||||
u32 x;
|
||||
std::stringstream ss;
|
||||
|
@ -92,15 +88,15 @@ namespace Util {
|
|||
ss >> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
static vec4 hexToColorVec(string hex) {
|
||||
vec4 color{};
|
||||
|
||||
vec4 color {};
|
||||
|
||||
if (hex[0] == '#') hex.erase(0, 1);
|
||||
else std::cout << Log::err << "Color string does not begin with hash!" << Log::endl;
|
||||
|
||||
|
||||
string r, g, b, a;
|
||||
|
||||
|
||||
if (hex.length() == 3 || hex.length() == 4) {
|
||||
r = hex.substr(0, 1);
|
||||
r += r;
|
||||
|
@ -121,19 +117,19 @@ namespace Util {
|
|||
std::cout << Log::err << "Color string \"" + hex + "\" is of incorrect length!" << Log::endl;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
color.r = intFromHexSegment(r) / 255.f;
|
||||
color.g = intFromHexSegment(g) / 255.f;
|
||||
color.b = intFromHexSegment(b) / 255.f;
|
||||
color.a = intFromHexSegment(a) / 255.f;
|
||||
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
static string getKeyStr(u16 key) {
|
||||
switch (key) {
|
||||
default: return "";
|
||||
|
||||
|
||||
case 0: return "mouse0";
|
||||
case 1: return "mouse1";
|
||||
case 2: return "mouse2";
|
||||
|
@ -146,7 +142,7 @@ namespace Util {
|
|||
case 9: return "scrolldown";
|
||||
case 10: return "scrollleft";
|
||||
case 11: return "scrollright";
|
||||
|
||||
|
||||
case 32: return "space";
|
||||
case 39: return "'";
|
||||
case 44: return ",";
|
||||
|
@ -267,22 +263,22 @@ namespace Util {
|
|||
case 348: return "menu";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
constexpr static u64 mix(char m, u64 s) {
|
||||
return ((s << 7) + ~(s >> 3)) + ~m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
constexpr static u64 hash(const char* m) {
|
||||
return (*m) ? mix(*m, hash(m + 1)) : 0;
|
||||
}
|
||||
|
||||
|
||||
template<class C, typename Ret, typename ... Ts>
|
||||
std::function<Ret(Ts...)> bind_this(C* c, Ret (C::*m)(Ts...)) {
|
||||
return [=](auto&& ... args) { return (c->*m)(std::forward<decltype(args)>(args)...); };
|
||||
}
|
||||
|
||||
|
||||
template<class C, typename Ret, typename ... Ts>
|
||||
std::function<Ret(Ts...)> bind_this(const C* c, Ret (C::*m)(Ts...) const) {
|
||||
return [=](auto&& ... args) { return (c->*m)(std::forward<decltype(args)>(args)...); };
|
||||
|
@ -293,4 +289,4 @@ template <typename T, std::enable_if_t<std::is_trivial_v<T>
|
|||
|| (std::is_trivial_v<typename T::value_type> && std::is_integral_v<typename T::length_type>), bool> = true>
|
||||
std::ostream& operator<<(std::ostream& out, const T& t) {
|
||||
return out << Util::toString(t);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,13 +87,13 @@ void NetHandler::initClient(Address hostAddress, int attempts, int timeout) {
|
|||
else {
|
||||
enet_peer_reset(peer);
|
||||
if (attempt < attempts) {
|
||||
std::cout << Log::info << "Failed to connect to peer, retrying." << Log::endl;
|
||||
std::cout << Log::info << "Failed to init to peer, retrying." << Log::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state == NetState::FAILED_CONNECT) {
|
||||
std::cout << Log::err << "Failed to connect to peer." << Log::endl;
|
||||
std::cout << Log::err << "Failed to init to peer." << Log::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
//
|
||||
// Created by aurailus on 14/12/18.
|
||||
//
|
||||
|
||||
#include "LocalWorld.h"
|
||||
|
||||
#include "util/PerfTimer.h"
|
||||
#include "util/net/PacketView.h"
|
||||
#include "client/graph/Renderer.h"
|
||||
#include "world/player/LocalPlayer.h"
|
||||
|
@ -13,12 +10,12 @@ LocalWorld::LocalWorld(SubgamePtr game, ServerConnection& conn, Renderer& render
|
|||
World(game),
|
||||
renderer(renderer),
|
||||
net(conn, *this),
|
||||
refs(make_shared<LocalInventoryRefs>(game, net)),
|
||||
debugGui(renderer.window.getSize(), game, *this, perfSections),
|
||||
refs(std::make_shared<LocalInventoryRefs>(game, net)),
|
||||
worldGenStream(std::make_shared<WorldInterpolationStream>(*game.l(), *this, 55)),
|
||||
player(std::make_shared<LocalPlayer>(game, *this, DimensionPtr(nullptr), renderer)) {}
|
||||
worldGenStream(make_shared<WorldInterpolationStream>(*game.l(), *this, 55)),
|
||||
player(make_shared<LocalPlayer>(game, *this, DimensionPtr(nullptr), renderer)) {}
|
||||
|
||||
void LocalWorld::connect() {
|
||||
void LocalWorld::init() {
|
||||
net.init(Util::bind_this(&(*refs), &LocalInventoryRefs::packetReceived));
|
||||
refs->init();
|
||||
}
|
||||
|
@ -30,27 +27,28 @@ bool LocalWorld::updatePlayerDimension() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void LocalWorld::update(double delta, vec<usize>& perfTimings, PerfTimer& perf) {
|
||||
void LocalWorld::update(f64 delta, vec<usize>& perfTimings, PerfTimer& perf) {
|
||||
|
||||
// Updates the dimensions.
|
||||
perf.start("update:world");
|
||||
World::update(delta);
|
||||
for (auto& dimension : dimensions) dimension->update(delta);
|
||||
|
||||
// Update children
|
||||
|
||||
perf.start("update:player");
|
||||
if (*player) player.l()->update(renderer.window.input, delta, renderer.window.input.mouseDelta());
|
||||
refs->update(delta, net);
|
||||
|
||||
// Update the network
|
||||
perf.start("update:net");
|
||||
net.update();
|
||||
|
||||
// Commit interpolated mapblocks
|
||||
|
||||
perf.start("update:chunks");
|
||||
auto finishedChunks = worldGenStream->update();
|
||||
lastInterpolations = finishedChunks->size() / 64;
|
||||
for (const auto& chunk : *finishedChunks) commitChunk(chunk);
|
||||
|
||||
// Update debug interface
|
||||
|
||||
perf.start("update:debug");
|
||||
debugGui.update(
|
||||
player.l(), delta,
|
||||
|
@ -60,7 +58,6 @@ void LocalWorld::update(double delta, vec<usize>& perfTimings, PerfTimer& perf)
|
|||
activeDimension->getMeshChunksCommitted());
|
||||
|
||||
// Toggle regular interface
|
||||
|
||||
if (renderer.window.input.keyPressed(GLFW_KEY_F1)) {
|
||||
hudVisible = !hudVisible;
|
||||
debugGui.changeVisibility(hudVisible ? debugVisible ? DebugGui::Visibility::OFF :
|
||||
|
@ -69,7 +66,6 @@ void LocalWorld::update(double delta, vec<usize>& perfTimings, PerfTimer& perf)
|
|||
}
|
||||
|
||||
// Toggle debug interface
|
||||
|
||||
if (renderer.window.input.keyPressed(GLFW_KEY_F3)) {
|
||||
debugVisible = !debugVisible;
|
||||
debugGui.changeVisibility(hudVisible ? debugVisible ? DebugGui::Visibility::OFF :
|
||||
|
@ -77,11 +73,11 @@ void LocalWorld::update(double delta, vec<usize>& perfTimings, PerfTimer& perf)
|
|||
}
|
||||
}
|
||||
|
||||
void LocalWorld::handleWorldPacket(std::unique_ptr<PacketView> p) {
|
||||
void LocalWorld::handleWorldPacket(uptr<PacketView> p) {
|
||||
worldGenStream->queuePacket(std::move(p));
|
||||
}
|
||||
|
||||
void LocalWorld::handlePlayerEntPacket(std::unique_ptr<PacketView> p) {
|
||||
void LocalWorld::handlePlayerEntPacket(uptr<PacketView> p) {
|
||||
if (!player) throw std::runtime_error("Received playerEnt info *before* the player was created.");
|
||||
|
||||
u32 id = p->d.read<u32>();
|
||||
|
@ -107,25 +103,26 @@ void LocalWorld::handlePlayerEntPacket(std::unique_ptr<PacketView> p) {
|
|||
// getActiveDimension().playerEntities.emplace_back(p->d.read<glm::vec3>(), id, playerModel);
|
||||
}
|
||||
|
||||
void LocalWorld::handleModMessage(const std::string& channel, const std::string& message) {
|
||||
void LocalWorld::handleModMessage(const string& channel, const string& message) {
|
||||
game->getParser().safe_function(game->getParser().core["trigger"], "message",
|
||||
channel, game->getParser().safe_function(game->getParser().core["deserialize"], message));
|
||||
}
|
||||
|
||||
void LocalWorld::commitChunk(std::shared_ptr<Chunk> c) {
|
||||
void LocalWorld::commitChunk(sptr<Chunk> c) {
|
||||
activeDimension->setChunk(std::move(c));
|
||||
}
|
||||
|
||||
DimensionPtr LocalWorld::createDimension(const std::string& identifier, std::unordered_set<std::string>& biomes) {
|
||||
DimensionPtr LocalWorld::createDimension(const string& identifier, std::unordered_set<string>& biomes) {
|
||||
auto mapGen = std::make_shared<MapGen>(**game, *this, 0 /* TODO: Get the seed here */, biomes);
|
||||
dimensions.emplace_back(std::make_shared<LocalDimension>(
|
||||
game, *this, identifier, this->dimensions.size(), std::move(mapGen)));
|
||||
|
||||
dimensionIndexes[identifier] = dimensions.size() - 1;
|
||||
DimensionPtr d = dimensions.back();
|
||||
return d;
|
||||
}
|
||||
|
||||
void LocalWorld::sendMessage(const std::string& channel, const std::string& message) {
|
||||
void LocalWorld::sendMessage(const string& channel, const string& message) {
|
||||
net.sendPacket(Serializer().append(channel).append(message)
|
||||
.packet(Packet::Type::MOD_MESSAGE), Packet::Channel::INTERACT);
|
||||
}
|
||||
|
@ -135,8 +132,8 @@ DimensionPtr LocalWorld::getActiveDimension() {
|
|||
}
|
||||
|
||||
void LocalWorld::setActiveDimension(DimensionPtr dim) {
|
||||
this->activeDimension->deactivate();
|
||||
this->activeDimension = dim.l();
|
||||
activeDimension->deactivate();
|
||||
activeDimension = dim.l();
|
||||
}
|
||||
|
||||
ClientNetworkInterpreter& LocalWorld::getNet() {
|
||||
|
@ -151,7 +148,7 @@ InventoryRefsPtr LocalWorld::getRefs() {
|
|||
return refs;
|
||||
}
|
||||
|
||||
void LocalWorld::drawWorld() {
|
||||
void LocalWorld::drawChunks() {
|
||||
activeDimension->renderChunks(renderer);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,76 +1,109 @@
|
|||
//
|
||||
// Created by aurailus on 14/12/18.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "World.h"
|
||||
|
||||
#include "util/PerfTimer.h"
|
||||
#include "client/gui/DebugGui.h"
|
||||
#include "world/dim/LocalDimension.h"
|
||||
#include "client/conn/ClientNetworkInterpreter.h"
|
||||
|
||||
class Window;
|
||||
class Renderer;
|
||||
class PerfTimer;
|
||||
class LocalPlayer;
|
||||
class LocalSubgame;
|
||||
class LocalInventoryRefs;
|
||||
class WorldInterpolationStream;
|
||||
|
||||
/**
|
||||
* Manages the local active dimension,
|
||||
* and communication between the client and the server.
|
||||
*/
|
||||
|
||||
class LocalWorld : public World {
|
||||
public:
|
||||
|
||||
LocalWorld(SubgamePtr game, ServerConnection& conn, Renderer& window, vec<string>& perfSections);
|
||||
|
||||
void connect();
|
||||
/** Initializes the world, binding callbacks to the network handler. */
|
||||
void init();
|
||||
|
||||
/** Sets the player's dimension to the default one, if it exists. TODO: Could this be done in init()? */
|
||||
bool updatePlayerDimension();
|
||||
|
||||
void update(double delta, vec<usize>& perfTimings, PerfTimer& perf);
|
||||
/** Updates the dimension and the player, reads incoming packets, and commits decoded chunks. TODO: Decoding all the chunks from the getgo seems unnecessary... */
|
||||
void update(f64 delta, vec<usize>& perfTimings, PerfTimer& perf);
|
||||
|
||||
void handleWorldPacket(std::unique_ptr<PacketView> p);
|
||||
/** Queues a packet to be read. */
|
||||
void handleWorldPacket(uptr<PacketView> p);
|
||||
|
||||
void handlePlayerEntPacket(std::unique_ptr<PacketView> p);
|
||||
/** Reads a player entity packet, and updates the required entity. */
|
||||
void handlePlayerEntPacket(uptr<PacketView> p);
|
||||
|
||||
void handleModMessage(const std::string& channel, const std::string& message);
|
||||
/** Triggers a callback in lua for the provided mod message. */
|
||||
void handleModMessage(const string& channel, const string& message);
|
||||
|
||||
void commitChunk(std::shared_ptr<Chunk> chunk);
|
||||
/** Sets a chunk in the current dimension. */
|
||||
void commitChunk(sptr<Chunk> chunk);
|
||||
|
||||
virtual void sendMessage(const std::string& channel, const std::string& message) override;
|
||||
/** Sends a mod message to the server on the channel specified. */
|
||||
virtual void sendMessage(const string& channel, const string& message) override;
|
||||
|
||||
virtual DimensionPtr
|
||||
createDimension(const std::string& identifier, std::unordered_set<std::string>& biomes) override;
|
||||
/** Creates a new dimension with the identifier and biomes provided. */
|
||||
virtual DimensionPtr createDimension(const string& identifier, std::unordered_set<string>& biomes) override;
|
||||
|
||||
/** Gets the active dimension. */
|
||||
DimensionPtr getActiveDimension();
|
||||
|
||||
/** Sets the active dimension. */
|
||||
void setActiveDimension(DimensionPtr);
|
||||
|
||||
/** Gets the local player. */
|
||||
PlayerPtr getPlayer();
|
||||
|
||||
/** Returns a reference to the local inventory refs. */
|
||||
virtual InventoryRefsPtr getRefs() override;
|
||||
|
||||
/** Returns a reference to the network handler. */
|
||||
ClientNetworkInterpreter& getNet();
|
||||
|
||||
/** Renders the visible block chunks to the screen. */
|
||||
void drawWorld();
|
||||
/** Renders the visible entities to the screen. */
|
||||
/** Renders the visible chunks to the screen. */
|
||||
void drawChunks();
|
||||
|
||||
/** Renders the entities to the screen. */
|
||||
void drawEntities();
|
||||
/** Renders non-diagetic (UI) elements to the screen using an orthographic projection. */
|
||||
|
||||
/** Renders the interface to the screen using an orthographic projection. */
|
||||
void drawInterface();
|
||||
|
||||
private:
|
||||
|
||||
/** A reference to the renderer. */
|
||||
Renderer& renderer;
|
||||
|
||||
/** The network handler. */
|
||||
ClientNetworkInterpreter net;
|
||||
std::shared_ptr<LocalInventoryRefs> refs;
|
||||
|
||||
/** The local inventories. */
|
||||
sptr<LocalInventoryRefs> refs;
|
||||
|
||||
/** The local player. */
|
||||
PlayerPtr player;
|
||||
|
||||
/** The debug interface. */
|
||||
DebugGui debugGui;
|
||||
uint32_t lastInterpolations = 0;
|
||||
|
||||
/** The number of chunks that were interpolated last frome. */
|
||||
u32 lastInterpolations = 0;
|
||||
|
||||
/** Whether or not the hud should be visible. */
|
||||
bool hudVisible = true;
|
||||
|
||||
/** Whether or not the debug interface should be visible. */
|
||||
bool debugVisible = true;
|
||||
|
||||
std::shared_ptr<LocalDimension> activeDimension = nullptr;
|
||||
std::shared_ptr<WorldInterpolationStream> worldGenStream = nullptr;
|
||||
/** A pointer to the active dimension. */
|
||||
sptr<LocalDimension> activeDimension = nullptr;
|
||||
|
||||
/** A reference to the world gen stream. */
|
||||
sptr<WorldInterpolationStream> worldGenStream;
|
||||
};
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
//
|
||||
// Created by aurailus on 05/03/19.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_map>
|
||||
#include <util/Timer.h>
|
||||
|
||||
#include "ServerWorld.h"
|
||||
|
||||
|
@ -22,33 +19,28 @@
|
|||
#include "server/stream/ServerGenStream.h"
|
||||
#include "server/stream/ServerPacketStream.h"
|
||||
|
||||
ServerWorld::ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clients) :
|
||||
ServerWorld::ServerWorld(u32 seed, SubgamePtr game, ServerClients& clients) :
|
||||
World(game),
|
||||
seed(seed),
|
||||
clients(clients),
|
||||
refs(std::make_shared<ServerInventoryRefs>(game, clients)) {
|
||||
refs(make_shared<ServerInventoryRefs>(game, clients)) {
|
||||
clients.init(this);
|
||||
|
||||
generateOrder.reserve(mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.y * 2 + 1);
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> found {};
|
||||
std::queue<glm::ivec3> queue {};
|
||||
std::unordered_set<ivec3, Vec::ivec3> found {};
|
||||
std::queue<ivec3> queue {};
|
||||
|
||||
queue.emplace(0, 0, 0);
|
||||
found.emplace(0, 0, 0);
|
||||
|
||||
const std::vector<glm::ivec3> dirs{
|
||||
ivec3 { 1, 0, 0 }, ivec3{ -1, 0, 0 },
|
||||
ivec3 { 0, 1, 0 }, ivec3{ 0, -1, 0 },
|
||||
ivec3 { 0, 0, 1 }, ivec3{ 0, 0, -1 }};
|
||||
|
||||
while (!queue.empty()) {
|
||||
glm::ivec3 pos = queue.front();
|
||||
ivec3 pos = queue.front();
|
||||
queue.pop();
|
||||
|
||||
generateOrder.push_back(pos);
|
||||
|
||||
for (auto dir : dirs) {
|
||||
glm::ivec3 offset = pos + dir;
|
||||
for (auto dir : Vec::TO_VEC) {
|
||||
ivec3 offset = pos + dir;
|
||||
if (offset.x < -mapBlockGenRange.x || offset.x > mapBlockGenRange.x ||
|
||||
offset.y < -mapBlockGenRange.y || offset.y > mapBlockGenRange.y ||
|
||||
offset.z < -mapBlockGenRange.x || offset.z > mapBlockGenRange.x ||
|
||||
|
@ -62,43 +54,67 @@ ServerWorld::ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clie
|
|||
}
|
||||
}
|
||||
|
||||
void ServerWorld::init(const std::string& worldDir) {
|
||||
genStream = std::make_unique<ServerGenStream>(*game.s(), *this);
|
||||
packetStream = std::make_unique<ServerPacketStream>(*this);
|
||||
void ServerWorld::init(const string& worldDir) {
|
||||
genStream = make_unique<ServerGenStream>(*game.s(), *this);
|
||||
// packetStream = make_unique<ServerPacketStream>(*this);
|
||||
// fileManip = std::make_shared<FileManipulator>("worlds/" + worldDir + "/");
|
||||
}
|
||||
|
||||
void ServerWorld::update(double delta) {
|
||||
World::update(delta);
|
||||
void ServerWorld::update(f64 delta) {
|
||||
for (auto& dimension : dimensions) dimension->update(delta);
|
||||
|
||||
refs->update();
|
||||
|
||||
u32 genCount = 0;
|
||||
std::unordered_set<ivec4, Vec::ivec4> updatedChunks {};
|
||||
|
||||
auto finishedGen = genStream->update();
|
||||
// if (finishedGen->size()) std::cout << finishedGen->size() << " finished gens" << std::endl;
|
||||
|
||||
Timer t("Finishing Generation");
|
||||
for (auto& data : *finishedGen) {
|
||||
let dim = getDimension(data.dim);
|
||||
for (const auto& chunkPair : *data.created) {
|
||||
updatedChunks.insert(ivec4(chunkPair.first, data.dim));
|
||||
getDimension(data.dim)->setChunk(sptr<Chunk>(chunkPair.second));
|
||||
dim->setChunk(sptr<Chunk>(chunkPair.second));
|
||||
}
|
||||
|
||||
// Mapblock might have been pruned in between generation assignment and now.
|
||||
auto mb = getDimension(data.dim)->getMapBlock(glm::ivec3(data.pos));
|
||||
if (mb) mb->generated = true;
|
||||
auto mapBlock = dim->getMapBlock(ivec3(data.pos));
|
||||
|
||||
packetStream->queue(data.dim, data.pos);
|
||||
genCount++;
|
||||
if (!mapBlock->generated) {
|
||||
mapBlock->generated = true;
|
||||
assert(mapBlock);
|
||||
|
||||
Serializer s {};
|
||||
for (u16 i = 0; i < 64; i++) {
|
||||
auto chunk = mapBlock->get(i);
|
||||
assert(chunk);
|
||||
if (chunk) s.append(chunk->compressToString());
|
||||
}
|
||||
|
||||
let packet = s.packet(Packet::Type::MAPBLOCK);
|
||||
|
||||
for (auto& client : clients.getClients()) {
|
||||
if (!client.second->player) continue;
|
||||
packet.sendTo(client.second->peer, Packet::Channel::WORLD);
|
||||
}
|
||||
|
||||
genCount++;
|
||||
totalGens++;
|
||||
}
|
||||
}
|
||||
if (!finishedGen->empty()) {
|
||||
t.printElapsedMs();
|
||||
std::cout << totalGens << std::endl;
|
||||
}
|
||||
|
||||
auto finishedPackets = packetStream->update();
|
||||
// auto finishedPackets = packetStream->update();
|
||||
// if (finishedPackets->size()) std::cout << finishedPackets->size() << " finished packets" << std::endl;
|
||||
for (auto& data : *finishedPackets) {
|
||||
for (auto& client : clients.getClients()) {
|
||||
if (!client.second->player) continue;
|
||||
data->packet->sendTo(client.second->peer, Packet::Channel::WORLD);
|
||||
}
|
||||
}
|
||||
// for (auto& data : *finishedPackets) {
|
||||
// for (auto& client : clients.getClients()) {
|
||||
// if (!client.second->player) continue;
|
||||
// data->packet->sendTo(client.second->peer, Packet::Channel::WORLD);
|
||||
// }
|
||||
// }
|
||||
|
||||
generatedMapBlocks = genCount;
|
||||
|
||||
|
@ -178,25 +194,16 @@ void ServerWorld::update(double delta) {
|
|||
}
|
||||
}
|
||||
|
||||
DimensionPtr ServerWorld::createDimension(const std::string& identifier, std::unordered_set<std::string>& biomes) {
|
||||
auto mapGen = std::make_shared<MapGen>(**game, *this, seed, biomes);
|
||||
dimensions.emplace_back(std::make_shared<ServerDimension>(
|
||||
game, *this, identifier, this->dimensions.size(), std::move(mapGen)));
|
||||
DimensionPtr ServerWorld::createDimension(const string& identifier, std::unordered_set<string>& biomes) {
|
||||
dimensions.emplace_back(make_shared<ServerDimension>(
|
||||
game, *this, identifier, this->dimensions.size(),
|
||||
make_shared<MapGen>(**game, *this, seed, biomes)));
|
||||
|
||||
dimensionIndexes[identifier] = dimensions.size() - 1;
|
||||
DimensionPtr d = dimensions.back();
|
||||
return d;
|
||||
}
|
||||
|
||||
DimensionPtr ServerWorld::getDimension(unsigned int index) {
|
||||
return dimensions[index];
|
||||
}
|
||||
|
||||
DimensionPtr ServerWorld::getDimension(const std::string& identifier) {
|
||||
for (auto& dimension : dimensions)
|
||||
if (dimension->getIdentifier() == identifier) return dimension;
|
||||
throw std::runtime_error("No dimension named " + identifier + " found.");
|
||||
}
|
||||
|
||||
InventoryRefsPtr ServerWorld::getRefs() {
|
||||
return InventoryRefsPtr(refs);
|
||||
}
|
||||
|
@ -212,18 +219,18 @@ void ServerWorld::changedMapBlocks(ServerPlayer& player) {
|
|||
}
|
||||
|
||||
void ServerWorld::generateMapBlocks(ServerPlayer& player) {
|
||||
unsigned int generating = 0;
|
||||
glm::ivec3 playerMapBlock = Space::MapBlock::world::fromBlock(player.getPos());
|
||||
u32 generating = 0;
|
||||
ivec3 playerMapBlock = Space::MapBlock::world::fromBlock(player.getPos());
|
||||
|
||||
for (const auto& c : generateOrder) {
|
||||
glm::ivec3 mapBlockPos = playerMapBlock + c;
|
||||
ivec3 mapBlockPos = playerMapBlock + c;
|
||||
generating += generateMapBlock(player.getDim()->getInd(), mapBlockPos);
|
||||
}
|
||||
|
||||
std::cout << "Player moved, generating " << generating << " MapBlocks." << std::endl;
|
||||
// std::cout << "Player moved, generating " << generating << " MapBlocks." << std::endl;
|
||||
}
|
||||
|
||||
bool ServerWorld::generateMapBlock(unsigned int dim, glm::ivec3 pos) {
|
||||
bool ServerWorld::generateMapBlock(u16 dim, ivec3 pos) {
|
||||
auto dimension = getDimension(dim);
|
||||
if (!dimension->getMapBlock(pos) || !dimension->getMapBlock(pos)->generated) return genStream->queue(dim, pos);
|
||||
return false;
|
||||
|
@ -240,7 +247,25 @@ void ServerWorld::sendChunksToPlayer(ServerPlayer& client) {
|
|||
|
||||
for (auto& pos : generateOrder) {
|
||||
if (oldBounds.intersects(playerPos + pos) || !newBounds.intersects(playerPos + pos)) continue;
|
||||
packetStream->queue(client.getDim()->getInd(), pos + playerPos);
|
||||
// packetStream->queue(client.getDim()->getInd(), pos + playerPos);
|
||||
|
||||
// auto dim = client.getDim();
|
||||
// std::cout << dim->getInd() << std::endl;
|
||||
// auto mb = dim->getMapBlock(pos);
|
||||
// std::cout << mb << std::endl;
|
||||
// if (!mb) return;
|
||||
// Serializer s {};
|
||||
// for (u16 i = 0; i < 64; i++) {
|
||||
// auto chunk = mb->get(i);
|
||||
// if (chunk) s.append(chunk->compressToString());
|
||||
// }
|
||||
//
|
||||
// let packet = make_unique<Packet>(Packet::Type::MAPBLOCK);
|
||||
//
|
||||
// for (auto& client : clients.getClients()) {
|
||||
// if (!client.second->player) continue;
|
||||
// packet->sendTo(client.second->peer, Packet::Channel::WORLD);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
//
|
||||
// World subclass for the server.
|
||||
// Handles blocks, entities, and clients.
|
||||
// Created by aurailus on 05/03/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "world/World.h"
|
||||
|
@ -19,51 +13,77 @@ class ServerGenStream;
|
|||
class ServerInventoryRefs;
|
||||
class ServerPacketStream;
|
||||
|
||||
/**
|
||||
* Manages server dimensions and players.
|
||||
* Handles sending chunk and entity data to clients.
|
||||
*/
|
||||
|
||||
class ServerWorld : public World {
|
||||
public:
|
||||
explicit ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clients);
|
||||
|
||||
void init(const std::string& worldDir);
|
||||
explicit ServerWorld(u32 seed, SubgamePtr game, ServerClients& clients);
|
||||
|
||||
void update(double delta) override;
|
||||
/** Initializes the map and packet thread pools. */
|
||||
void init(const string& worldDir);
|
||||
|
||||
virtual void sendMessage(const std::string& channel, const std::string& message) override;
|
||||
/** Updates dimensions, and sends new or dirty chunks to clients. */
|
||||
void update(double delta);
|
||||
|
||||
/** Sends a mod message to the channel provided. */
|
||||
virtual void sendMessage(const string& channel, const string& message) override;
|
||||
|
||||
virtual DimensionPtr
|
||||
createDimension(const std::string& identifier, std::unordered_set<std::string>& biomes) override;
|
||||
|
||||
virtual DimensionPtr getDimension(unsigned int index) override;
|
||||
|
||||
virtual DimensionPtr getDimension(const std::string& identifier) override;
|
||||
/** Creates a new dimension with the identifier and biomes provided. */
|
||||
virtual DimensionPtr createDimension(const string& identifier, std::unordered_set<string>& biomes) override;
|
||||
|
||||
/** Returns a reference to the world's inventory refs. */
|
||||
virtual InventoryRefsPtr getRefs() override;
|
||||
|
||||
/** Gets the list of connected clients. */
|
||||
virtual ServerClients& getClients();
|
||||
|
||||
private:
|
||||
|
||||
/** Called when a player changes mapblocks, to generate and send new chunks. */
|
||||
void changedMapBlocks(ServerPlayer& player);
|
||||
|
||||
bool generateMapBlock(unsigned int dim, glm::ivec3 pos);
|
||||
/** Generates a single mapblock, if it doesn't exist already. */
|
||||
bool generateMapBlock(u16 dim, ivec3 pos);
|
||||
|
||||
/** Generates mapblocks around the player specified. */
|
||||
void generateMapBlocks(ServerPlayer& player);
|
||||
|
||||
/** Sends all of the surrounding chunks to the specified player. */
|
||||
void sendChunksToPlayer(ServerPlayer& client);
|
||||
|
||||
std::shared_ptr<ServerGenStream> genStream = nullptr;
|
||||
std::shared_ptr<ServerPacketStream> packetStream = nullptr;
|
||||
|
||||
/** Generates new chunks. */
|
||||
sptr<ServerGenStream> genStream = nullptr;
|
||||
|
||||
/** The seed for generating the world. */
|
||||
u32 seed;
|
||||
|
||||
/** A reference to the client list. */
|
||||
ServerClients& clients;
|
||||
std::shared_ptr<ServerInventoryRefs> refs;
|
||||
|
||||
/** The server inventories. */
|
||||
sptr<ServerInventoryRefs> refs;
|
||||
|
||||
// std::string worldDir;
|
||||
// std::shared_ptr<FileManipulator> fileManip;
|
||||
|
||||
u32 generatedMapBlocks = 0;
|
||||
std::vector<ivec3> generateOrder;
|
||||
|
||||
const ivec2 mapBlockGenRange = { 4, 4 };
|
||||
const ivec2 sendRange = { 4, 4 };
|
||||
const ivec2 activeChunkRange = { 16, 16 };
|
||||
};
|
||||
usize totalGens = 0;
|
||||
|
||||
/** The amount of mapblocks that were generated last frame. */
|
||||
u32 generatedMapBlocks = 0;
|
||||
|
||||
/** A vector of positions for the order to generate mapblocks in. */
|
||||
vec<ivec3> generateOrder;
|
||||
|
||||
/** The range in mapblocks to generate around clients. */
|
||||
const ivec2 mapBlockGenRange = { 4, 4 };
|
||||
|
||||
/** The range in mapblocks to send to clients. */
|
||||
const ivec2 sendRange = { 4, 4 };
|
||||
|
||||
/** The range around clients that chunks should be updated. */
|
||||
const ivec2 activeChunkRange = { 4, 4 };
|
||||
};
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
//
|
||||
// Created by aurailus on 2020-01-09.
|
||||
//
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "World.h"
|
||||
|
||||
#include "util/Util.h"
|
||||
#include "world/dim/Dimension.h"
|
||||
|
||||
World::World(SubgamePtr game) : game(game) {}
|
||||
|
||||
void World::update(double delta) {
|
||||
for (auto& dimension : dimensions) dimension->update(delta);
|
||||
}
|
||||
//void World::update(f64 delta) {
|
||||
// for (auto& dimension : dimensions) dimension->update(delta);
|
||||
//}
|
||||
|
||||
DimensionPtr World::getDefaultDimension() {
|
||||
if (defaultDimension.empty()) throw std::runtime_error("No default dimension was set.");
|
||||
return getDimension(defaultDimension);
|
||||
}
|
||||
|
||||
void World::setDefaultDimension(const std::string& identifier) {
|
||||
void World::setDefaultDimension(const string& identifier) {
|
||||
defaultDimension = identifier;
|
||||
}
|
||||
|
||||
DimensionPtr World::getDimension(unsigned int index) {
|
||||
DimensionPtr World::getDimension(u16 index) {
|
||||
if (dimensions.size() <= index) throw std::runtime_error(
|
||||
"Dimension #" + Util::toString(index) + " does not exist.");
|
||||
return dimensions[index];
|
||||
}
|
||||
|
||||
DimensionPtr World::getDimension(const std::string& identifier) {
|
||||
for (auto& dimension : dimensions) if (dimension->getIdentifier() == identifier) return dimension;
|
||||
throw std::runtime_error("No dimension named " + identifier + " found.");
|
||||
}
|
||||
DimensionPtr World::getDimension(const string& identifier) {
|
||||
if (dimensionIndexes.find(identifier) == dimensionIndexes.end() || dimensions.size() <= dimensionIndexes[identifier])
|
||||
throw std::runtime_error("Dimension '" + identifier + "'does not exist.");
|
||||
return dimensions[dimensionIndexes[identifier]];
|
||||
}
|
|
@ -1,45 +1,59 @@
|
|||
//
|
||||
// Created by aurailus on 2020-01-09.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "util/Vec.h"
|
||||
#include "util/Types.h"
|
||||
#include "util/CovariantPtr.h"
|
||||
|
||||
class Subgame;
|
||||
|
||||
class Dimension;
|
||||
|
||||
/**
|
||||
* Manages all loaded dimensions.
|
||||
* Also handles all inventories, and sending mod messages.
|
||||
* LocalWorld and ServerWorld are children of this class.
|
||||
*/
|
||||
|
||||
class World {
|
||||
public:
|
||||
|
||||
World(const World& o) = delete;
|
||||
|
||||
explicit World(SubgamePtr game);
|
||||
explicit World(SubgamePtr game) : game(game) {};
|
||||
|
||||
virtual void update(double delta);
|
||||
|
||||
virtual DimensionPtr createDimension(const std::string& identifier, std::unordered_set<std::string>& biomes) = 0;
|
||||
/** Creates a new dimension with the identifier and biomes provided. */
|
||||
virtual DimensionPtr createDimension(const string& identifier, std::unordered_set<string>& biomes) = 0;
|
||||
|
||||
/** Gets the default dimension, throws if no default is set. */
|
||||
virtual DimensionPtr getDefaultDimension();
|
||||
|
||||
virtual void setDefaultDimension(const std::string& defaultDimension);
|
||||
/** Sets the identifier of the default dimension. */
|
||||
virtual void setDefaultDimension(const string& defaultDimension);
|
||||
|
||||
virtual DimensionPtr getDimension(unsigned int index);
|
||||
/** Gets a dimension by its index, throws if there is none. */
|
||||
virtual DimensionPtr getDimension(u16 index);
|
||||
|
||||
virtual DimensionPtr getDimension(const std::string& identifier);
|
||||
/** Gets a dimension by its identifier, throws if there is none. */
|
||||
virtual DimensionPtr getDimension(const string& identifier);
|
||||
|
||||
virtual void sendMessage(const std::string& channel, const std::string& message) = 0;
|
||||
/** Sends a mod message on the channel specified. */
|
||||
virtual void sendMessage(const string& channel, const string& message) = 0;
|
||||
|
||||
/** Returns a reference to the world's inventory refs. */
|
||||
virtual InventoryRefsPtr getRefs() = 0;
|
||||
|
||||
protected:
|
||||
std::string defaultDimension{};
|
||||
std::vector<std::shared_ptr<Dimension>> dimensions;
|
||||
|
||||
/** The identifier of the default dimension. */
|
||||
string defaultDimension {};
|
||||
|
||||
/** A vector of dimensions in the world. */
|
||||
vec<sptr<Dimension>> dimensions;
|
||||
|
||||
/** A map of dimension identifiers to indexes. */
|
||||
std::unordered_map<string, u16> dimensionIndexes;
|
||||
|
||||
/** A reference to the subgame. */
|
||||
SubgamePtr game;
|
||||
};
|
||||
|
|
|
@ -18,8 +18,8 @@ bool Dimension::setBlock(ivec3 pos, u16 block) {
|
|||
|
||||
auto& def = game->getDefs().blockFromId(block);
|
||||
|
||||
glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos));
|
||||
glm::ivec3 newLight = def.lightSource;
|
||||
ivec4 oldLight = chunk->getLight(Space::Block::index(pos));
|
||||
ivec3 newLight = def.lightSource;
|
||||
|
||||
if (oldLight.x + oldLight.y + oldLight.z != 0) removeBlockLight(pos);
|
||||
if (newLight.x + newLight.y + newLight.z != 0) addBlockLight(pos, newLight);
|
||||
|
|
|
@ -35,75 +35,79 @@ void LocalDimension::deactivate() {
|
|||
}
|
||||
}
|
||||
|
||||
void LocalDimension::update(double delta) {
|
||||
void LocalDimension::update(f64 delta) {
|
||||
finishMeshes();
|
||||
|
||||
/* Update local entities and player entities. */
|
||||
for (auto& entity : entities) entity.entity.l()->update(delta);
|
||||
for (auto& entity : playerEntities) entity.update(delta);
|
||||
|
||||
auto clientMapBlock = Space::MapBlock::world::fromBlock(static_cast<LocalWorld&>(world).getPlayer()->getPos());
|
||||
/*
|
||||
* Delete mapblocks and regions that are outside of the retain range,
|
||||
* and compress chunks if they are idle.
|
||||
*/
|
||||
|
||||
for (auto it = regions.cbegin(); it != regions.cend();) {
|
||||
bool remove = false;
|
||||
for (unsigned short m = 0; m < 64; m++) {
|
||||
auto mapBlock = it->second->get(m);
|
||||
let clientMapBlock = Space::MapBlock::world::fromBlock(static_cast<LocalWorld&>(world).getPlayer()->getPos());
|
||||
|
||||
for (let it = regions.cbegin(); it != regions.cend();) {
|
||||
for (u16 m = 0; m < 64; m++) {
|
||||
let mapBlock = it->second->get(m);
|
||||
if (!mapBlock) continue;
|
||||
|
||||
if (abs(clientMapBlock.x - mapBlock->pos.x) > LocalDimension::MB_STORE_H + 1
|
||||
|| abs(clientMapBlock.y - mapBlock->pos.y) > LocalDimension::MB_STORE_V + 1
|
||||
|| abs(clientMapBlock.z - mapBlock->pos.z) > LocalDimension::MB_STORE_H + 1) {
|
||||
if (abs(clientMapBlock.x - mapBlock->pos.x) > retainMapBlockRange.x ||
|
||||
abs(clientMapBlock.y - mapBlock->pos.y) > retainMapBlockRange.y ||
|
||||
abs(clientMapBlock.z - mapBlock->pos.z) > retainMapBlockRange.x) {
|
||||
|
||||
for (unsigned short c = 0; c < 64; c++) {
|
||||
auto chunk = mapBlock->get(c);
|
||||
if (!chunk) continue;
|
||||
removeMeshChunk(chunk->getPos());
|
||||
for (u16 c = 0; c < 64; c++) {
|
||||
let chunk = mapBlock->get(c);
|
||||
if (chunk) removeMeshChunk(chunk->getPos());
|
||||
}
|
||||
|
||||
it->second->remove(m);
|
||||
if (it->second->count <= 0) {
|
||||
remove = true;
|
||||
it = regions.erase(it);
|
||||
break;
|
||||
}
|
||||
if (it->second->count <= 0) goto erase_region_and_continue;
|
||||
}
|
||||
else {
|
||||
for (unsigned short c = 0; c < 64; c++) {
|
||||
auto chunk = mapBlock->get(c);
|
||||
if (!chunk) continue;
|
||||
chunk->compressIfIdle();
|
||||
for (u16 c = 0; c < 64; c++) {
|
||||
let chunk = mapBlock->get(c);
|
||||
if (chunk) chunk->compressIfIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!remove) it++;
|
||||
|
||||
it++;
|
||||
continue;
|
||||
|
||||
erase_region_and_continue:
|
||||
it = regions.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalDimension::setChunk(std::shared_ptr<Chunk> chunk) {
|
||||
void LocalDimension::setChunk(sptr<Chunk> chunk) {
|
||||
Dimension::setChunk(chunk);
|
||||
attemptMeshChunk(chunk);
|
||||
meshChunk(chunk);
|
||||
}
|
||||
|
||||
bool LocalDimension::setBlock(ivec3 pos, u16 block) {
|
||||
bool exists = Dimension::setBlock(pos, block);
|
||||
if (!exists) return false;
|
||||
bool modified = Dimension::setBlock(pos, block);
|
||||
if (!modified) return false;
|
||||
|
||||
auto chunkPos = Space::Chunk::world::fromBlock(pos);
|
||||
auto chunk = getChunk(chunkPos);
|
||||
let chunkPos = Space::Chunk::world::fromBlock(pos);
|
||||
let chunk = getChunk(chunkPos);
|
||||
|
||||
chunk->setDirty(true);
|
||||
|
||||
auto lp = Space::Block::relative::toChunk(pos);
|
||||
auto cp = Space::Chunk::world::fromBlock(pos);
|
||||
let lp = Space::Block::relative::toChunk(pos);
|
||||
let cp = Space::Chunk::world::fromBlock(pos);
|
||||
|
||||
std::shared_ptr<Chunk> tempChunk;
|
||||
if (lp.x == 15 && (tempChunk = getChunk(cp + ivec3{ 1, 0, 0 }))) tempChunk->setDirty(true);
|
||||
else if (lp.x == 0 && (tempChunk = getChunk(cp + ivec3{ -1, 0, 0 }))) tempChunk->setDirty(true);
|
||||
if (lp.y == 15 && (tempChunk = getChunk(cp + ivec3{ 0, 1, 0 }))) tempChunk->setDirty(true);
|
||||
else if (lp.y == 0 && (tempChunk = getChunk(cp + ivec3{ 0, -1, 0 }))) tempChunk->setDirty(true);
|
||||
if (lp.z == 15 && (tempChunk = getChunk(cp + ivec3{ 0, 0, 1 }))) tempChunk->setDirty(true);
|
||||
else if (lp.z == 0 && (tempChunk = getChunk(cp + ivec3{ 0, 0, -1 }))) tempChunk->setDirty(true);
|
||||
sptr<Chunk> adjacent;
|
||||
if (lp.x == 15 && (adjacent = getChunk(cp + ivec3 { 1, 0, 0 }))) adjacent->setDirty(true);
|
||||
else if (lp.x == 0 && (adjacent = getChunk(cp + ivec3 { -1, 0, 0 }))) adjacent->setDirty(true);
|
||||
if (lp.y == 15 && (adjacent = getChunk(cp + ivec3 { 0, 1, 0 }))) adjacent->setDirty(true);
|
||||
else if (lp.y == 0 && (adjacent = getChunk(cp + ivec3 { 0, -1, 0 }))) adjacent->setDirty(true);
|
||||
if (lp.z == 15 && (adjacent = getChunk(cp + ivec3 { 0, 0, 1 }))) adjacent->setDirty(true);
|
||||
else if (lp.z == 0 && (adjacent = getChunk(cp + ivec3 { 0, 0, -1 }))) adjacent->setDirty(true);
|
||||
|
||||
attemptMeshChunk(chunk, true);
|
||||
meshChunk(chunk, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -129,7 +133,7 @@ void LocalDimension::blockInteract(const Target& target, PlayerPtr player) {
|
|||
}
|
||||
|
||||
void LocalDimension::blockPlaceOrInteract(const Target& target, PlayerPtr player) {
|
||||
std::tuple<sol::optional<Api::Usertype::ItemStack>, sol::optional<glm::vec3>> res = game->getParser().safe_function(
|
||||
std::tuple<sol::optional<Api::Usertype::ItemStack>, sol::optional<vec3>> res = game->getParser().safe_function(
|
||||
game->getParser().core["block_interact_or_place"], Api::Usertype::LocalPlayer(player.l()),
|
||||
Api::Usertype::Target(target));
|
||||
|
||||
|
@ -144,7 +148,7 @@ void LocalDimension::blockPlaceOrInteract(const Target& target, PlayerPtr player
|
|||
}
|
||||
|
||||
double LocalDimension::blockHit(const Target& target, PlayerPtr player) {
|
||||
double timeout = 0, damage = 0;
|
||||
f64 timeout = 0, damage = 0;
|
||||
sol::tie(damage, timeout) = game->getParser().safe_function(game->getParser().core["block_hit"],
|
||||
Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target));
|
||||
|
||||
|
@ -164,13 +168,13 @@ void LocalDimension::wieldItemUse(const Target& target, PlayerPtr player) {
|
|||
inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game));
|
||||
}
|
||||
|
||||
void LocalDimension::setMeshChunk(std::shared_ptr<MeshChunk> meshChunk) {
|
||||
void LocalDimension::setMeshChunk(sptr<MeshChunk> meshChunk) {
|
||||
if (renderRefs.count(meshChunk->getPos())) removeMeshChunk(meshChunk->getPos());
|
||||
renderElems.push_back(std::static_pointer_cast<ChunkRenderElem>(meshChunk));
|
||||
renderRefs.emplace(meshChunk->getPos(), --renderElems.end());
|
||||
}
|
||||
|
||||
void LocalDimension::removeMeshChunk(const glm::ivec3& pos) {
|
||||
void LocalDimension::removeMeshChunk(const ivec3& pos) {
|
||||
if (!renderRefs.count(pos)) return;
|
||||
auto refIter = renderRefs.at(pos);
|
||||
|
||||
|
@ -185,13 +189,13 @@ i64 LocalDimension::nextEntityInd() {
|
|||
}
|
||||
|
||||
void LocalDimension::addLocalEntity(Api::Usertype::Entity entity) {
|
||||
unsigned int id = entity.get_id();
|
||||
i64 id = entity.get_id();
|
||||
entities.push_back(entity);
|
||||
entityRefs.emplace(id, --entities.end());
|
||||
}
|
||||
|
||||
void LocalDimension::removeLocalEntity(Api::Usertype::Entity entity) {
|
||||
unsigned int id = entity.get_id();
|
||||
i64 id = entity.get_id();
|
||||
|
||||
if (!entityRefs.count(id)) return;
|
||||
auto refIter = entityRefs.at(id);
|
||||
|
@ -303,7 +307,7 @@ void LocalDimension::serverEntitiesInfo(Deserializer& e) {
|
|||
}
|
||||
}
|
||||
|
||||
void LocalDimension::serverEntitiesRemoved(Deserializer& d) {
|
||||
void LocalDimension::removeServerEntities(Deserializer& d) {
|
||||
d.read<u16>();
|
||||
while (!d.atEnd()) {
|
||||
i64 id = d.read<i64>();
|
||||
|
@ -350,13 +354,13 @@ u32 LocalDimension::getMeshChunksCommitted() {
|
|||
|
||||
std::unordered_set<ivec3, Vec::ivec3> LocalDimension::propogateAddNodes() {
|
||||
auto updated = Dimension::propogateAddNodes();
|
||||
for (auto& update : updated) attemptMeshChunk(getChunk(update));
|
||||
for (auto& update : updated) meshChunk(getChunk(update));
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unordered_set<ivec3, Vec::ivec3> LocalDimension::propogateRemoveNodes() {
|
||||
auto updated = Dimension::propogateRemoveNodes();
|
||||
for (auto& update : updated) attemptMeshChunk(getChunk(update));
|
||||
for (auto& update : updated) meshChunk(getChunk(update));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -364,36 +368,38 @@ void LocalDimension::finishMeshes() {
|
|||
lastMeshesCommitted = 0;
|
||||
auto finishedMeshes = meshGenStream->update();
|
||||
|
||||
for (ChunkMeshDetails* meshDetails : finishedMeshes) {
|
||||
if (!meshDetails->vertices.empty()) {
|
||||
auto meshChunk = std::make_shared<MeshChunk>();
|
||||
meshChunk->create(meshDetails->vertices, meshDetails->indices);
|
||||
meshChunk->setPos(meshDetails->pos);
|
||||
|
||||
setMeshChunk(meshChunk);
|
||||
for (MeshChunkDetails* details : finishedMeshes) {
|
||||
if (!details->vertices.empty()) {
|
||||
setMeshChunk(make_shared<MeshChunk>(details->pos, details->vertices, details->indices));
|
||||
lastMeshesCommitted++;
|
||||
}
|
||||
else removeMeshChunk(meshDetails->pos);
|
||||
else removeMeshChunk(details->pos);
|
||||
|
||||
delete meshDetails;
|
||||
delete details;
|
||||
}
|
||||
}
|
||||
|
||||
void LocalDimension::attemptMeshChunk(const sptr<Chunk>& chunk, bool priority, bool updateAdjacents) {
|
||||
bool renderable = true;
|
||||
for (auto dir : Vec::TO_VEC) if (!getAdjacentExists(chunk->getPos() + dir, updateAdjacents)) renderable = false;
|
||||
if (!renderable) return;
|
||||
void LocalDimension::meshChunk(const sptr<Chunk>& chunk, bool priority, bool updateAdjacents) {
|
||||
// Run this loop first, because even if this chunk shouldn't render, the adjacents maybe should.
|
||||
bool render = true;
|
||||
for (let dir : Vec::TO_VEC)
|
||||
if (!adjacentExists(chunk->getPos() + dir, updateAdjacents, priority))
|
||||
render = false;
|
||||
if (!render) return;
|
||||
|
||||
if (!chunk->isDirty()) return;
|
||||
if (!chunk->chunkShouldRender()) removeMeshChunk(chunk->getPos());
|
||||
if (!chunk->chunkShouldRender()) {
|
||||
removeMeshChunk(chunk->getPos());
|
||||
return;
|
||||
}
|
||||
|
||||
meshGenStream->queue(chunk->getPos(), priority);
|
||||
chunk->setDirty(false);
|
||||
}
|
||||
|
||||
bool LocalDimension::getAdjacentExists(vec3 pos, bool updateAdjacents) {
|
||||
auto chunk = getChunk(pos);
|
||||
if (chunk == nullptr) return false;
|
||||
if (updateAdjacents) attemptMeshChunk(chunk, false, false);
|
||||
bool LocalDimension::adjacentExists(ivec3 pos, bool update, bool priority) {
|
||||
let chunk = getChunk(pos);
|
||||
if (!chunk) return false;
|
||||
if (update) meshChunk(chunk, priority, false);
|
||||
return true;
|
||||
}
|
|
@ -21,17 +21,17 @@ class ChunkRenderElem;
|
|||
|
||||
class LocalDimension : public Dimension {
|
||||
public:
|
||||
const static u8 MB_STORE_H = 4;
|
||||
const static u8 MB_STORE_V = 4;
|
||||
|
||||
LocalDimension(SubgamePtr game, LocalWorld& world, const string& identifier, u16 ind, sptr<MapGen> mapGen);
|
||||
|
||||
void deactivate();
|
||||
|
||||
/** Updates chunks and entities. */
|
||||
void update(f64 delta) override;
|
||||
|
||||
/** Sets the chunk, and then queues it to be meshed. */
|
||||
void setChunk(sptr<Chunk> chunk) override;
|
||||
|
||||
/** Sets the block, and queues the relevant chunks for remeshing. */
|
||||
bool setBlock(ivec3 pos, u16 block) override;
|
||||
|
||||
virtual void blockPlace(const Target& target, PlayerPtr player) override;
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
|
||||
void serverEntitiesInfo(Deserializer& d);
|
||||
|
||||
void serverEntitiesRemoved(Deserializer& d);
|
||||
void removeServerEntities(Deserializer& d);
|
||||
|
||||
std::vector<Api::Usertype::Entity> getEntitiesInRadius(vec3 pos, f32 radius);
|
||||
|
||||
|
@ -84,9 +84,11 @@ private:
|
|||
|
||||
void finishMeshes();
|
||||
|
||||
void attemptMeshChunk(const sptr<Chunk>& chunk, bool priority = false, bool updateAdjacents = true);
|
||||
/** Queues a chunk to be meshed if its dirty and the adjacent chunks exist. */
|
||||
void meshChunk(const sptr<Chunk>& chunk, bool priority = false, bool updateAdjacents = true);
|
||||
|
||||
bool getAdjacentExists(vec3 pos, bool updateAdjacents);
|
||||
/** Checks if a chunk exists and optionally meshes it if dirty. */
|
||||
bool adjacentExists(ivec3 pos, bool update, bool priority = false);
|
||||
|
||||
sptr<MeshGenStream> meshGenStream;
|
||||
|
||||
|
@ -96,6 +98,7 @@ private:
|
|||
std::unordered_map<vec3, chunk_ref, Vec::vec3> renderRefs{};
|
||||
std::list<sptr<ChunkRenderElem>> renderElems{};
|
||||
|
||||
const ivec2 retainMapBlockRange = { 4, 4 };
|
||||
i64 entityInd = -1;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,36 +22,49 @@ ServerDimension::ServerDimension(SubgamePtr game, ServerWorld& world, const std:
|
|||
Dimension(game, static_cast<World&>(world), identifier, ind, std::move(mapGen)) {}
|
||||
|
||||
void ServerDimension::update(double delta) {
|
||||
|
||||
/* Update server entities. */
|
||||
for (auto& entity : luaEntities) entity.entity.s()->update(delta);
|
||||
|
||||
for (const auto& region : regions) {
|
||||
for (unsigned short i = 0; i < 64; i++) {
|
||||
auto mapBlock = region.second->get(i);
|
||||
/*
|
||||
* Delete mapblocks and regions that are outside of the retain range,
|
||||
* and compress chunks if they are idle.
|
||||
*/
|
||||
|
||||
for (let it = regions.cbegin(); it != regions.cend();) {
|
||||
for (u16 m = 0; m < 64; m++) {
|
||||
let mapBlock = it->second->get(m);
|
||||
if (!mapBlock) continue;
|
||||
|
||||
bool clientNearby = false;
|
||||
for (auto& client : static_cast<ServerWorld&>(world).getClients().getClients()) {
|
||||
if (!client.second->player) continue;
|
||||
if (client.second->player->getDim()->getInd() == ind) {
|
||||
auto clientPos = Space::MapBlock::world::fromBlock(client.second->player->getPos());
|
||||
if (abs(clientPos.x - mapBlock->pos.x) <= discardRange.x + 1
|
||||
&& abs(clientPos.y - mapBlock->pos.y) <= discardRange.y + 1
|
||||
&& abs(clientPos.z - mapBlock->pos.z) <= discardRange.x + 1) {
|
||||
clientNearby = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!client.second->player || client.second->player->getDim()->getInd() != ind) continue;
|
||||
auto clientMapBlock = Space::MapBlock::world::fromBlock(client.second->player->getPos());
|
||||
if (abs(clientMapBlock.x - mapBlock->pos.x) <= retainMapBlockRange.x &&
|
||||
abs(clientMapBlock.y - mapBlock->pos.y) <= retainMapBlockRange.y &&
|
||||
abs(clientMapBlock.z - mapBlock->pos.z) <= retainMapBlockRange.x) {
|
||||
clientNearby = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!clientNearby) region.second->remove(i);
|
||||
if (!clientNearby) {
|
||||
it->second->remove(m);
|
||||
if (it->second->count <= 0) goto erase_region_and_continue;
|
||||
}
|
||||
else {
|
||||
for (unsigned short c = 0; c < 64; c++) {
|
||||
auto chunk = mapBlock->get(c);
|
||||
if (!chunk) continue;
|
||||
chunk->compressIfIdle();
|
||||
for (u16 c = 0; c < 64; c++) {
|
||||
let chunk = mapBlock->get(c);
|
||||
if (chunk) chunk->compressIfIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it++;
|
||||
continue;
|
||||
|
||||
erase_region_and_continue:
|
||||
it = regions.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,8 +116,8 @@ void ServerDimension::wieldItemUse(const Target& target, PlayerPtr player) {
|
|||
}
|
||||
|
||||
void ServerDimension::setChunk(std::shared_ptr<Chunk> chunk) {
|
||||
// std::shared_ptr<Chunk> existing = getChunk(chunk->getPos());
|
||||
// if (existing) chunk = combineChunks(chunk, existing);
|
||||
std::shared_ptr<Chunk> existing = getChunk(chunk->getPos());
|
||||
if (existing) chunk = combineChunks(chunk, existing);
|
||||
Dimension::setChunk(chunk);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ private:
|
|||
std::list<Api::Usertype::Entity> luaEntities{};
|
||||
std::list<i64> removedEntities{};
|
||||
|
||||
const ivec2 discardRange = { 20, 20 };
|
||||
const ivec2 retainMapBlockRange = { 4, 4 };
|
||||
i64 entityInd = 1;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,8 +52,11 @@ const array<u16, 4096>& Chunk::getBiomesArray() {
|
|||
}
|
||||
|
||||
void Chunk::combineWith(sptr<Chunk> o) {
|
||||
useDecompressed();
|
||||
o->useDecompressed();
|
||||
|
||||
for (u16 i = 0; i < 4096; i++)
|
||||
if (o->getBlock(i) > DefinitionAtlas::INVALID) setBlock(i, o->getBlock(i));
|
||||
if (o->getBlock(i) > DefinitionAtlas::INVALID) d->blocks[i] = o->d->blocks[i];
|
||||
|
||||
if (generationState == GenerationState::GENERATED || o->isGenerated()) {
|
||||
generationState = GenerationState::GENERATED;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include <random>
|
||||
#include <iostream>
|
||||
|
||||
#include "MapGen.h"
|
||||
|
||||
#include "util/Types.h"
|
||||
#include "world/World.h"
|
||||
#include "game/Subgame.h"
|
||||
#include "util/Structure.h"
|
||||
|
@ -14,7 +16,7 @@
|
|||
|
||||
MapGen::MapGen(Subgame& game, World& world, u32 seed, std::unordered_set<string> biomes) :
|
||||
game(game), world(world), props(seed) {
|
||||
|
||||
|
||||
std::unordered_set<u16> biomeIndices {};
|
||||
for (const auto& str : biomes) {
|
||||
if (str[0] == '#')
|
||||
|
@ -22,7 +24,7 @@ MapGen::MapGen(Subgame& game, World& world, u32 seed, std::unordered_set<string>
|
|||
biomeIndices.insert(biome->index);
|
||||
else biomeIndices.insert(game.getBiomes().biomeFromStr(str).index);
|
||||
}
|
||||
|
||||
|
||||
generateVoronoi(biomeIndices);
|
||||
}
|
||||
|
||||
|
@ -95,12 +97,16 @@ std::unique_ptr<MapGen::ChunkMap> MapGen::generateArea(u16 dim, ivec3 origin, u1
|
|||
uptr<ChunkData> depth = populateChunkDepth(density, std::move(densityAbove));
|
||||
|
||||
generateChunkBlocks(job, pos, biomeMap, *depth);
|
||||
// generateChunkDecorAndLight(job, pos, biomeMap, *depth);
|
||||
generateChunkDecorAndLight(job, pos, biomeMap, *depth);
|
||||
|
||||
densityAbove = std::move(density);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let& chunk : *job.chunks) {
|
||||
chunk.second->compress();
|
||||
}
|
||||
|
||||
return std::move(job.chunks);
|
||||
}
|
||||
|
@ -109,7 +115,7 @@ void MapGen::generateVoronoi(const std::unordered_set<u16>& biomes) {
|
|||
vec<std::pair<vec3, u16>> points {};
|
||||
for (auto biomeInd : biomes) {
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeInd);
|
||||
|
||||
|
||||
points.emplace_back(vec3 {
|
||||
static_cast<u16>(std::fmin(voronoiSize - 1,
|
||||
std::fmax(0, (biome.temperature + 1) / 2 * voronoiSize))),
|
||||
|
@ -117,7 +123,7 @@ void MapGen::generateVoronoi(const std::unordered_set<u16>& biomes) {
|
|||
static_cast<u16>(std::fmin(voronoiSize - 1, std::fmax(0, biome.roughness * voronoiSize)))
|
||||
}, biomeInd);
|
||||
}
|
||||
|
||||
|
||||
voronoi.setPoints(points);
|
||||
}
|
||||
|
||||
|
@ -130,20 +136,20 @@ u16 MapGen::getBiomeAt(f32 temperature, f32 humidity, f32 roughness) {
|
|||
|
||||
uptr<MapGen::ChunkData> MapGen::populateChunkDensity(MapGen::Job& job, ivec3 localPos) {
|
||||
auto data = make_unique<ChunkData>();
|
||||
|
||||
|
||||
for (u16 i = 0; i < 4096; i++) {
|
||||
ivec3 indPos = Space::Block::fromIndex(i);
|
||||
vec3 queryPos = (vec3(localPos) + vec3(indPos) / 16.f) / static_cast<f32>(job.size);
|
||||
(*data)[i] = (job.volume.get(queryPos) + job.heightmap.get({ queryPos.x, 0, queryPos.z }))
|
||||
- ((job.pos.y + localPos.y) * 16 + indPos.y);
|
||||
}
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
uptr<MapGen::ChunkData> MapGen::populateChunkDepth(uptr<ChunkData>& chunkDensity, uptr<ChunkData> chunkDensityAbove) {
|
||||
auto data = make_unique<ChunkData>();
|
||||
|
||||
|
||||
for (u16 i = 0; i < 256; i++) {
|
||||
ivec2 pos = { i / 16, i % 16 };
|
||||
short depth = 16;
|
||||
|
@ -166,27 +172,27 @@ uptr<MapGen::ChunkData> MapGen::populateChunkDepth(uptr<ChunkData>& chunkDensity
|
|||
(*data)[ind] = depth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void MapGen::generateChunkBlocks(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap) {
|
||||
ivec3 chunkPos = job.pos + localPos;
|
||||
|
||||
|
||||
auto partial = (job.chunks->count(chunkPos) ? job.chunks->at(chunkPos) : nullptr);
|
||||
if (partial) job.chunks->erase(chunkPos);
|
||||
|
||||
|
||||
auto& chunk = *(*job.chunks->emplace(chunkPos, new Chunk(chunkPos)).first).second;
|
||||
|
||||
|
||||
u16 partialBlock = DefinitionAtlas::INVALID;
|
||||
|
||||
|
||||
for (u16 i = 0; i < 4096; i++) {
|
||||
ivec3 indPos = Space::Block::fromIndex(i);
|
||||
|
||||
|
||||
u16 biomeId = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)];
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeId);
|
||||
chunk.d->biomes[i] = biomeId;
|
||||
|
||||
|
||||
f32 depth = depthMap[i];
|
||||
u16 blockId =
|
||||
partialBlock > DefinitionAtlas::INVALID ? partialBlock
|
||||
|
@ -194,49 +200,49 @@ void MapGen::generateChunkBlocks(Job& job, ivec3 localPos, vec<u16> biomeMap, Ch
|
|||
: depth <= 2 ? biome.topBlock
|
||||
: depth <= 4 ? biome.soilBlock
|
||||
: biome.rockBlock;
|
||||
|
||||
|
||||
if (chunk.d == nullptr) std::cout << "THE DATA ISNT LOADED." << std::endl;
|
||||
chunk.d->blocks[i] = blockId;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
chunk.countRenderableBlocks();
|
||||
}
|
||||
|
||||
void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biomeMap,
|
||||
ChunkData& depthMap) {
|
||||
|
||||
|
||||
vec3 posFloat = job.pos + localPos;
|
||||
std::default_random_engine generator(posFloat.x + posFloat.y * M_PI + posFloat.z * (M_PI * 2));
|
||||
std::uniform_real_distribution<f32> distribution(0, 1);
|
||||
|
||||
|
||||
auto& chunk = job.chunks->at(job.pos + localPos);
|
||||
|
||||
|
||||
ivec3 abovePos = job.pos + localPos + ivec3 { 0, 1, 0 };
|
||||
Chunk* above = (localPos.y != job.size - 1) ?
|
||||
job.chunks->count(abovePos) ? job.chunks->at(abovePos) : nullptr : nullptr;
|
||||
|
||||
|
||||
for (u16 i = 0; i < 256; i++) {
|
||||
ivec3 indPos = { i / 16, 15, i % 16 };
|
||||
|
||||
|
||||
u16 biomeID = biomeMap[(localPos.x * 16 + indPos.x)
|
||||
* (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)];
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeID);
|
||||
|
||||
u16 schemID = -1;
|
||||
|
||||
i16 schemID = -1;
|
||||
for (u16 j = 0; j < biome.schematics.size(); j++) {
|
||||
if (distribution(generator) > 1 - biome.schematics[j]->probability) {
|
||||
schemID = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i8 light = -1;
|
||||
|
||||
for (; indPos.y >= 0 && (light || schemID > -1); indPos.y--) {
|
||||
|
||||
for (; indPos.y >= 0 && (light > -1 || schemID > -1); indPos.y--) {
|
||||
u16 ind = Space::Block::index(indPos);
|
||||
|
||||
if (schemID > UINT16_MAX && depthMap[ind] > 1 && depthMap[ind] <= 2) {
|
||||
|
||||
if (schemID > -1 && depthMap[ind] > 1 && depthMap[ind] <= 2) {
|
||||
ivec3 pos = (job.pos + localPos) * 16 + indPos;
|
||||
pos.y++; // Compensate for the fact that we're finding solid positions.
|
||||
auto& schematic = biome.schematics[schemID];
|
||||
|
@ -246,28 +252,28 @@ void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biome
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (light == -1) light = above ? above->getLight(Space::Block::index(indPos), 3) :
|
||||
game.getDefs().blockFromId(chunk->getBlock(indPos)).lightPropagates ? 15 : 0;
|
||||
|
||||
if (!light) continue;
|
||||
|
||||
auto& blockDef = game.getDefs().blockFromId(chunk->getBlock(indPos));
|
||||
if (!blockDef.lightPropagates) light = 0;
|
||||
else {
|
||||
chunk->setLight(ind, 3, light);
|
||||
job.sunlightQueue.emplace(ind, chunk);
|
||||
}
|
||||
|
||||
// if (light == -1) light = above ? above->getLight(Space::Block::index(indPos), 3) :
|
||||
// game.getDefs().blockFromId(chunk->getBlock(indPos)).lightPropagates ? 15 : 0;
|
||||
|
||||
// if (!light) continue;
|
||||
|
||||
// auto& blockDef = game.getDefs().blockFromId(chunk->getBlock(indPos));
|
||||
// if (!blockDef.lightPropagates) light = 0;
|
||||
// else {
|
||||
// chunk->setLight(ind, 3, light);
|
||||
// job.sunlightQueue.emplace(ind, chunk);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
chunk->generationState = Chunk::GenerationState::GENERATED;
|
||||
}
|
||||
|
||||
void MapGen::setBlock(MapGen::Job& job, ivec3 worldPos, u16 block, Chunk* hint) {
|
||||
if (block == DefinitionAtlas::INVALID) return;
|
||||
u16 ind = Space::Block::index(worldPos);
|
||||
|
||||
|
||||
if (hint && Space::Chunk::world::fromBlock(worldPos) == hint->getPos()) {
|
||||
if (hint->getBlock(ind) <= DefinitionAtlas::AIR) hint->setBlock(ind, block);
|
||||
}
|
||||
|
|
|
@ -27,56 +27,56 @@ class MapGen {
|
|||
public:
|
||||
/** The precision of the Biome map, as a divisor of the chunk size. */
|
||||
constexpr static u8 BIOP = 4;
|
||||
|
||||
|
||||
/** The precision of the Terrain maps, as a divisor of the chunk size. */
|
||||
constexpr static u8 TERP = 4;
|
||||
|
||||
|
||||
/** A type alias for the type the map of Chunks stored in the Job. */
|
||||
typedef std::unordered_map<ivec3, Chunk*, Vec::ivec3> ChunkMap;
|
||||
|
||||
|
||||
/**
|
||||
* A struct representing a single position in a chunk at which sunlight should be updated at.
|
||||
*/
|
||||
|
||||
|
||||
struct SunlightNode {
|
||||
SunlightNode(u16 index, Chunk* chunk) : index(index), chunk(chunk) {};
|
||||
|
||||
|
||||
u16 index;
|
||||
Chunk* chunk;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A struct containing all the information for a generation job.
|
||||
* Contains a list of chunks, Noise samples, and the world position of the the job's root.
|
||||
*/
|
||||
|
||||
|
||||
struct Job {
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new job with the root position and size specified, and initializes the NoiseSample params.
|
||||
* @param pos - The root position of the job.
|
||||
* @param size - The size in chunks of the job.
|
||||
*/
|
||||
|
||||
|
||||
Job(ivec3 pos, u16 size) :
|
||||
pos(pos), size(size),
|
||||
volume {{ size * TERP, (size + 1) * TERP }, { 1, 1.25 }}, heightmap {{ size * TERP, 0 }},
|
||||
temperature {{ size * BIOP, 0 }}, roughness {{ size * BIOP, 0 }}, humidity {{ size * BIOP, 0 }} {}
|
||||
|
||||
|
||||
ivec3 pos {};
|
||||
u16 size {};
|
||||
|
||||
|
||||
uptr<ChunkMap> chunks = make_unique<ChunkMap>();
|
||||
std::queue<SunlightNode> sunlightQueue {};
|
||||
|
||||
|
||||
NoiseSample volume, heightmap;
|
||||
NoiseSample temperature, humidity, roughness;
|
||||
};
|
||||
|
||||
|
||||
typedef array<f32, 4096> ChunkData;
|
||||
|
||||
|
||||
MapGen(const MapGen& o) = delete;
|
||||
|
||||
|
||||
/**
|
||||
* Create a MapGen object with the seed and biomes provided.
|
||||
*
|
||||
|
@ -85,9 +85,9 @@ public:
|
|||
* @param seed - A seed to base the generation off of.
|
||||
* @param biomes - A list of biome identifiers or tags to include in generation.
|
||||
*/
|
||||
|
||||
|
||||
MapGen(Subgame& game, World& world, u32 seed, std::unordered_set<string> biomes);
|
||||
|
||||
|
||||
/**
|
||||
* Generate a single chunk at the dimension and position provided.
|
||||
* As with all generate* functions, this may result in extraneous chunk partials being created.
|
||||
|
@ -97,9 +97,9 @@ public:
|
|||
* @param pos - The position in the dimension to generate the chunk.
|
||||
* @returns a set of positions that were generated by this function call.
|
||||
*/
|
||||
|
||||
|
||||
[[maybe_unused]] uptr<ChunkMap> generateChunk(u16 dim, ivec3 pos);
|
||||
|
||||
|
||||
/**
|
||||
* Generate a mapblock at the dimension and position provided.
|
||||
* As with all generate* functions, this may result in extraneous chunk partials being created.
|
||||
|
@ -109,9 +109,9 @@ public:
|
|||
* @param pos - The position in the dimension to generate the chunk.
|
||||
* @returns a set of positions that were generated by this function call.
|
||||
*/
|
||||
|
||||
|
||||
uptr<ChunkMap> generateMapBlock(u16 dim, ivec3 pos);
|
||||
|
||||
|
||||
/**
|
||||
* The underlying generate function called by both generateMapBlock and generateChunk.
|
||||
* Can also be called on it's own to generate an arbitrary region of chunks.
|
||||
|
@ -121,11 +121,11 @@ public:
|
|||
* @param pos - The position in the dimension to generate the chunk.
|
||||
* @return - A set of positions that were generated by this function call.
|
||||
*/
|
||||
|
||||
|
||||
uptr<ChunkMap> generateArea(u16 dim, ivec3 origin, u16 size = 1);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/**
|
||||
* Get the closest biome to the provided environmental values from the Vonoroi map.
|
||||
* Returns the index of the matched biome.
|
||||
|
@ -135,18 +135,18 @@ private:
|
|||
* @param roughness - The roughness value of the position to check.
|
||||
* @returns the biome index of the environmentally closest biome.
|
||||
*/
|
||||
|
||||
|
||||
u16 getBiomeAt(f32 temperature, f32 humidity, f32 roughness);
|
||||
|
||||
|
||||
/**
|
||||
* Generate the Vonoroi biome map, using the biomes listed,
|
||||
* according to their definition parameters.
|
||||
*
|
||||
* @param biomes - The biomes to add to the map.
|
||||
*/
|
||||
|
||||
|
||||
void generateVoronoi(const std::unordered_set<u16>& biomes);
|
||||
|
||||
|
||||
/**
|
||||
* Create a density array for a chunk using a generation Job and an offset within it.
|
||||
* Returns a flattened array of block densities for every point in the chunk.
|
||||
|
@ -155,9 +155,9 @@ private:
|
|||
* @param localPos - The offset of the chunk's data within the job.
|
||||
* @returns a ChunkData array containing the chunk's density.
|
||||
*/
|
||||
|
||||
|
||||
static uptr<ChunkData> populateChunkDensity(Job& job, ivec3 localPos);
|
||||
|
||||
|
||||
/**
|
||||
* Create a depth array for a chunk using a generation Job and the chunk densities around it.
|
||||
* Returns a flattened array of block depths for every point in the chunk.
|
||||
|
@ -166,9 +166,9 @@ private:
|
|||
* @param chunkDensityAbove - A density array of the chunk above it.
|
||||
* @returns a ChunkData array containing the chunk's depth.
|
||||
*/
|
||||
|
||||
|
||||
static uptr<ChunkData> populateChunkDepth(uptr<ChunkData>& chunkDensity, uptr<ChunkData> chunkDensityAbove);
|
||||
|
||||
|
||||
/**
|
||||
* Generates a chunk's blocks from a generation Job and an offset within it, and inserts it into the Job.
|
||||
* Combines with any partials that have been previously created at that position within job.
|
||||
|
@ -181,9 +181,9 @@ private:
|
|||
* @param biomeMap - The two-dimensional biome array of the entire generation area.
|
||||
* @param depthMap - The depth map of the chunk being generated.
|
||||
*/
|
||||
|
||||
|
||||
void generateChunkBlocks(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap);
|
||||
|
||||
|
||||
/**
|
||||
* Generates structures for a Chunk based on data within the generation job and an offset within it.
|
||||
* Also generates initial light cascade, which will later be refined by propogateSunlightNodes.
|
||||
|
@ -194,9 +194,9 @@ private:
|
|||
* @param biomeMap - The two-dimensional biome array of the entire generation area.
|
||||
* @param depthMap - The depth map of the chunk being generated.
|
||||
*/
|
||||
|
||||
|
||||
void generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap);
|
||||
|
||||
|
||||
/**
|
||||
* Sets a block at the position specified into the Job, if the block at said position is not filled by
|
||||
* a material greater than air. If a chunk does not exist at the specified position, a partial is generated
|
||||
|
@ -207,23 +207,23 @@ private:
|
|||
* @param block - The block to set.
|
||||
* @param hint - An optional parameter that may speed up the function if set to the chunk to set to.
|
||||
*/
|
||||
|
||||
|
||||
static void setBlock(Job& job, ivec3 worldPos, u16 block, Chunk* hint);
|
||||
|
||||
|
||||
/**
|
||||
* Calculates and smooths sunlight for an entire Job's chunks.
|
||||
*
|
||||
* @param job - The job to act upon.
|
||||
*/
|
||||
|
||||
|
||||
void propogateSunlightNodes(Job& job);
|
||||
|
||||
|
||||
u32 seed = 0;
|
||||
MapGenProps props;
|
||||
|
||||
|
||||
constexpr const static u16 voronoiSize = 64;
|
||||
Voronoi3D voronoi { voronoiSize };
|
||||
|
||||
|
||||
Subgame& game;
|
||||
World& world;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
|||
|
||||
vec3 lookOffset{};
|
||||
|
||||
bool flying = false;
|
||||
bool flying = true;
|
||||
|
||||
string handList = "";
|
||||
string wieldList = "";
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
|
||||
ENetPeer* getPeer();
|
||||
|
||||
bool changedMapBlocks = false;
|
||||
bool changedMapBlocks = true;
|
||||
vec3 lastPos = vec3(INFINITY);
|
||||
|
||||
private:
|
||||
|
|
|
@ -121,6 +121,6 @@ end
|
|||
|
||||
zepha.register_keybind("zeus:inventory:open_inventory", {
|
||||
description = "Open Inventory",
|
||||
default = zepha.keys.e,
|
||||
default = zepha.keys['.'],
|
||||
on_press = inventory.open_inventory
|
||||
})
|
|
@ -81,7 +81,7 @@ local leaf_layer_3 = {
|
|||
|
||||
local tree = zepha.create_structure({
|
||||
origin = V(2, 2, 2),
|
||||
schematic = {
|
||||
layout = {
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
|
|
|
@ -2,7 +2,7 @@ local identifier = "zeus:world:highlands"
|
|||
|
||||
local grass = zepha.create_structure({
|
||||
origin = V{1, 2, 3},
|
||||
schematic = {
|
||||
layout = {
|
||||
{{"zeus:default:tall_grass_4"}}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -23,9 +23,9 @@ local shrub_layer_2 = {
|
|||
}
|
||||
|
||||
local shrub = zepha.create_structure({
|
||||
origin = V{1, 1, 1},
|
||||
origin = V {1, 1, 1},
|
||||
probability = 0.01,
|
||||
schematic = {
|
||||
layout = {
|
||||
shrub_layer_0,
|
||||
shrub_layer_1,
|
||||
shrub_layer_2,
|
||||
|
@ -38,7 +38,7 @@ for i = 1, 5 do
|
|||
table.insert(structures, zepha.create_structure({
|
||||
origin = V {1, 1, 1},
|
||||
probability = 0.04,
|
||||
schematic = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
layout = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
}))
|
||||
end
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
|
@ -131,6 +131,6 @@ end
|
|||
|
||||
zepha.register_keybind("zeus:inventory:open_inventory", {
|
||||
description = "Open Inventory",
|
||||
default = zepha.keys.p,
|
||||
default = zepha.keys['.'],
|
||||
on_press = inventory.open_inventory
|
||||
})
|
|
@ -1,49 +1,49 @@
|
|||
local identifier = "zeus:world:desert"
|
||||
|
||||
local noise = {
|
||||
heightmap = {
|
||||
module = "add",
|
||||
sources = {{
|
||||
module = "const",
|
||||
value = -80
|
||||
}, {
|
||||
-- Elevation
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.02,
|
||||
octaves = 8
|
||||
},
|
||||
scale = 20,
|
||||
bias = 32
|
||||
}, {
|
||||
-- Features
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.8,
|
||||
octaves = 3,
|
||||
},
|
||||
scale = 5,
|
||||
bias = 6
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
zepha.register_biome(identifier, {
|
||||
environment = {
|
||||
temperature = 40/100,
|
||||
humidity = 20/100,
|
||||
roughness = 10/100
|
||||
},
|
||||
blocks = {
|
||||
top = "zeus:default:sand",
|
||||
soil = "zeus:default:sand",
|
||||
rock = "zeus:default:sandstone"
|
||||
},
|
||||
tags = { natural = 1, default = 1 },
|
||||
biome_tint = "#e6fa61",
|
||||
noise = noise
|
||||
})
|
||||
|
||||
return identifier;
|
||||
-- local identifier = "zeus:world:desert"
|
||||
--
|
||||
-- local noise = {
|
||||
-- heightmap = {
|
||||
-- module = "add",
|
||||
-- sources = {{
|
||||
-- module = "const",
|
||||
-- value = -80
|
||||
-- }, {
|
||||
-- -- Elevation
|
||||
-- module = "scale_bias",
|
||||
-- source = {
|
||||
-- module = "perlin",
|
||||
-- frequency = 0.02,
|
||||
-- octaves = 8
|
||||
-- },
|
||||
-- scale = 20,
|
||||
-- bias = 32
|
||||
-- }, {
|
||||
-- -- Features
|
||||
-- module = "scale_bias",
|
||||
-- source = {
|
||||
-- module = "perlin",
|
||||
-- frequency = 0.8,
|
||||
-- octaves = 3,
|
||||
-- },
|
||||
-- scale = 5,
|
||||
-- bias = 6
|
||||
-- }}
|
||||
-- }
|
||||
-- }
|
||||
--
|
||||
-- zepha.register_biome(identifier, {
|
||||
-- environment = {
|
||||
-- temperature = 40/100,
|
||||
-- humidity = 20/100,
|
||||
-- roughness = 10/100
|
||||
-- },
|
||||
-- blocks = {
|
||||
-- top = "zeus:default:sand",
|
||||
-- soil = "zeus:default:sand",
|
||||
-- rock = "zeus:default:sandstone"
|
||||
-- },
|
||||
-- tags = { natural = 1, default = 1 },
|
||||
-- biome_tint = "#e6fa61",
|
||||
-- noise = noise
|
||||
-- })
|
||||
--
|
||||
-- return identifier;
|
|
@ -1,178 +1,178 @@
|
|||
local identifier = "zeus:world:forest"
|
||||
|
||||
local noise = {
|
||||
heightmap = {
|
||||
module = "add",
|
||||
sources = {
|
||||
runfile(_PATH .. 'world_noise'), {
|
||||
-- Features
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = .5,
|
||||
octaves = 3,
|
||||
},
|
||||
scale = 3,
|
||||
bias = 0
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
--local woo = "zeus:default:wood"
|
||||
--local lea = "zeus:default:leaves"
|
||||
--local inv = "invalid"
|
||||
-- local identifier = "zeus:world:forest"
|
||||
--
|
||||
--local trunk_layer_0 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
--}
|
||||
--
|
||||
--local trunk_layer_1 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, woo, inv, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, inv, woo, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
--}
|
||||
--
|
||||
--local trunk_layer_2 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, woo, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
--}
|
||||
--
|
||||
--local leaf_layer_1 = {
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { lea, lea, lea, lea, lea },
|
||||
-- { lea, lea, woo, lea, lea },
|
||||
-- { lea, lea, lea, lea, lea },
|
||||
-- { inv, lea, lea, lea, inv }
|
||||
--}
|
||||
--
|
||||
--local leaf_layer_2 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { inv, lea, woo, lea, inv },
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
--}
|
||||
--
|
||||
--local leaf_layer_3 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, lea, lea, inv, inv },
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { inv, inv, lea, lea, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
--}
|
||||
--
|
||||
--local tree = zepha.create_structure({
|
||||
-- origin = V(2, 2, 2),
|
||||
-- probability = 0.01,
|
||||
-- schematic = {
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_1,
|
||||
-- trunk_layer_1,
|
||||
-- trunk_layer_1,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- leaf_layer_2,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_2,
|
||||
-- leaf_layer_3
|
||||
-- }
|
||||
--})
|
||||
--
|
||||
--local woo = "zeus:default:wood"
|
||||
--local lea = "zeus:default:leaves"
|
||||
--local inv = "invalid"
|
||||
--
|
||||
--local shrub_layer_0 = {
|
||||
-- { inv, inv, inv },
|
||||
-- { inv, woo, inv },
|
||||
-- { inv, inv, inv }
|
||||
--}
|
||||
--
|
||||
--local shrub_layer_1 = {
|
||||
-- { inv, lea, inv },
|
||||
-- { lea, woo, lea },
|
||||
-- { inv, lea, inv }
|
||||
--}
|
||||
--
|
||||
--local shrub_layer_2 = {
|
||||
-- { inv, inv, inv },
|
||||
-- { inv, lea, inv },
|
||||
-- { inv, inv, inv }
|
||||
--}
|
||||
--
|
||||
--local shrub = zepha.create_structure({
|
||||
-- origin = V{1, 1, 1},
|
||||
-- probability = 0.005,
|
||||
-- schematic = {
|
||||
-- shrub_layer_0,
|
||||
-- shrub_layer_1,
|
||||
-- shrub_layer_2,
|
||||
-- local noise = {
|
||||
-- heightmap = {
|
||||
-- module = "add",
|
||||
-- sources = {
|
||||
-- runfile(_PATH .. 'world_noise'), {
|
||||
-- -- Features
|
||||
-- module = "scale_bias",
|
||||
-- source = {
|
||||
-- module = "perlin",
|
||||
-- frequency = .5,
|
||||
-- octaves = 3,
|
||||
-- },
|
||||
-- scale = 3,
|
||||
-- bias = 0
|
||||
-- } }
|
||||
-- }
|
||||
--})
|
||||
-- }
|
||||
--
|
||||
--local structures = { tree, shrub }
|
||||
-- --local woo = "zeus:default:wood"
|
||||
-- --local lea = "zeus:default:leaves"
|
||||
-- --local inv = "invalid"
|
||||
-- --
|
||||
-- --local trunk_layer_0 = {
|
||||
-- -- { inv, inv, inv, inv, inv },
|
||||
-- -- { inv, woo, woo, woo, inv },
|
||||
-- -- { inv, woo, woo, woo, inv },
|
||||
-- -- { inv, woo, woo, woo, inv },
|
||||
-- -- { inv, inv, inv, inv, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local trunk_layer_1 = {
|
||||
-- -- { inv, inv, inv, inv, inv },
|
||||
-- -- { inv, inv, woo, inv, inv },
|
||||
-- -- { inv, woo, woo, woo, inv },
|
||||
-- -- { inv, inv, woo, inv, inv },
|
||||
-- -- { inv, inv, inv, inv, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local trunk_layer_2 = {
|
||||
-- -- { inv, inv, inv, inv, inv },
|
||||
-- -- { inv, inv, inv, inv, inv },
|
||||
-- -- { inv, inv, woo, inv, inv },
|
||||
-- -- { inv, inv, inv, inv, inv },
|
||||
-- -- { inv, inv, inv, inv, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local leaf_layer_1 = {
|
||||
-- -- { inv, lea, lea, lea, inv },
|
||||
-- -- { lea, lea, lea, lea, lea },
|
||||
-- -- { lea, lea, woo, lea, lea },
|
||||
-- -- { lea, lea, lea, lea, lea },
|
||||
-- -- { inv, lea, lea, lea, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local leaf_layer_2 = {
|
||||
-- -- { inv, inv, inv, inv, inv },
|
||||
-- -- { inv, lea, lea, lea, inv },
|
||||
-- -- { inv, lea, woo, lea, inv },
|
||||
-- -- { inv, lea, lea, lea, inv },
|
||||
-- -- { inv, inv, inv, inv, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local leaf_layer_3 = {
|
||||
-- -- { inv, inv, inv, inv, inv },
|
||||
-- -- { inv, lea, lea, inv, inv },
|
||||
-- -- { inv, lea, lea, lea, inv },
|
||||
-- -- { inv, inv, lea, lea, inv },
|
||||
-- -- { inv, inv, inv, inv, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local tree = zepha.create_structure({
|
||||
-- -- origin = V(2, 2, 2),
|
||||
-- -- probability = 0.01,
|
||||
-- -- schematic = {
|
||||
-- -- trunk_layer_0,
|
||||
-- -- trunk_layer_0,
|
||||
-- -- trunk_layer_0,
|
||||
-- -- trunk_layer_0,
|
||||
-- -- trunk_layer_1,
|
||||
-- -- trunk_layer_1,
|
||||
-- -- trunk_layer_1,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- trunk_layer_2,
|
||||
-- -- leaf_layer_2,
|
||||
-- -- leaf_layer_1,
|
||||
-- -- leaf_layer_1,
|
||||
-- -- leaf_layer_1,
|
||||
-- -- leaf_layer_1,
|
||||
-- -- leaf_layer_2,
|
||||
-- -- leaf_layer_3
|
||||
-- -- }
|
||||
-- --})
|
||||
-- --
|
||||
-- --local woo = "zeus:default:wood"
|
||||
-- --local lea = "zeus:default:leaves"
|
||||
-- --local inv = "invalid"
|
||||
-- --
|
||||
-- --local shrub_layer_0 = {
|
||||
-- -- { inv, inv, inv },
|
||||
-- -- { inv, woo, inv },
|
||||
-- -- { inv, inv, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local shrub_layer_1 = {
|
||||
-- -- { inv, lea, inv },
|
||||
-- -- { lea, woo, lea },
|
||||
-- -- { inv, lea, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local shrub_layer_2 = {
|
||||
-- -- { inv, inv, inv },
|
||||
-- -- { inv, lea, inv },
|
||||
-- -- { inv, inv, inv }
|
||||
-- --}
|
||||
-- --
|
||||
-- --local shrub = zepha.create_structure({
|
||||
-- -- origin = V{1, 1, 1},
|
||||
-- -- probability = 0.005,
|
||||
-- -- schematic = {
|
||||
-- -- shrub_layer_0,
|
||||
-- -- shrub_layer_1,
|
||||
-- -- shrub_layer_2,
|
||||
-- -- }
|
||||
-- --})
|
||||
-- --
|
||||
-- --local structures = { tree, shrub }
|
||||
-- --
|
||||
-- --for i = 1, 5 do
|
||||
-- -- table.insert(structures, zepha.create_structure({
|
||||
-- -- origin = V(),
|
||||
-- -- probability = 0.01,
|
||||
-- -- schematic = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
-- -- }))
|
||||
-- --end
|
||||
-- --
|
||||
-- --table.insert(structures, zepha.create_structure({
|
||||
-- -- origin = V(),
|
||||
-- -- probability = 0.0025,
|
||||
-- -- schematic = {{{ "zeus:flowers:flower_red_mushroom" }}}
|
||||
-- --}))
|
||||
-- --
|
||||
-- --table.insert(structures, zepha.create_structure({
|
||||
-- -- origin = V(),
|
||||
-- -- probability = 0.0025,
|
||||
-- -- schematic = {{{ "zeus:flowers:flower_brown_mushroom" }}}
|
||||
-- --}))
|
||||
--
|
||||
--for i = 1, 5 do
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.01,
|
||||
-- schematic = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
-- }))
|
||||
--end
|
||||
-- local structures = {}
|
||||
--
|
||||
--table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.0025,
|
||||
-- schematic = {{{ "zeus:flowers:flower_red_mushroom" }}}
|
||||
--}))
|
||||
-- zepha.register_biome(identifier, {
|
||||
-- environment = {
|
||||
-- temperature = 15/100,
|
||||
-- humidity = 80/100,
|
||||
-- roughness = 20/100,
|
||||
-- },
|
||||
-- blocks = {
|
||||
-- top = "zeus:default:podzol",
|
||||
-- soil = "zeus:default:dirt",
|
||||
-- rock = "zeus:default:stone"
|
||||
-- },
|
||||
-- tags = { natural = 1, default = 1 },
|
||||
-- structures = structures,
|
||||
-- biome_tint = "#7beb26",
|
||||
-- noise = noise
|
||||
-- })
|
||||
--
|
||||
--table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.0025,
|
||||
-- schematic = {{{ "zeus:flowers:flower_brown_mushroom" }}}
|
||||
--}))
|
||||
|
||||
local structures = {}
|
||||
|
||||
zepha.register_biome(identifier, {
|
||||
environment = {
|
||||
temperature = 15/100,
|
||||
humidity = 80/100,
|
||||
roughness = 20/100,
|
||||
},
|
||||
blocks = {
|
||||
top = "zeus:default:podzol",
|
||||
soil = "zeus:default:dirt",
|
||||
rock = "zeus:default:stone"
|
||||
},
|
||||
tags = { natural = 1, default = 1 },
|
||||
structures = structures,
|
||||
biome_tint = "#7beb26",
|
||||
noise = noise
|
||||
})
|
||||
|
||||
return identifier
|
||||
-- return identifier
|
|
@ -1,57 +1,57 @@
|
|||
local identifier = "zeus:world:highlands"
|
||||
|
||||
local noise = {
|
||||
volume = {
|
||||
module = "add",
|
||||
sources = {{
|
||||
module = "add",
|
||||
sources = {{
|
||||
-- Voronoi
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "voronoi",
|
||||
frequency = 0.2,
|
||||
displacement = 5
|
||||
},
|
||||
scale = 8,
|
||||
bias = -32
|
||||
}, {
|
||||
-- Features
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.6,
|
||||
octaves = 3,
|
||||
},
|
||||
scale = 3
|
||||
}}
|
||||
}, {
|
||||
-- Variation
|
||||
module = "scale_bias",
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.05,
|
||||
octaves = 6
|
||||
},
|
||||
scale = 15
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
zepha.register_biome(identifier, {
|
||||
environment = {
|
||||
temperature = 0/100,
|
||||
humidity = 0/100,
|
||||
roughness = 50/100
|
||||
},
|
||||
blocks = {
|
||||
top = "zeus:default:grass",
|
||||
soil = "zeus:default:dirt",
|
||||
rock = "zeus:default:stone"
|
||||
},
|
||||
tags = { natural = 1, default = 1 },
|
||||
biome_tint = "#c2fa61",
|
||||
noise = noise
|
||||
})
|
||||
|
||||
return identifier
|
||||
-- local identifier = "zeus:world:highlands"
|
||||
--
|
||||
-- local noise = {
|
||||
-- volume = {
|
||||
-- module = "add",
|
||||
-- sources = {{
|
||||
-- module = "add",
|
||||
-- sources = {{
|
||||
-- -- Voronoi
|
||||
-- module = "scale_bias",
|
||||
-- source = {
|
||||
-- module = "voronoi",
|
||||
-- frequency = 0.2,
|
||||
-- displacement = 5
|
||||
-- },
|
||||
-- scale = 8,
|
||||
-- bias = -32
|
||||
-- }, {
|
||||
-- -- Features
|
||||
-- module = "scale_bias",
|
||||
-- source = {
|
||||
-- module = "perlin",
|
||||
-- frequency = 0.6,
|
||||
-- octaves = 3,
|
||||
-- },
|
||||
-- scale = 3
|
||||
-- }}
|
||||
-- }, {
|
||||
-- -- Variation
|
||||
-- module = "scale_bias",
|
||||
-- source = {
|
||||
-- module = "perlin",
|
||||
-- frequency = 0.05,
|
||||
-- octaves = 6
|
||||
-- },
|
||||
-- scale = 15
|
||||
-- }}
|
||||
-- }
|
||||
-- }
|
||||
--
|
||||
-- zepha.register_biome(identifier, {
|
||||
-- environment = {
|
||||
-- temperature = 0/100,
|
||||
-- humidity = 0/100,
|
||||
-- roughness = 50/100
|
||||
-- },
|
||||
-- blocks = {
|
||||
-- top = "zeus:default:grass",
|
||||
-- soil = "zeus:default:dirt",
|
||||
-- rock = "zeus:default:stone"
|
||||
-- },
|
||||
-- tags = { natural = 1, default = 1 },
|
||||
-- biome_tint = "#c2fa61",
|
||||
-- noise = noise
|
||||
-- })
|
||||
--
|
||||
-- return identifier
|
|
@ -5,15 +5,43 @@ local leaf = "zeus:default:leaves"
|
|||
local none = "invalid"
|
||||
|
||||
local structures = {}
|
||||
--
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- -- noise = {
|
||||
-- -- module = "perlin",
|
||||
-- -- frequency = 0.002,
|
||||
-- -- octaves = 8
|
||||
-- -- },
|
||||
-- -- region_size = 4,
|
||||
-- probability = 0.1,
|
||||
-- -- origin = V{1, 1, 1},
|
||||
-- origin = V(),
|
||||
-- layout = {{{ "zeus:flowers:flower_geranium" }}}
|
||||
-- }))
|
||||
|
||||
for i = 1, 5 do
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(),
|
||||
probability = 0.1,
|
||||
layout = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
}))
|
||||
end
|
||||
--
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(),
|
||||
probability = 0.025,
|
||||
layout = {{{ "zeus:flowers:flower_geranium" }}}
|
||||
}))
|
||||
|
||||
table.insert(structures, zepha.create_structure({
|
||||
noise = {
|
||||
module = "perlin",
|
||||
frequency = 0.002,
|
||||
octaves = 8
|
||||
},
|
||||
region_size = 4,
|
||||
origin = V{1, 1, 1},
|
||||
origin = V(),
|
||||
probability = 0.025,
|
||||
layout = {{{ "zeus:flowers:flower_white_dandelion" }}}
|
||||
}))
|
||||
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(),
|
||||
probability = 0.025,
|
||||
layout = {{
|
||||
{ none, none, none },
|
||||
{ none, wood, none },
|
||||
|
@ -29,28 +57,105 @@ table.insert(structures, zepha.create_structure({
|
|||
}}
|
||||
}))
|
||||
|
||||
--for i = 1, 5 do
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.1,
|
||||
-- layout = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
-- }))
|
||||
--end
|
||||
--
|
||||
--table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.025,
|
||||
-- layout = {{{ "zeus:flowers:flower_geranium" }}}
|
||||
--}))
|
||||
--
|
||||
--table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.025,
|
||||
-- layout = {{{ "zeus:flowers:flower_white_dandelion" }}}
|
||||
--}))
|
||||
local woo = "zeus:default:wood"
|
||||
local lea = "zeus:default:leaves"
|
||||
local inv = "invalid"
|
||||
|
||||
local trunk_layer_0 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local trunk_layer_1 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, woo, inv, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, inv, woo, inv, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local trunk_layer_2 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, woo, inv, inv },
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local leaf_layer_1 = {
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ lea, lea, lea, lea, lea },
|
||||
{ lea, lea, woo, lea, lea },
|
||||
{ lea, lea, lea, lea, lea },
|
||||
{ inv, lea, lea, lea, inv }
|
||||
}
|
||||
|
||||
local leaf_layer_2 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ inv, lea, woo, lea, inv },
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local leaf_layer_3 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, lea, lea, inv, inv },
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ inv, inv, lea, lea, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(2, 2, 2),
|
||||
probability = 0.0005,
|
||||
layout = {
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
trunk_layer_1,
|
||||
trunk_layer_1,
|
||||
trunk_layer_1,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
leaf_layer_2,
|
||||
leaf_layer_1,
|
||||
leaf_layer_1,
|
||||
leaf_layer_1,
|
||||
leaf_layer_1,
|
||||
leaf_layer_2,
|
||||
leaf_layer_3
|
||||
}
|
||||
}))
|
||||
|
||||
local noise = {
|
||||
heightmap = runfile(_PATH .. 'world_noise')
|
||||
-- heightmap = runfile(_PATH .. 'world_noise'),
|
||||
volume = {
|
||||
module = "scale_bias",
|
||||
scale = 3000,
|
||||
bias = -3500,
|
||||
source = {
|
||||
module = "scale_point",
|
||||
y_scale = 2,
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zepha.register_biome(identifier, {
|
||||
|
|
|
@ -5,8 +5,8 @@ zepha.create_dimension('zeus:world:default', {
|
|||
biomes = { '#natural', '#default' }
|
||||
})
|
||||
|
||||
zepha.create_dimension('zeus:world:endless_desert', {
|
||||
biomes = { 'zeus:world:desert' }
|
||||
})
|
||||
-- zepha.create_dimension('zeus:world:endless_desert', {
|
||||
-- biomes = { 'zeus:world:desert' }
|
||||
-- })
|
||||
|
||||
zepha.set_default_dimension('zeus:world:default')
|
Loading…
Reference in New Issue