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.
|
||||
*/
|
||||
|
||||
// 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;
|
||||
virtual bool updateChunkUse(ivec3 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;
|
||||
|
||||
void setPos(glm::vec3 pos);
|
||||
private:
|
||||
|
||||
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
|
|
@ -184,6 +184,7 @@ void DebugGui::update(sptr<LocalPlayer> player, f64 delta, u32 interpolatedChunk
|
|||
|
||||
// Chunk States
|
||||
|
||||
if (chunkTimer == 0) {
|
||||
auto chunkStates = get<GuiCellGraph>("chunkStates");
|
||||
ivec3 off = { 0, 0, 0 };
|
||||
for (off.x = 0; off.x < CHUNK_RANGE; off.x++) {
|
||||
|
@ -210,6 +211,9 @@ void DebugGui::update(sptr<LocalPlayer> player, f64 delta, u32 interpolatedChunk
|
|||
}
|
||||
}
|
||||
chunkStates->refresh();
|
||||
}
|
||||
|
||||
chunkTimer = (chunkTimer + 1) % CHUNK_INTERVAL;
|
||||
|
||||
// Crosshair information
|
||||
|
||||
|
|
|
@ -47,5 +47,8 @@ private:
|
|||
SubgamePtr game;
|
||||
LocalWorld& world;
|
||||
|
||||
u16 chunkTimer = 0;
|
||||
constexpr static u16 CHUNK_INTERVAL = 5;
|
||||
|
||||
Visibility state = Visibility::ON;
|
||||
};
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
//
|
||||
// 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);
|
||||
|
@ -33,11 +29,11 @@ class GameGui {
|
|||
|
||||
void drawMenu(Renderer& renderer);
|
||||
|
||||
private:
|
||||
private:
|
||||
SubgamePtr defs;
|
||||
Renderer& renderer;
|
||||
|
||||
glm::ivec2 win{};
|
||||
ivec2 win {};
|
||||
bool inMenu = false;
|
||||
|
||||
std::shared_ptr<LuaGuiElement> hudRootElem = nullptr;
|
||||
|
|
|
@ -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,8 +22,8 @@ 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);
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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"
|
||||
|
@ -94,7 +90,7 @@ namespace Util {
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
auto finishedPackets = packetStream->update();
|
||||
// if (finishedPackets->size()) std::cout << finishedPackets->size() << " finished packets" << std::endl;
|
||||
for (auto& data : *finishedPackets) {
|
||||
let packet = s.packet(Packet::Type::MAPBLOCK);
|
||||
|
||||
for (auto& client : clients.getClients()) {
|
||||
if (!client.second->player) continue;
|
||||
data->packet->sendTo(client.second->peer, Packet::Channel::WORLD);
|
||||
packet.sendTo(client.second->peer, Packet::Channel::WORLD);
|
||||
}
|
||||
|
||||
genCount++;
|
||||
totalGens++;
|
||||
}
|
||||
}
|
||||
if (!finishedGen->empty()) {
|
||||
t.printElapsedMs();
|
||||
std::cout << totalGens << std::endl;
|
||||
}
|
||||
|
||||
// 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);
|
||||
// }
|
||||
// }
|
||||
|
||||
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);
|
||||
|
||||
virtual DimensionPtr
|
||||
createDimension(const std::string& identifier, std::unordered_set<std::string>& biomes) override;
|
||||
/** Sends a mod message to the channel provided. */
|
||||
virtual void sendMessage(const string& channel, const string& message) 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;
|
||||
|
||||
usize totalGens = 0;
|
||||
|
||||
/** The amount of mapblocks that were generated last frame. */
|
||||
u32 generatedMapBlocks = 0;
|
||||
std::vector<ivec3> generateOrder;
|
||||
|
||||
/** 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 };
|
||||
const ivec2 sendRange = { 4, 4 };
|
||||
const ivec2 activeChunkRange = { 16, 16 };
|
||||
};
|
||||
|
||||
/** 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) {
|
||||
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) {
|
||||
it->second->remove(m);
|
||||
if (it->second->count <= 0) goto erase_region_and_continue;
|
||||
}
|
||||
else {
|
||||
for (u16 c = 0; c < 64; c++) {
|
||||
let chunk = mapBlock->get(c);
|
||||
if (chunk) chunk->compressIfIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!clientNearby) region.second->remove(i);
|
||||
else {
|
||||
for (unsigned short c = 0; c < 64; c++) {
|
||||
auto chunk = mapBlock->get(c);
|
||||
if (!chunk) continue;
|
||||
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"
|
||||
|
@ -95,13 +97,17 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -223,7 +229,7 @@ void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biome
|
|||
* (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;
|
||||
|
@ -233,10 +239,10 @@ void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biome
|
|||
|
||||
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];
|
||||
|
@ -247,17 +253,17 @@ 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 == -1) light = above ? above->getLight(Space::Block::index(indPos), 3) :
|
||||
// game.getDefs().blockFromId(chunk->getBlock(indPos)).lightPropagates ? 15 : 0;
|
||||
|
||||
if (!light) continue;
|
||||
// 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);
|
||||
}
|
||||
// auto& blockDef = game.getDefs().blockFromId(chunk->getBlock(indPos));
|
||||
// if (!blockDef.lightPropagates) light = 0;
|
||||
// else {
|
||||
// chunk->setLight(ind, 3, light);
|
||||
// job.sunlightQueue.emplace(ind, chunk);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 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 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 }
|
||||
-- --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