diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1551aa32..4b0fa059 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 .) \ No newline at end of file diff --git a/src/client/conn/ClientNetworkInterpreter.cpp b/src/client/conn/ClientNetworkInterpreter.cpp index 3c1be64f..16a4c7b8 100644 --- a/src/client/conn/ClientNetworkInterpreter.cpp +++ b/src/client/conn/ClientNetworkInterpreter.cpp @@ -103,7 +103,7 @@ void ClientNetworkInterpreter::receivedPacket(uptr p) { } case Packet::Type::ENTITY_REMOVED: { - world.getActiveDimension().l()->serverEntitiesRemoved(p->d); + world.getActiveDimension().l()->removeServerEntities(p->d); break; } diff --git a/src/client/conn/ServerConnection.cpp b/src/client/conn/ServerConnection.cpp index af9be53a..e2305b17 100644 --- a/src/client/conn/ServerConnection.cpp +++ b/src/client/conn/ServerConnection.cpp @@ -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; } } diff --git a/src/client/graph/Drawable.h b/src/client/graph/Drawable.h index 3eb1caa0..c1f86042 100644 --- a/src/client/graph/Drawable.h +++ b/src/client/graph/Drawable.h @@ -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; }; diff --git a/src/client/graph/mesh/ChunkMesh.cpp b/src/client/graph/mesh/ChunkMesh.cpp deleted file mode 100644 index d80b55ec..00000000 --- a/src/client/graph/mesh/ChunkMesh.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created by aurailus on 25/11/18. -// - -#include "ChunkMesh.h" - -#include "ChunkVertex.h" - -void ChunkMesh::create(const std::vector& vertices, const std::vector& indices) { - indCount = static_cast(indices.size()); - - genArrays(static_cast(vertices.size() * sizeof(ChunkVertex)), - static_cast(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); -} \ No newline at end of file diff --git a/src/client/graph/mesh/ChunkMesh.h b/src/client/graph/mesh/ChunkMesh.h deleted file mode 100644 index 98d7de7a..00000000 --- a/src/client/graph/mesh/ChunkMesh.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Created by aurailus on 25/11/18. -// - -#pragma once - -#include -#include - -#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& vertices, const std::vector& indices); - - ~ChunkMesh() = default; -}; diff --git a/src/client/graph/mesh/ChunkMeshGenerator.cpp b/src/client/graph/mesh/ChunkMeshGenerator.cpp index 89ad9133..450304ff 100644 --- a/src/client/graph/mesh/ChunkMeshGenerator.cpp +++ b/src/client/graph/mesh/ChunkMeshGenerator.cpp @@ -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 chk, array, 6> adj, array& blockOffsets) : defs(defs), biomes(biomes), diff --git a/src/client/graph/mesh/ChunkMeshGenerator.h b/src/client/graph/mesh/ChunkMeshGenerator.h index e5d6ff03..a745c240 100644 --- a/src/client/graph/mesh/ChunkMeshGenerator.h +++ b/src/client/graph/mesh/ChunkMeshGenerator.h @@ -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, array, 6> adjacent, array& blockOffsets); private: @@ -27,7 +27,7 @@ private: LocalBiomeAtlas& biomes; usize indOffset = 0; - ChunkMeshDetails* meshDetails; + MeshChunkDetails* meshDetails; uptr chunk; array, 6> adjacent; diff --git a/src/client/graph/mesh/ChunkRenderElem.h b/src/client/graph/mesh/ChunkRenderElem.h index 3bc4ac20..59e3af48 100644 --- a/src/client/graph/mesh/ChunkRenderElem.h +++ b/src/client/graph/mesh/ChunkRenderElem.h @@ -1,20 +1,41 @@ -// -// Created by aurailus on 28/09/19. -// - #pragma once -#include +#include "util/Types.h" class Renderer; +/** + * An abstract class for a visual representation of one or more chunks. + * Currently used by MeshChunk, but in the future Mesh MapBlocks will use it as well. + * Keeps track of the chunk positions that are using this element, and if it should be kept alive. + */ + struct ChunkRenderElem { + ChunkRenderElem() = default; + ChunkRenderElem(vec3 pos): pos(pos) {}; + + /** Sets the element's visual position. */ + virtual void setPos(vec3 pos) { + this->pos = pos; + }; + + /** Gets the element's visual position. */ + virtual vec3 getPos() { + return pos; + }; + + /** Draws the element to the screen. */ virtual void draw(Renderer& renderer) = 0; - virtual glm::vec3 getPos() = 0; + /** + * Specifies if a chunk is using this render element. + * Returns a boolean indicating if there are any chunks using the element. + */ + + virtual bool updateChunkUse(ivec3 chunk, bool used) = 0; - // Used to determine if the RenderElem should be deleted. - // Bool is if the RenderElem should be kept alive. - // True = keep, False = remove - virtual bool updateChunkUse(glm::vec3 chunk, bool used) = 0; +protected: + + /** The element's visual position. */ + vec3 pos {}; }; diff --git a/src/client/graph/mesh/ChunkVertex.h b/src/client/graph/mesh/ChunkVertex.h deleted file mode 100644 index 97561be2..00000000 --- a/src/client/graph/mesh/ChunkVertex.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Created by aurailus on 24/08/19. -// - -#pragma once - -#include -#include -#include - -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) diff --git a/src/client/graph/mesh/Mesh.cpp b/src/client/graph/mesh/Mesh.cpp index ea83abf1..e6fc3f1c 100644 --- a/src/client/graph/mesh/Mesh.cpp +++ b/src/client/graph/mesh/Mesh.cpp @@ -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); } \ No newline at end of file diff --git a/src/client/graph/mesh/Mesh.h b/src/client/graph/mesh/Mesh.h index 701fb316..8e568a73 100644 --- a/src/client/graph/mesh/Mesh.h +++ b/src/client/graph/mesh/Mesh.h @@ -1,28 +1,27 @@ -// -// Created by aurailus on 24/08/19. -// - #pragma once #include +#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; }; diff --git a/src/client/graph/mesh/MeshChunk.cpp b/src/client/graph/mesh/MeshChunk.cpp index 833703ad..690cd1af 100644 --- a/src/client/graph/mesh/MeshChunk.cpp +++ b/src/client/graph/mesh/MeshChunk.cpp @@ -1,35 +1,36 @@ -// -// Created by aurailus on 15/12/18. -// - -#include +#include #include #include "MeshChunk.h" #include "client/graph/Renderer.h" -#include "client/graph/mesh/ChunkMesh.h" -void MeshChunk::create(std::vector& vertices, std::vector& indices) { - this->mesh = std::make_shared(); - mesh->create(vertices, indices); -} +MeshChunk::MeshChunk(const vec3 pos, const vec& vertices, const vec& indices) : + ChunkRenderElem(pos), mesh(make_unique(vertices, indices)) {} void MeshChunk::draw(Renderer& renderer) { glm::mat4 model = glm::mat4(1.0); - model = glm::translate(model, pos * static_cast(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& vertices, const vec& 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)); } \ No newline at end of file diff --git a/src/client/graph/mesh/MeshChunk.h b/src/client/graph/mesh/MeshChunk.h index 704f5b11..0a2a2934 100644 --- a/src/client/graph/mesh/MeshChunk.h +++ b/src/client/graph/mesh/MeshChunk.h @@ -1,34 +1,51 @@ -// -// Created by aurailus on 15/12/18. -// - #pragma once +#pragma clang diagnostic push +#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection" -#include -#include - +#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& vertices, std::vector& 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& vertices, const vec& indices); + }; + + /** Creates a new MeshChunk with the data provided. */ + MeshChunk(const vec3 pos, const vec& vertices, const vec& indices); void draw(Renderer& renderer) override; - bool updateChunkUse(glm::vec3 chunk, bool used) override; + bool updateChunkUse(ivec3 chunk, bool used) override; + +private: - void setPos(glm::vec3 pos); - - glm::vec3 getPos() override; - - private: - std::shared_ptr mesh = nullptr; - glm::vec3 pos{}; -}; \ No newline at end of file + /** The underlying mesh used by this chunk. */ + uptr mesh = nullptr; +}; + +#pragma clang diagnostic pop \ No newline at end of file diff --git a/src/client/gui/DebugGui.cpp b/src/client/gui/DebugGui.cpp index e24bf704..70b0ac6c 100644 --- a/src/client/gui/DebugGui.cpp +++ b/src/client/gui/DebugGui.cpp @@ -13,142 +13,142 @@ DebugGui::DebugGui(u16vec2 buffer, SubgamePtr game, LocalWorld& world, vec& perfSections) : game(game), world(world) { - + auto fontRef = game.l()->textures["font"]; auto fpsHistogramRef = game.l()->textures["histogram"]; auto genericHistogramRef = game.l()->textures["histogram_white"]; - + Font f(game.l()->textures, fontRef); - + auto crosshairText = make_shared("crosshairText"); crosshairText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f); add(crosshairText); - + auto dataText = make_shared("dataText"); dataText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f); add(dataText); - + auto interpGraph = make_shared("interpGraph"); interpGraph->create({ 244, 64 }, {}, "Interp", 120, 256, genericHistogramRef, f); add(interpGraph); - + auto meshGraph = make_shared("meshGraph"); meshGraph->create({ 244, 64 }, {}, "Mesh", 120, 32, genericHistogramRef, f); add(meshGraph); - + auto genGraph = make_shared("genGraph"); genGraph->create({ 244, 64 }, {}, "Gen", 120, 16, genericHistogramRef, f); add(genGraph); - + auto packetGraph = make_shared("packetGraph"); packetGraph->create({ 244, 64 }, {}, "Packets", 120, 32, genericHistogramRef, f); add(packetGraph); - + auto fpsGraph = make_shared("fpsGraph"); fpsGraph->create({ 244, 64 }, {}, "FPS", 120, 60, fpsHistogramRef, f); add(fpsGraph); - + auto drawsGraph = make_shared("drawsGraph"); drawsGraph->create({ 244, 64 }, {}, "Draw Calls", 120, 0, genericHistogramRef, f); add(drawsGraph); - + auto gpuGraph = make_shared("gpuGraph"); gpuGraph->create({ 244, 64 }, {}, "GPU", 120, 1, genericHistogramRef, f); add(gpuGraph); - + auto perfGraph = make_shared("perfGraph"); perfGraph->create(344, {}, perfSections, "Performance", f); add(perfGraph); - + auto chunkStates = make_shared("chunkStates"); chunkStates->create(6, vec4(4), CHUNK_RANGE, "Chunk Compression", f); chunkStates->refresh(); add(chunkStates); - + positionElements(buffer); } void DebugGui::positionElements(u16vec2 buffer) { get("crosshairText")->setPos({ buffer.x / 2 + 22, buffer.y / 2 - 7 }); get("dataText")->setPos({ 10, 10 }); - + get("genGraph")->setPos({ buffer.x - 254, buffer.y - 70 - 160 }); get("packetGraph")->setPos({ buffer.x - 254, buffer.y - 70 - 240 }); get("meshGraph")->setPos({ buffer.x - 254, buffer.y - 70 - 80 }); get("interpGraph")->setPos({ buffer.x - 254, buffer.y - 70 }); - + get("fpsGraph")->setPos({ buffer.x - 254, 10 }); get("drawsGraph")->setPos({ buffer.x - 254, 90 }); get("gpuGraph")->setPos({ buffer.x - 254, 90 + 80 }); get("perfGraph")->setPos({ buffer.x - 354 - 254, 10 }); - + get("chunkStates")->setPos({ buffer.x - 264 - 300, buffer.y - 334 }); } void DebugGui::update(sptr player, f64 delta, u32 interpolatedChunks, u32 generatedChunks, u32 recievedPackets, vec& perfTimings, u32 drawnMeshChunks, u32 generatedMeshChunks) { - + Target target = player->getTarget(); - + auto& onBiomeDef = game->getBiomes().biomeFromId( world.getActiveDimension()->getBiome(glm::floor(player->getPos()))); - + // FPS and Draw calls graphs - + get("perfGraph")->updateTimings(perfTimings); get("fpsGraph")->pushValue(1 / delta); get("drawsGraph")->pushValue(drawnMeshChunks); - + int videoMemAvail, videoMemTotal; - + glGetIntegerv(0x9048, &videoMemTotal); glGetIntegerv(0x9049, &videoMemAvail); - + get("gpuGraph")->pushValue(std::round( (videoMemTotal - videoMemAvail) / static_cast(videoMemTotal) * 100.0) / 100.0f); - - + + // Thread information graphs - + get("meshGraph")->pushValue(generatedMeshChunks); get("interpGraph")->pushValue(interpolatedChunks); get("genGraph")->pushValue(generatedChunks); get("packetGraph")->pushValue(recievedPackets); - + // Textual information - + vec3 playerPos = glm::floor(player->getPos()); vec3 chunkPos = Space::Chunk::world::fromBlock(playerPos); vec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos); vec3 regionPos = Space::Region::world::fromChunk(chunkPos); - + vec3 posOffsetFromChunk = Space::Block::relative::toChunk(playerPos); vec3 posOffsetFromBlock = Space::Block::relative::toMapBlock(playerPos); vec3 posOffsetFromRegion = Space::Block::relative::toRegion(playerPos); - + std::ostringstream str; - + str << "Dimension: " << world.getActiveDimension()->getIdentifier() << " [" << world.getActiveDimension()->getInd() << "]" << std::endl << std::endl - + << "Pos: " << playerPos << " (" << player->getPos() << ")" << std::endl << "Vel: " << player->getVel() << std::endl - + << "Yaw: " << player->getYaw() << ", " << "Pitch: " << player->getPitch() << std::endl << std::endl - + << "C: " << posOffsetFromChunk << " [" << chunkPos << "]" << std::endl << "M: " << posOffsetFromBlock << " [" << mapBlockPos << "]" << std::endl << "R: " << posOffsetFromRegion << " [" << regionPos << "]" << std::endl << std::endl - + << "Texture Slots: " << game.l()->textures.textureSlotsUsed << " / " << game.l()->textures.maxTextureSlots << " (" << round(game.l()->textures.textureSlotsUsed / static_cast(game.l()->textures.maxTextureSlots) * 100) << "%)" << std::endl << std::endl - + << "Biome: " << onBiomeDef.identifier << " [" << onBiomeDef.index << "]" << std::endl << std::endl; - + if (target.type == Target::Type::BLOCK) { string face = target.data.block.face == EVec::TOP ? "Top" : @@ -158,16 +158,16 @@ void DebugGui::update(sptr player, f64 delta, u32 interpolatedChunk target.data.block.face == EVec::FRONT ? "Front" : target.data.block.face == EVec::BACK ? "Back" : "None (!)"; - + const auto& def = game->getDefs().blockFromId(world.getActiveDimension()->getBlock(target.data.block.pos)); - + str << "Pointing At: " << def.identifier << " [" << def.index << "]" << std::endl << "Pointed Position: " << target.data.block.pos << std::endl << "Pointed Face: " << face << std::endl; } else if (target.type == Target::Type::ENTITY) { const auto& entity = **world.getActiveDimension().l()->getEntityById(target.data.entity.id).entity; - + str << "Pointing At: " << (target.data.entity.id < 0 ? "Local" : "Server") << " Entity #" << std::fabs(target.data.entity.id) << std::endl << "Pointed Position: " << entity.getPos() << std::endl << std::endl; @@ -175,44 +175,48 @@ void DebugGui::update(sptr player, f64 delta, u32 interpolatedChunk else { str << "No Target" << std::endl << std::endl; } - + // for (usize i = 0; i < perfTimings.size(); i++) { // str << perfSections[i] << ": " << perfTimings[i] << " ns." << std::endl; // } - + get("dataText")->setText(str.str()); - + // Chunk States - - auto chunkStates = get("chunkStates"); - ivec3 off = { 0, 0, 0 }; - for (off.x = 0; off.x < CHUNK_RANGE; off.x++) { - for (off.z = 0; off.z < CHUNK_RANGE; off.z++) { - f32 existAmount = 0; - f32 compressedAmount = 0; - ivec3 check = ivec3(chunkPos) + off - - glm::ivec3(floor(CHUNK_RANGE / 2), 0, floor(CHUNK_RANGE / 2)); - - for (off.y = 0; off.y < CHUNK_VERT; off.y++) { - check.y = static_cast(chunkPos.y) + off.y - CHUNK_VERT / 2; - const auto chunk = world.getActiveDimension()->getChunk(check); - if (chunk) { - existAmount++; - if (chunk->isCompressed()) compressedAmount++; + + if (chunkTimer == 0) { + auto chunkStates = get("chunkStates"); + ivec3 off = { 0, 0, 0 }; + for (off.x = 0; off.x < CHUNK_RANGE; off.x++) { + for (off.z = 0; off.z < CHUNK_RANGE; off.z++) { + f32 existAmount = 0; + f32 compressedAmount = 0; + ivec3 check = ivec3(chunkPos) + off - + glm::ivec3(floor(CHUNK_RANGE / 2), 0, floor(CHUNK_RANGE / 2)); + + for (off.y = 0; off.y < CHUNK_VERT; off.y++) { + check.y = static_cast(chunkPos.y) + off.y - CHUNK_VERT / 2; + const auto chunk = world.getActiveDimension()->getChunk(check); + if (chunk) { + existAmount++; + if (chunk->isCompressed()) compressedAmount++; + } } + + const auto color = glm::mix(CHUNK_UNLOADED, + glm::mix(CHUNK_UNCOMPRESSED, CHUNK_COMPRESSED, + compressedAmount / CHUNK_VERT),existAmount / CHUNK_VERT); + + chunkStates->setCellColor(u16vec2(off.x, off.z), color); } - - const auto color = glm::mix(CHUNK_UNLOADED, - glm::mix(CHUNK_UNCOMPRESSED, CHUNK_COMPRESSED, - compressedAmount / CHUNK_VERT),existAmount / CHUNK_VERT); - - chunkStates->setCellColor(u16vec2(off.x, off.z), color); } + chunkStates->refresh(); } - chunkStates->refresh(); + chunkTimer = (chunkTimer + 1) % CHUNK_INTERVAL; + // Crosshair information - + if (target.type == Target::Type::BLOCK) { const auto& def = game->getDefs().blockFromId(world.getActiveDimension()->getBlock(target.data.block.pos)); get("crosshairText")->setText(def.name + " (" + def.identifier + ") [" + std::to_string(def.index) + "]"); diff --git a/src/client/gui/DebugGui.h b/src/client/gui/DebugGui.h index 8589b10f..9a0c0c9e 100644 --- a/src/client/gui/DebugGui.h +++ b/src/client/gui/DebugGui.h @@ -17,35 +17,38 @@ class LocalSubgame; class DebugGui : public GuiContainer { public: - + enum class Visibility { OFF, FPS_ONLY, ON }; - + DebugGui(u16vec2 buffer, SubgamePtr game, LocalWorld& world, vec& perfSections); - + /** Resizes elements when the screen buffer is resized. */ void bufferResized(u16vec2 bufferSize); - + /** Sets which elements are visible based on the state provided. */ void changeVisibility(Visibility state); - + /** Positions all elements based on the buffer size. */ void positionElements(u16vec2 buffer); - + /** Updates the debug screen with the latest data. */ void update(sptr player, f64 delta, u32 interpolatedChunks, u32 generatedChunks, u32 recievedPackets, vec& perfTimings, u32 drawnMeshChunks, u32 generatedMeshChunks); - + private: - + constexpr static vec4 CHUNK_UNLOADED = { 1, 1, 1, 0.15 }; constexpr static vec4 CHUNK_COMPRESSED = { 1, 1, 1, 0.75 }; constexpr static vec4 CHUNK_UNCOMPRESSED = { 1, 0, 0, 0.75 }; - + constexpr static i32 CHUNK_VERT = 3; constexpr static i32 CHUNK_RANGE = 48; - + SubgamePtr game; LocalWorld& world; - + + u16 chunkTimer = 0; + constexpr static u16 CHUNK_INTERVAL = 5; + Visibility state = Visibility::ON; }; diff --git a/src/client/gui/GameGui.h b/src/client/gui/GameGui.h index daa46a16..e9e9918b 100644 --- a/src/client/gui/GameGui.h +++ b/src/client/gui/GameGui.h @@ -1,56 +1,52 @@ -// -// Created by aurailus on 05/02/19. -// - #pragma once #include "client/gui/GameGuiBuilder.h" #include "client/gui/compound/GuiInventoryList.h" class GameGui { - public: +public: explicit GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer); - + void winResized(glm::ivec2 win); - + void update(double delta); - + void setVisible(bool visible); - + bool isVisible(); - + void showMenu(std::shared_ptr root); - + void closeMenu(); - + const bool isInMenu() const; - + void setHud(std::shared_ptr hud); - + std::shared_ptr getHud(); - + void drawHud(Renderer& renderer); - + void drawMenu(Renderer& renderer); - - private: + +private: SubgamePtr defs; Renderer& renderer; - - glm::ivec2 win{}; + + ivec2 win {}; bool inMenu = false; - + std::shared_ptr hudRootElem = nullptr; - + std::shared_ptr menuRoot = std::make_shared("menuRoot"); std::shared_ptr menuLuaRoot = std::make_shared("menuLuaRoot"); GameGuiBuilder menuBuilder; std::shared_ptr hudRoot = std::make_shared("hudRoot"); std::shared_ptr hudLuaRoot = std::make_shared("hudLuaRoot"); GameGuiBuilder hudBuilder; - + std::shared_ptr handList = std::make_shared("hand"); - + InventoryRefsPtr refs; }; diff --git a/src/client/scene/ConnectScene.cpp b/src/client/scene/ConnectScene.cpp index 8c11e16a..c8f7db06 100644 --- a/src/client/scene/ConnectScene.cpp +++ b/src/client/scene/ConnectScene.cpp @@ -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: diff --git a/src/client/scene/GameScene.cpp b/src/client/scene/GameScene.cpp index e698cde4..bd6fc943 100644 --- a/src/client/scene/GameScene.cpp +++ b/src/client/scene/GameScene.cpp @@ -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(); diff --git a/src/client/stream/ChunkMeshDetails.h b/src/client/stream/ChunkMeshDetails.h deleted file mode 100644 index 2570adee..00000000 --- a/src/client/stream/ChunkMeshDetails.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// Created by aurailus on 23/07/19. -// - -#pragma once - -#include -#include - -#include "client/graph/mesh/ChunkVertex.h" - -struct ChunkMeshDetails { - std::vector vertices; - std::vector indices; - - glm::ivec3 pos {}; -}; diff --git a/src/client/stream/MeshChunkDetails.h b/src/client/stream/MeshChunkDetails.h new file mode 100644 index 00000000..a7604392 --- /dev/null +++ b/src/client/stream/MeshChunkDetails.h @@ -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 indices; + vec vertices; +}; diff --git a/src/client/stream/MeshGenStream.cpp b/src/client/stream/MeshGenStream.cpp index 3651077c..b96a7de2 100644 --- a/src/client/stream/MeshGenStream.cpp +++ b/src/client/stream/MeshGenStream.cpp @@ -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 MeshGenStream::update() { - std::vector finishedChunks; +std::vector MeshGenStream::update() { + std::vector finishedChunks; for (u16 i = 0; i < THREAD_QUEUE_SIZE; i++) { for (Thread& t : threads) { @@ -44,7 +44,7 @@ std::vector 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()) { diff --git a/src/client/stream/MeshGenStream.h b/src/client/stream/MeshGenStream.h index 3b508259..4f6b941e 100644 --- a/src/client/stream/MeshGenStream.h +++ b/src/client/stream/MeshGenStream.h @@ -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 update(); + std::vector update(); struct Job { std::unique_ptr thisChunk = nullptr; std::array, 6> adjacentChunks {}; - ChunkMeshDetails* meshDetails = new ChunkMeshDetails(); + MeshChunkDetails* meshDetails = new MeshChunkDetails(); bool busy = false; }; diff --git a/src/client/stream/WorldInterpolationStream.cpp b/src/client/stream/WorldInterpolationStream.cpp index da42641c..cbd96a5a 100644 --- a/src/client/stream/WorldInterpolationStream.cpp +++ b/src/client/stream/WorldInterpolationStream.cpp @@ -91,7 +91,6 @@ void WorldInterpolationStream::Thread::run() { u.chunks.reserve(64); while (!u.packet->d.atEnd()) { string data = u.packet->d.read(); -// std::cout << Util::toString(Deserializer(data).read()) << std::endl; u.chunks.emplace_back(make_shared()); u.chunks.back()->decompressFromString(data); } diff --git a/src/client/stream/WorldInterpolationStream.h b/src/client/stream/WorldInterpolationStream.h index fb4d7f90..96366dc6 100644 --- a/src/client/stream/WorldInterpolationStream.h +++ b/src/client/stream/WorldInterpolationStream.h @@ -22,52 +22,52 @@ class PacketView; class WorldInterpolationStream { public: - static const int THREADS = 4; - static const int THREAD_QUEUE_SIZE = 16; - + static const int THREADS = 1; + static const int THREAD_QUEUE_SIZE = 1; + WorldInterpolationStream(LocalSubgame& game, LocalWorld& world, unsigned int seed); - + // Queue parsing of packet `p`. void queuePacket(std::unique_ptr p); - + // Queue interpolation of Mapblock at `pos`. // bool queuePosition(glm::vec3 pos); // Returns a vector of BlockChunks that have finished processing, // and gives the threads new data to work with. std::unique_ptr>> update(); - + ~WorldInterpolationStream(); - + private: // enum class JobType { // EMPTY, // PACKET, // FARMAP // }; - + struct Job { bool locked = false; // JobType job = JobType::EMPTY; - + std::shared_ptr packet = nullptr; std::vector> chunks = {}; // std::shared_ptr mapblock = nullptr; // glm::vec3 mapBlockPos = {0, 0, 0}; }; - + struct Thread { explicit Thread(LocalSubgame& game, LocalWorld& world, unsigned int seed); - + void run(); - + bool kill = false; - + std::vector jobs = std::vector(THREAD_QUEUE_SIZE); - + std::thread thread; }; - + std::vector threads; std::queue> queuedPacketTasks; // std::unordered_set queuedInterpMap; diff --git a/src/lua/NoiseFromLua.cpp b/src/lua/NoiseFromLua.cpp index 905c94fe..7bbdcdd0 100644 --- a/src/lua/NoiseFromLua.cpp +++ b/src/lua/NoiseFromLua.cpp @@ -184,6 +184,7 @@ noise::module::Module* NoiseFromLua::parseNoise(std::vectorSetSeed(noise.get_or("seed", 0)); +// module->EnableDistance(noise.get_or("distance", false)); module->SetDisplacement(noise.get_or("displacement", 0)); module->SetFrequency(noise.get_or("frequency", 0)); @@ -233,5 +234,19 @@ noise::module::Module* NoiseFromLua::parseNoise(std::vectorSetSourceModule(0, *mod0); + module->SetXScale(noise.get_or("x_scale", 1)); + module->SetYScale(noise.get_or("y_scale", 1)); + module->SetZScale(noise.get_or("z_scale", 1)); + + modules.push_back(module); + return module; + } throw std::runtime_error("Invalid noise module specified."); } \ No newline at end of file diff --git a/src/lua/modules/Structure.cpp b/src/lua/modules/Structure.cpp index 784d3e2f..2e22561a 100644 --- a/src/lua/modules/Structure.cpp +++ b/src/lua/modules/Structure.cpp @@ -12,7 +12,7 @@ void Api::Module::Structure::bind() { sol::object Api::Module::Structure::create_structure(sol::table data) { auto origin = data.get>("origin"); -// auto probability = data.get("probability"); + auto probability = data.get("probability"); auto layout = data.get("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++) diff --git a/src/lua/modules/create_structure.h b/src/lua/modules/create_structure.h index 92017de6..d003b209 100644 --- a/src/lua/modules/create_structure.h +++ b/src/lua/modules/create_structure.h @@ -12,16 +12,16 @@ namespace Api { if (!data) throw "expected a table as the first argument."; auto origin = data->get>("origin"); - auto schematic = data->get>("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(); - unsigned int yWid = schematic->size(); - unsigned int zWid = (*schematic).get(1).size(); - unsigned int xWid = (*schematic).get(1).get(1).size(); + unsigned int yWid = layout->size(); + unsigned int zWid = (*layout).get(1).size(); + unsigned int xWid = (*layout).get(1).get(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(y).get(z).get_or(x, ""); + layout->get(y).get(z).get_or(x, ""); } } } diff --git a/src/server/Server.cpp b/src/server/Server.cpp index d5f7eb31..9c3549c5 100644 --- a/src/server/Server.cpp +++ b/src/server/Server.cpp @@ -33,7 +33,7 @@ void Server::update() { const static i64 interval_ns = static_cast((1000 / 60.f) * 1000000L); Timer loop(""); - world->update(delta); + world.s()->update(delta); game.s()->update(delta); // Read incoming events. diff --git a/src/server/Server.h b/src/server/Server.h index ca7cbc96..e9bcc75f 100644 --- a/src/server/Server.h +++ b/src/server/Server.h @@ -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: diff --git a/src/server/ServerClients.cpp b/src/server/ServerClients.cpp index e08ad931..d426cde1 100644 --- a/src/server/ServerClients.cpp +++ b/src/server/ServerClients.cpp @@ -36,7 +36,7 @@ void ServerClients::createPlayer(sptr client, DimensionPtr dimensi client->player = make_shared(*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(client->player->getId())) diff --git a/src/server/stream/ServerPacketStream.cpp b/src/server/stream/ServerPacketStream.cpp index 6d6a4707..7c1f4575 100644 --- a/src/server/stream/ServerPacketStream.cpp +++ b/src/server/stream/ServerPacketStream.cpp @@ -44,8 +44,11 @@ std::unique_ptr>> 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); 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++) { diff --git a/src/util/Types.h b/src/util/Types.h index 420b13fc..0ac13b6f 100644 --- a/src/util/Types.h +++ b/src/util/Types.h @@ -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; template using uptr = std::unique_ptr; -using std::make_shared, std::make_unique; +using std::make_shared; +using std::make_unique; -#pragma clang diagnostic pop \ No newline at end of file +#pragma clang diagnostic pop diff --git a/src/util/Util.h b/src/util/Util.h index 7bd43943..8d071f28 100644 --- a/src/util/Util.h +++ b/src/util/Util.h @@ -4,14 +4,10 @@ #pragma once -#include #include #include #include -#include -#include -#include -#include +#include #include "util/Log.h" #include "util/Types.h" @@ -23,7 +19,7 @@ namespace Util { return static_cast(t); } }; - + template , bool> = true> inline static string toFixed(T val, u8 precision = 2) { std::ostringstream out; @@ -31,17 +27,17 @@ namespace Util { out << std::fixed << val; return out.str(); } - + template , bool> = true> static string toString(T val) { return std::to_string(val); } - + template , bool> = true> static string toString(T val) { return toFixed(val); } - + template && std::is_same_v, V>, bool> = true> static string toString(V vec) { @@ -51,7 +47,7 @@ namespace Util { out << " ]"; return out.str(); } - + template && std::is_same_v, A>, bool> = true> static string toString(A arr) { @@ -59,7 +55,7 @@ namespace Util { for (usize i = 0; i < arr.size(); i++) out << (i == 0 ? "" : ", ") << arr[i]; return out.str(); } - + template && std::is_integral_v, bool> = true> static string toString(T vec) { @@ -67,7 +63,7 @@ namespace Util { for (usize i = 0; i < T::length(); i++) out << (i == 0 ? "" : ", ") << vec[i]; return out.str(); } - + template && std::is_integral_v, bool> = true> static string toString(T vec) { @@ -75,16 +71,16 @@ namespace Util { for (usize i = 0; i < T::length(); i++) out << (i == 0 ? "" : ", ") << toString(vec[i]); return out.str(); } - + inline static f32 packFloat(const vec3& vec) { auto charX = static_cast((vec.x + 1.0f) * 0.5f * 255.f); auto charY = static_cast((vec.y + 1.0f) * 0.5f * 255.f); auto charZ = static_cast((vec.z + 1.0f) * 0.5f * 255.f); - + u32 packedInt = (charX << 16) | (charY << 8) | charZ; return static_cast(static_cast(packedInt) / static_cast(1 << 24)); } - + inline static u32 intFromHexSegment(const string& t) { u32 x; std::stringstream ss; @@ -92,15 +88,15 @@ namespace Util { ss >> x; return x; } - + static vec4 hexToColorVec(string hex) { - vec4 color{}; - + vec4 color {}; + if (hex[0] == '#') hex.erase(0, 1); else std::cout << Log::err << "Color string does not begin with hash!" << Log::endl; - + string r, g, b, a; - + if (hex.length() == 3 || hex.length() == 4) { r = hex.substr(0, 1); r += r; @@ -121,19 +117,19 @@ namespace Util { std::cout << Log::err << "Color string \"" + hex + "\" is of incorrect length!" << Log::endl; return color; } - + color.r = intFromHexSegment(r) / 255.f; color.g = intFromHexSegment(g) / 255.f; color.b = intFromHexSegment(b) / 255.f; color.a = intFromHexSegment(a) / 255.f; - + return color; } - + static string getKeyStr(u16 key) { switch (key) { default: return ""; - + case 0: return "mouse0"; case 1: return "mouse1"; case 2: return "mouse2"; @@ -146,7 +142,7 @@ namespace Util { case 9: return "scrolldown"; case 10: return "scrollleft"; case 11: return "scrollright"; - + case 32: return "space"; case 39: return "'"; case 44: return ","; @@ -267,22 +263,22 @@ namespace Util { case 348: return "menu"; } } - + namespace { constexpr static u64 mix(char m, u64 s) { return ((s << 7) + ~(s >> 3)) + ~m; } } - + constexpr static u64 hash(const char* m) { return (*m) ? mix(*m, hash(m + 1)) : 0; } - + template std::function bind_this(C* c, Ret (C::*m)(Ts...)) { return [=](auto&& ... args) { return (c->*m)(std::forward(args)...); }; } - + template std::function bind_this(const C* c, Ret (C::*m)(Ts...) const) { return [=](auto&& ... args) { return (c->*m)(std::forward(args)...); }; @@ -293,4 +289,4 @@ template || (std::is_trivial_v && std::is_integral_v), bool> = true> std::ostream& operator<<(std::ostream& out, const T& t) { return out << Util::toString(t); -} \ No newline at end of file +} diff --git a/src/util/net/NetHandler.cpp b/src/util/net/NetHandler.cpp index 04f2c809..58cb446c 100644 --- a/src/util/net/NetHandler.cpp +++ b/src/util/net/NetHandler.cpp @@ -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; } } diff --git a/src/world/LocalWorld.cpp b/src/world/LocalWorld.cpp index 085196d2..ccad1036 100644 --- a/src/world/LocalWorld.cpp +++ b/src/world/LocalWorld.cpp @@ -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(game, net)), debugGui(renderer.window.getSize(), game, *this, perfSections), - refs(std::make_shared(game, net)), - worldGenStream(std::make_shared(*game.l(), *this, 55)), - player(std::make_shared(game, *this, DimensionPtr(nullptr), renderer)) {} + worldGenStream(make_shared(*game.l(), *this, 55)), + player(make_shared(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& perfTimings, PerfTimer& perf) { +void LocalWorld::update(f64 delta, vec& 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& 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& 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& perfTimings, PerfTimer& perf) } } -void LocalWorld::handleWorldPacket(std::unique_ptr p) { +void LocalWorld::handleWorldPacket(uptr p) { worldGenStream->queuePacket(std::move(p)); } -void LocalWorld::handlePlayerEntPacket(std::unique_ptr p) { +void LocalWorld::handlePlayerEntPacket(uptr p) { if (!player) throw std::runtime_error("Received playerEnt info *before* the player was created."); u32 id = p->d.read(); @@ -107,25 +103,26 @@ void LocalWorld::handlePlayerEntPacket(std::unique_ptr p) { // getActiveDimension().playerEntities.emplace_back(p->d.read(), 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 c) { +void LocalWorld::commitChunk(sptr c) { activeDimension->setChunk(std::move(c)); } -DimensionPtr LocalWorld::createDimension(const std::string& identifier, std::unordered_set& biomes) { +DimensionPtr LocalWorld::createDimension(const string& identifier, std::unordered_set& biomes) { auto mapGen = std::make_shared(**game, *this, 0 /* TODO: Get the seed here */, biomes); dimensions.emplace_back(std::make_shared( 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); } diff --git a/src/world/LocalWorld.h b/src/world/LocalWorld.h index 100f967e..4a7f149b 100644 --- a/src/world/LocalWorld.h +++ b/src/world/LocalWorld.h @@ -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& 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& 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& perfTimings, PerfTimer& perf); - void handleWorldPacket(std::unique_ptr p); + /** Queues a packet to be read. */ + void handleWorldPacket(uptr p); - void handlePlayerEntPacket(std::unique_ptr p); + /** Reads a player entity packet, and updates the required entity. */ + void handlePlayerEntPacket(uptr 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); + /** Sets a chunk in the current dimension. */ + void commitChunk(sptr 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& biomes) override; + /** Creates a new dimension with the identifier and biomes provided. */ + virtual DimensionPtr createDimension(const string& identifier, std::unordered_set& 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 refs; + + /** The local inventories. */ + sptr 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 activeDimension = nullptr; - std::shared_ptr worldGenStream = nullptr; + /** A pointer to the active dimension. */ + sptr activeDimension = nullptr; + + /** A reference to the world gen stream. */ + sptr worldGenStream; }; diff --git a/src/world/ServerWorld.cpp b/src/world/ServerWorld.cpp index f7bc3a79..f285bcd0 100644 --- a/src/world/ServerWorld.cpp +++ b/src/world/ServerWorld.cpp @@ -1,10 +1,7 @@ -// -// Created by aurailus on 05/03/19. -// - #include #include #include +#include #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(game, clients)) { + refs(make_shared(game, clients)) { clients.init(this); generateOrder.reserve(mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.y * 2 + 1); - std::unordered_set found {}; - std::queue queue {}; + std::unordered_set found {}; + std::queue queue {}; queue.emplace(0, 0, 0); found.emplace(0, 0, 0); - const std::vector 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(*game.s(), *this); - packetStream = std::make_unique(*this); +void ServerWorld::init(const string& worldDir) { + genStream = make_unique(*game.s(), *this); +// packetStream = make_unique(*this); // fileManip = std::make_shared("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 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(chunkPair.second)); + dim->setChunk(sptr(chunkPair.second)); } - // Mapblock might have been pruned in between generation assignment and now. - auto mb = getDimension(data.dim)->getMapBlock(glm::ivec3(data.pos)); - if (mb) mb->generated = true; + auto mapBlock = dim->getMapBlock(ivec3(data.pos)); - packetStream->queue(data.dim, data.pos); - genCount++; + if (!mapBlock->generated) { + mapBlock->generated = true; + assert(mapBlock); + + Serializer s {}; + for (u16 i = 0; i < 64; i++) { + auto chunk = mapBlock->get(i); + assert(chunk); + if (chunk) s.append(chunk->compressToString()); + } + + let packet = s.packet(Packet::Type::MAPBLOCK); + + for (auto& client : clients.getClients()) { + if (!client.second->player) continue; + packet.sendTo(client.second->peer, Packet::Channel::WORLD); + } + + genCount++; + totalGens++; + } + } + if (!finishedGen->empty()) { + t.printElapsedMs(); + std::cout << totalGens << std::endl; } - auto finishedPackets = packetStream->update(); +// auto finishedPackets = packetStream->update(); // if (finishedPackets->size()) std::cout << finishedPackets->size() << " finished packets" << std::endl; - for (auto& data : *finishedPackets) { - for (auto& client : clients.getClients()) { - if (!client.second->player) continue; - data->packet->sendTo(client.second->peer, Packet::Channel::WORLD); - } - } +// for (auto& data : *finishedPackets) { +// for (auto& client : clients.getClients()) { +// if (!client.second->player) continue; +// data->packet->sendTo(client.second->peer, Packet::Channel::WORLD); +// } +// } generatedMapBlocks = genCount; @@ -178,25 +194,16 @@ void ServerWorld::update(double delta) { } } -DimensionPtr ServerWorld::createDimension(const std::string& identifier, std::unordered_set& biomes) { - auto mapGen = std::make_shared(**game, *this, seed, biomes); - dimensions.emplace_back(std::make_shared( - game, *this, identifier, this->dimensions.size(), std::move(mapGen))); +DimensionPtr ServerWorld::createDimension(const string& identifier, std::unordered_set& biomes) { + dimensions.emplace_back(make_shared( + game, *this, identifier, this->dimensions.size(), + make_shared(**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::Type::MAPBLOCK); +// +// for (auto& client : clients.getClients()) { +// if (!client.second->player) continue; +// packet->sendTo(client.second->peer, Packet::Channel::WORLD); +// } } } diff --git a/src/world/ServerWorld.h b/src/world/ServerWorld.h index 30f0ffb5..70a3f83d 100644 --- a/src/world/ServerWorld.h +++ b/src/world/ServerWorld.h @@ -1,9 +1,3 @@ -// -// World subclass for the server. -// Handles blocks, entities, and clients. -// Created by aurailus on 05/03/19. -// - #pragma once #include "world/World.h" @@ -19,51 +13,77 @@ class ServerGenStream; class ServerInventoryRefs; class ServerPacketStream; +/** + * Manages server dimensions and players. + * Handles sending chunk and entity data to clients. + */ + class ServerWorld : public World { public: - explicit ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clients); - void init(const std::string& worldDir); + explicit ServerWorld(u32 seed, SubgamePtr game, ServerClients& clients); - void update(double delta) override; + /** Initializes the map and packet thread pools. */ + void init(const string& worldDir); - virtual void sendMessage(const std::string& channel, const std::string& message) override; + /** Updates dimensions, and sends new or dirty chunks to clients. */ + void update(double delta); + + /** Sends a mod message to the channel provided. */ + virtual void sendMessage(const string& channel, const string& message) override; - virtual DimensionPtr - createDimension(const std::string& identifier, std::unordered_set& biomes) override; - - virtual DimensionPtr getDimension(unsigned int index) override; - - virtual DimensionPtr getDimension(const std::string& identifier) override; + /** Creates a new dimension with the identifier and biomes provided. */ + virtual DimensionPtr createDimension(const string& identifier, std::unordered_set& 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 genStream = nullptr; - std::shared_ptr packetStream = nullptr; - + /** Generates new chunks. */ + sptr genStream = nullptr; + + /** The seed for generating the world. */ u32 seed; + + /** A reference to the client list. */ ServerClients& clients; - std::shared_ptr refs; + + /** The server inventories. */ + sptr refs; // std::string worldDir; // std::shared_ptr fileManip; - u32 generatedMapBlocks = 0; - std::vector generateOrder; - - const ivec2 mapBlockGenRange = { 4, 4 }; - const ivec2 sendRange = { 4, 4 }; - const ivec2 activeChunkRange = { 16, 16 }; -}; + usize totalGens = 0; + /** The amount of mapblocks that were generated last frame. */ + u32 generatedMapBlocks = 0; + + /** A vector of positions for the order to generate mapblocks in. */ + vec generateOrder; + + /** The range in mapblocks to generate around clients. */ + const ivec2 mapBlockGenRange = { 4, 4 }; + + /** The range in mapblocks to send to clients. */ + const ivec2 sendRange = { 4, 4 }; + + /** The range around clients that chunks should be updated. */ + const ivec2 activeChunkRange = { 4, 4 }; +}; diff --git a/src/world/World.cpp b/src/world/World.cpp index 1b7a3c45..699c67be 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -1,33 +1,29 @@ -// -// Created by aurailus on 2020-01-09. -// - -#include - #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]]; +} \ No newline at end of file diff --git a/src/world/World.h b/src/world/World.h index b63adcb1..6681375d 100644 --- a/src/world/World.h +++ b/src/world/World.h @@ -1,45 +1,59 @@ -// -// Created by aurailus on 2020-01-09. -// - #pragma once -#include -#include #include #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& biomes) = 0; + /** Creates a new dimension with the identifier and biomes provided. */ + virtual DimensionPtr createDimension(const string& identifier, std::unordered_set& 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> dimensions; + /** The identifier of the default dimension. */ + string defaultDimension {}; + + /** A vector of dimensions in the world. */ + vec> dimensions; + + /** A map of dimension identifiers to indexes. */ + std::unordered_map dimensionIndexes; + + /** A reference to the subgame. */ SubgamePtr game; }; diff --git a/src/world/dim/Dimension.cpp b/src/world/dim/Dimension.cpp index 7abeae5e..3c86745e 100644 --- a/src/world/dim/Dimension.cpp +++ b/src/world/dim/Dimension.cpp @@ -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); diff --git a/src/world/dim/LocalDimension.cpp b/src/world/dim/LocalDimension.cpp index 47ec5d3e..3c64d45e 100644 --- a/src/world/dim/LocalDimension.cpp +++ b/src/world/dim/LocalDimension.cpp @@ -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(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(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) { +void LocalDimension::setChunk(sptr 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 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 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> res = game->getParser().safe_function( + std::tuple, sol::optional> 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) { +void LocalDimension::setMeshChunk(sptr meshChunk) { if (renderRefs.count(meshChunk->getPos())) removeMeshChunk(meshChunk->getPos()); renderElems.push_back(std::static_pointer_cast(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(); while (!d.atEnd()) { i64 id = d.read(); @@ -350,13 +354,13 @@ u32 LocalDimension::getMeshChunksCommitted() { std::unordered_set LocalDimension::propogateAddNodes() { auto updated = Dimension::propogateAddNodes(); - for (auto& update : updated) attemptMeshChunk(getChunk(update)); + for (auto& update : updated) meshChunk(getChunk(update)); return {}; } std::unordered_set 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->create(meshDetails->vertices, meshDetails->indices); - meshChunk->setPos(meshDetails->pos); - - setMeshChunk(meshChunk); + for (MeshChunkDetails* details : finishedMeshes) { + if (!details->vertices.empty()) { + setMeshChunk(make_shared(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, 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, 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; } \ No newline at end of file diff --git a/src/world/dim/LocalDimension.h b/src/world/dim/LocalDimension.h index c08af9ba..e3e05edb 100644 --- a/src/world/dim/LocalDimension.h +++ b/src/world/dim/LocalDimension.h @@ -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); 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) 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 getEntitiesInRadius(vec3 pos, f32 radius); @@ -84,9 +84,11 @@ private: void finishMeshes(); - void attemptMeshChunk(const sptr& 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, 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; @@ -96,6 +98,7 @@ private: std::unordered_map renderRefs{}; std::list> renderElems{}; + const ivec2 retainMapBlockRange = { 4, 4 }; i64 entityInd = -1; }; diff --git a/src/world/dim/ServerDimension.cpp b/src/world/dim/ServerDimension.cpp index 04985e76..17290c2c 100644 --- a/src/world/dim/ServerDimension.cpp +++ b/src/world/dim/ServerDimension.cpp @@ -22,36 +22,49 @@ ServerDimension::ServerDimension(SubgamePtr game, ServerWorld& world, const std: Dimension(game, static_cast(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(world).getClients().getClients()) { - if (!client.second->player) continue; - if (client.second->player->getDim()->getInd() == ind) { - auto clientPos = Space::MapBlock::world::fromBlock(client.second->player->getPos()); - if (abs(clientPos.x - mapBlock->pos.x) <= discardRange.x + 1 - && abs(clientPos.y - mapBlock->pos.y) <= discardRange.y + 1 - && abs(clientPos.z - mapBlock->pos.z) <= discardRange.x + 1) { - clientNearby = true; - break; - } - } + if (!client.second->player || client.second->player->getDim()->getInd() != ind) continue; + auto clientMapBlock = Space::MapBlock::world::fromBlock(client.second->player->getPos()); + if (abs(clientMapBlock.x - mapBlock->pos.x) <= retainMapBlockRange.x && + abs(clientMapBlock.y - mapBlock->pos.y) <= retainMapBlockRange.y && + abs(clientMapBlock.z - mapBlock->pos.z) <= retainMapBlockRange.x) { + clientNearby = true; + break; + } } - if (!clientNearby) region.second->remove(i); + if (!clientNearby) { + it->second->remove(m); + if (it->second->count <= 0) goto erase_region_and_continue; + } else { - for (unsigned short c = 0; c < 64; c++) { - auto chunk = mapBlock->get(c); - if (!chunk) continue; - chunk->compressIfIdle(); + for (u16 c = 0; c < 64; c++) { + let chunk = mapBlock->get(c); + if (chunk) chunk->compressIfIdle(); } } } + + it++; + continue; + + erase_region_and_continue: + it = regions.erase(it); } } @@ -103,8 +116,8 @@ void ServerDimension::wieldItemUse(const Target& target, PlayerPtr player) { } void ServerDimension::setChunk(std::shared_ptr chunk) { -// std::shared_ptr existing = getChunk(chunk->getPos()); -// if (existing) chunk = combineChunks(chunk, existing); + std::shared_ptr existing = getChunk(chunk->getPos()); + if (existing) chunk = combineChunks(chunk, existing); Dimension::setChunk(chunk); } diff --git a/src/world/dim/ServerDimension.h b/src/world/dim/ServerDimension.h index a4b2573b..9dd7af0e 100644 --- a/src/world/dim/ServerDimension.h +++ b/src/world/dim/ServerDimension.h @@ -53,7 +53,7 @@ private: std::list luaEntities{}; std::list removedEntities{}; - const ivec2 discardRange = { 20, 20 }; + const ivec2 retainMapBlockRange = { 4, 4 }; i64 entityInd = 1; }; diff --git a/src/world/dim/chunk/Chunk.cpp b/src/world/dim/chunk/Chunk.cpp index 1cf6b5a2..82afa895 100644 --- a/src/world/dim/chunk/Chunk.cpp +++ b/src/world/dim/chunk/Chunk.cpp @@ -52,8 +52,11 @@ const array& Chunk::getBiomesArray() { } void Chunk::combineWith(sptr 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; diff --git a/src/world/gen/MapGen.cpp b/src/world/gen/MapGen.cpp index 5baa58d8..c90d9e0f 100644 --- a/src/world/gen/MapGen.cpp +++ b/src/world/gen/MapGen.cpp @@ -1,7 +1,9 @@ #include +#include #include "MapGen.h" +#include "util/Types.h" #include "world/World.h" #include "game/Subgame.h" #include "util/Structure.h" @@ -14,7 +16,7 @@ MapGen::MapGen(Subgame& game, World& world, u32 seed, std::unordered_set biomes) : game(game), world(world), props(seed) { - + std::unordered_set biomeIndices {}; for (const auto& str : biomes) { if (str[0] == '#') @@ -22,7 +24,7 @@ MapGen::MapGen(Subgame& game, World& world, u32 seed, std::unordered_set biomeIndices.insert(biome->index); else biomeIndices.insert(game.getBiomes().biomeFromStr(str).index); } - + generateVoronoi(biomeIndices); } @@ -95,12 +97,16 @@ std::unique_ptr MapGen::generateArea(u16 dim, ivec3 origin, u1 uptr depth = populateChunkDepth(density, std::move(densityAbove)); generateChunkBlocks(job, pos, biomeMap, *depth); -// generateChunkDecorAndLight(job, pos, biomeMap, *depth); + generateChunkDecorAndLight(job, pos, biomeMap, *depth); densityAbove = std::move(density); } } } + + for (let& chunk : *job.chunks) { + chunk.second->compress(); + } return std::move(job.chunks); } @@ -109,7 +115,7 @@ void MapGen::generateVoronoi(const std::unordered_set& biomes) { vec> points {}; for (auto biomeInd : biomes) { auto& biome = game.getBiomes().biomeFromId(biomeInd); - + points.emplace_back(vec3 { static_cast(std::fmin(voronoiSize - 1, std::fmax(0, (biome.temperature + 1) / 2 * voronoiSize))), @@ -117,7 +123,7 @@ void MapGen::generateVoronoi(const std::unordered_set& biomes) { static_cast(std::fmin(voronoiSize - 1, std::fmax(0, biome.roughness * voronoiSize))) }, biomeInd); } - + voronoi.setPoints(points); } @@ -130,20 +136,20 @@ u16 MapGen::getBiomeAt(f32 temperature, f32 humidity, f32 roughness) { uptr MapGen::populateChunkDensity(MapGen::Job& job, ivec3 localPos) { auto data = make_unique(); - + for (u16 i = 0; i < 4096; i++) { ivec3 indPos = Space::Block::fromIndex(i); vec3 queryPos = (vec3(localPos) + vec3(indPos) / 16.f) / static_cast(job.size); (*data)[i] = (job.volume.get(queryPos) + job.heightmap.get({ queryPos.x, 0, queryPos.z })) - ((job.pos.y + localPos.y) * 16 + indPos.y); } - + return data; } uptr MapGen::populateChunkDepth(uptr& chunkDensity, uptr chunkDensityAbove) { auto data = make_unique(); - + for (u16 i = 0; i < 256; i++) { ivec2 pos = { i / 16, i % 16 }; short depth = 16; @@ -166,27 +172,27 @@ uptr MapGen::populateChunkDepth(uptr& chunkDensity (*data)[ind] = depth; } } - + return data; } void MapGen::generateChunkBlocks(Job& job, ivec3 localPos, vec biomeMap, ChunkData& depthMap) { ivec3 chunkPos = job.pos + localPos; - + auto partial = (job.chunks->count(chunkPos) ? job.chunks->at(chunkPos) : nullptr); if (partial) job.chunks->erase(chunkPos); - + auto& chunk = *(*job.chunks->emplace(chunkPos, new Chunk(chunkPos)).first).second; - + u16 partialBlock = DefinitionAtlas::INVALID; - + for (u16 i = 0; i < 4096; i++) { ivec3 indPos = Space::Block::fromIndex(i); - + u16 biomeId = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)]; auto& biome = game.getBiomes().biomeFromId(biomeId); chunk.d->biomes[i] = biomeId; - + f32 depth = depthMap[i]; u16 blockId = partialBlock > DefinitionAtlas::INVALID ? partialBlock @@ -194,49 +200,49 @@ void MapGen::generateChunkBlocks(Job& job, ivec3 localPos, vec biomeMap, Ch : depth <= 2 ? biome.topBlock : depth <= 4 ? biome.soilBlock : biome.rockBlock; - + if (chunk.d == nullptr) std::cout << "THE DATA ISNT LOADED." << std::endl; chunk.d->blocks[i] = blockId; - + } - + chunk.countRenderableBlocks(); } void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec biomeMap, ChunkData& depthMap) { - + vec3 posFloat = job.pos + localPos; std::default_random_engine generator(posFloat.x + posFloat.y * M_PI + posFloat.z * (M_PI * 2)); std::uniform_real_distribution distribution(0, 1); - + auto& chunk = job.chunks->at(job.pos + localPos); - + ivec3 abovePos = job.pos + localPos + ivec3 { 0, 1, 0 }; Chunk* above = (localPos.y != job.size - 1) ? job.chunks->count(abovePos) ? job.chunks->at(abovePos) : nullptr : nullptr; - + for (u16 i = 0; i < 256; i++) { ivec3 indPos = { i / 16, 15, i % 16 }; - + u16 biomeID = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)]; auto& biome = game.getBiomes().biomeFromId(biomeID); - - u16 schemID = -1; + + i16 schemID = -1; for (u16 j = 0; j < biome.schematics.size(); j++) { if (distribution(generator) > 1 - biome.schematics[j]->probability) { schemID = j; break; } } - + i8 light = -1; - - for (; indPos.y >= 0 && (light || schemID > -1); indPos.y--) { + + for (; indPos.y >= 0 && (light > -1 || schemID > -1); indPos.y--) { u16 ind = Space::Block::index(indPos); - - if (schemID > UINT16_MAX && depthMap[ind] > 1 && depthMap[ind] <= 2) { + + if (schemID > -1 && depthMap[ind] > 1 && depthMap[ind] <= 2) { ivec3 pos = (job.pos + localPos) * 16 + indPos; pos.y++; // Compensate for the fact that we're finding solid positions. auto& schematic = biome.schematics[schemID]; @@ -246,28 +252,28 @@ void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec biome } break; } - - if (light == -1) light = above ? above->getLight(Space::Block::index(indPos), 3) : - game.getDefs().blockFromId(chunk->getBlock(indPos)).lightPropagates ? 15 : 0; - - if (!light) continue; - - auto& blockDef = game.getDefs().blockFromId(chunk->getBlock(indPos)); - if (!blockDef.lightPropagates) light = 0; - else { - chunk->setLight(ind, 3, light); - job.sunlightQueue.emplace(ind, chunk); - } + + // if (light == -1) light = above ? above->getLight(Space::Block::index(indPos), 3) : + // game.getDefs().blockFromId(chunk->getBlock(indPos)).lightPropagates ? 15 : 0; + + // if (!light) continue; + + // auto& blockDef = game.getDefs().blockFromId(chunk->getBlock(indPos)); + // if (!blockDef.lightPropagates) light = 0; + // else { + // chunk->setLight(ind, 3, light); + // job.sunlightQueue.emplace(ind, chunk); + // } } } - + chunk->generationState = Chunk::GenerationState::GENERATED; } void MapGen::setBlock(MapGen::Job& job, ivec3 worldPos, u16 block, Chunk* hint) { if (block == DefinitionAtlas::INVALID) return; u16 ind = Space::Block::index(worldPos); - + if (hint && Space::Chunk::world::fromBlock(worldPos) == hint->getPos()) { if (hint->getBlock(ind) <= DefinitionAtlas::AIR) hint->setBlock(ind, block); } diff --git a/src/world/gen/MapGen.h b/src/world/gen/MapGen.h index 2581d586..54a6fc3a 100644 --- a/src/world/gen/MapGen.h +++ b/src/world/gen/MapGen.h @@ -27,56 +27,56 @@ class MapGen { public: /** The precision of the Biome map, as a divisor of the chunk size. */ constexpr static u8 BIOP = 4; - + /** The precision of the Terrain maps, as a divisor of the chunk size. */ constexpr static u8 TERP = 4; - + /** A type alias for the type the map of Chunks stored in the Job. */ typedef std::unordered_map ChunkMap; - + /** * A struct representing a single position in a chunk at which sunlight should be updated at. */ - + struct SunlightNode { SunlightNode(u16 index, Chunk* chunk) : index(index), chunk(chunk) {}; - + u16 index; Chunk* chunk; }; - + /** * A struct containing all the information for a generation job. * Contains a list of chunks, Noise samples, and the world position of the the job's root. */ - + struct Job { - + /** * Creates a new job with the root position and size specified, and initializes the NoiseSample params. * @param pos - The root position of the job. * @param size - The size in chunks of the job. */ - + Job(ivec3 pos, u16 size) : pos(pos), size(size), volume {{ size * TERP, (size + 1) * TERP }, { 1, 1.25 }}, heightmap {{ size * TERP, 0 }}, temperature {{ size * BIOP, 0 }}, roughness {{ size * BIOP, 0 }}, humidity {{ size * BIOP, 0 }} {} - + ivec3 pos {}; u16 size {}; - + uptr chunks = make_unique(); std::queue sunlightQueue {}; - + NoiseSample volume, heightmap; NoiseSample temperature, humidity, roughness; }; - + typedef array ChunkData; - + MapGen(const MapGen& o) = delete; - + /** * Create a MapGen object with the seed and biomes provided. * @@ -85,9 +85,9 @@ public: * @param seed - A seed to base the generation off of. * @param biomes - A list of biome identifiers or tags to include in generation. */ - + MapGen(Subgame& game, World& world, u32 seed, std::unordered_set biomes); - + /** * Generate a single chunk at the dimension and position provided. * As with all generate* functions, this may result in extraneous chunk partials being created. @@ -97,9 +97,9 @@ public: * @param pos - The position in the dimension to generate the chunk. * @returns a set of positions that were generated by this function call. */ - + [[maybe_unused]] uptr generateChunk(u16 dim, ivec3 pos); - + /** * Generate a mapblock at the dimension and position provided. * As with all generate* functions, this may result in extraneous chunk partials being created. @@ -109,9 +109,9 @@ public: * @param pos - The position in the dimension to generate the chunk. * @returns a set of positions that were generated by this function call. */ - + uptr generateMapBlock(u16 dim, ivec3 pos); - + /** * The underlying generate function called by both generateMapBlock and generateChunk. * Can also be called on it's own to generate an arbitrary region of chunks. @@ -121,11 +121,11 @@ public: * @param pos - The position in the dimension to generate the chunk. * @return - A set of positions that were generated by this function call. */ - + uptr generateArea(u16 dim, ivec3 origin, u16 size = 1); private: - + /** * Get the closest biome to the provided environmental values from the Vonoroi map. * Returns the index of the matched biome. @@ -135,18 +135,18 @@ private: * @param roughness - The roughness value of the position to check. * @returns the biome index of the environmentally closest biome. */ - + u16 getBiomeAt(f32 temperature, f32 humidity, f32 roughness); - + /** * Generate the Vonoroi biome map, using the biomes listed, * according to their definition parameters. * * @param biomes - The biomes to add to the map. */ - + void generateVoronoi(const std::unordered_set& biomes); - + /** * Create a density array for a chunk using a generation Job and an offset within it. * Returns a flattened array of block densities for every point in the chunk. @@ -155,9 +155,9 @@ private: * @param localPos - The offset of the chunk's data within the job. * @returns a ChunkData array containing the chunk's density. */ - + static uptr populateChunkDensity(Job& job, ivec3 localPos); - + /** * Create a depth array for a chunk using a generation Job and the chunk densities around it. * Returns a flattened array of block depths for every point in the chunk. @@ -166,9 +166,9 @@ private: * @param chunkDensityAbove - A density array of the chunk above it. * @returns a ChunkData array containing the chunk's depth. */ - + static uptr populateChunkDepth(uptr& chunkDensity, uptr chunkDensityAbove); - + /** * Generates a chunk's blocks from a generation Job and an offset within it, and inserts it into the Job. * Combines with any partials that have been previously created at that position within job. @@ -181,9 +181,9 @@ private: * @param biomeMap - The two-dimensional biome array of the entire generation area. * @param depthMap - The depth map of the chunk being generated. */ - + void generateChunkBlocks(Job& job, ivec3 localPos, vec biomeMap, ChunkData& depthMap); - + /** * Generates structures for a Chunk based on data within the generation job and an offset within it. * Also generates initial light cascade, which will later be refined by propogateSunlightNodes. @@ -194,9 +194,9 @@ private: * @param biomeMap - The two-dimensional biome array of the entire generation area. * @param depthMap - The depth map of the chunk being generated. */ - + void generateChunkDecorAndLight(Job& job, ivec3 localPos, vec biomeMap, ChunkData& depthMap); - + /** * Sets a block at the position specified into the Job, if the block at said position is not filled by * a material greater than air. If a chunk does not exist at the specified position, a partial is generated @@ -207,23 +207,23 @@ private: * @param block - The block to set. * @param hint - An optional parameter that may speed up the function if set to the chunk to set to. */ - + static void setBlock(Job& job, ivec3 worldPos, u16 block, Chunk* hint); - + /** * Calculates and smooths sunlight for an entire Job's chunks. * * @param job - The job to act upon. */ - + void propogateSunlightNodes(Job& job); - + u32 seed = 0; MapGenProps props; - + constexpr const static u16 voronoiSize = 64; Voronoi3D voronoi { voronoiSize }; - + Subgame& game; World& world; -}; \ No newline at end of file +}; diff --git a/src/world/player/Player.h b/src/world/player/Player.h index 51209eef..dadcf041 100644 --- a/src/world/player/Player.h +++ b/src/world/player/Player.h @@ -70,7 +70,7 @@ protected: vec3 lookOffset{}; - bool flying = false; + bool flying = true; string handList = ""; string wieldList = ""; diff --git a/src/world/player/ServerPlayer.h b/src/world/player/ServerPlayer.h index 98487951..126081e1 100644 --- a/src/world/player/ServerPlayer.h +++ b/src/world/player/ServerPlayer.h @@ -35,7 +35,7 @@ public: ENetPeer* getPeer(); - bool changedMapBlocks = false; + bool changedMapBlocks = true; vec3 lastPos = vec3(INFINITY); private: diff --git a/subgames/minimal/mods/zeus_inventory/script/menu.lua b/subgames/minimal/mods/zeus_inventory/script/menu.lua index 5233167f..ba6e38a9 100644 --- a/subgames/minimal/mods/zeus_inventory/script/menu.lua +++ b/subgames/minimal/mods/zeus_inventory/script/menu.lua @@ -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 }) \ No newline at end of file diff --git a/subgames/minimal/mods/zeus_world/script/biomes/forest.lua b/subgames/minimal/mods/zeus_world/script/biomes/forest.lua index 77a6e3a7..1433501f 100644 --- a/subgames/minimal/mods/zeus_world/script/biomes/forest.lua +++ b/subgames/minimal/mods/zeus_world/script/biomes/forest.lua @@ -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, diff --git a/subgames/minimal/mods/zeus_world/script/biomes/highlands.lua b/subgames/minimal/mods/zeus_world/script/biomes/highlands.lua index c044f014..062df8ef 100644 --- a/subgames/minimal/mods/zeus_world/script/biomes/highlands.lua +++ b/subgames/minimal/mods/zeus_world/script/biomes/highlands.lua @@ -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"}} } }) diff --git a/subgames/minimal/mods/zeus_world/script/biomes/plains.lua b/subgames/minimal/mods/zeus_world/script/biomes/plains.lua index b95f176b..08f9d5e9 100644 --- a/subgames/minimal/mods/zeus_world/script/biomes/plains.lua +++ b/subgames/minimal/mods/zeus_world/script/biomes/plains.lua @@ -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 diff --git a/subgames/parentheses/menu/script/faafafafa.lua b/subgames/parentheses/menu/script/init.lua similarity index 100% rename from subgames/parentheses/menu/script/faafafafa.lua rename to subgames/parentheses/menu/script/init.lua diff --git a/subgames/zeus/mods/zeus_default/models/wip/workbench.blend b/subgames/zeus/mods/zeus_default/models/wip/workbench.blend new file mode 100644 index 00000000..6144b581 Binary files /dev/null and b/subgames/zeus/mods/zeus_default/models/wip/workbench.blend differ diff --git a/subgames/zeus/mods/zeus_default/textures/podzol.png b/subgames/zeus/mods/zeus_default/textures/podzol.png new file mode 100755 index 00000000..fd62d0ba Binary files /dev/null and b/subgames/zeus/mods/zeus_default/textures/podzol.png differ diff --git a/subgames/zeus/mods/zeus_default/textures/podzol_side.png b/subgames/zeus/mods/zeus_default/textures/podzol_side.png new file mode 100755 index 00000000..d64502dd Binary files /dev/null and b/subgames/zeus/mods/zeus_default/textures/podzol_side.png differ diff --git a/subgames/zeus/mods/zeus_default/textures/workbench.png b/subgames/zeus/mods/zeus_default/textures/workbench.png new file mode 100644 index 00000000..6cc55c41 Binary files /dev/null and b/subgames/zeus/mods/zeus_default/textures/workbench.png differ diff --git a/subgames/zeus/mods/zeus_default/textures/workbench.xcf b/subgames/zeus/mods/zeus_default/textures/workbench.xcf new file mode 100644 index 00000000..8e5cb463 Binary files /dev/null and b/subgames/zeus/mods/zeus_default/textures/workbench.xcf differ diff --git a/subgames/zeus/mods/zeus_inventory/script/menu.lua b/subgames/zeus/mods/zeus_inventory/script/menu.lua index a5918703..84b3d64d 100644 --- a/subgames/zeus/mods/zeus_inventory/script/menu.lua +++ b/subgames/zeus/mods/zeus_inventory/script/menu.lua @@ -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 }) \ No newline at end of file diff --git a/subgames/zeus/mods/zeus_world/script/biomes/desert.lua b/subgames/zeus/mods/zeus_world/script/biomes/desert.lua index 00157c79..77e86540 100644 --- a/subgames/zeus/mods/zeus_world/script/biomes/desert.lua +++ b/subgames/zeus/mods/zeus_world/script/biomes/desert.lua @@ -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; \ No newline at end of file +-- 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; \ No newline at end of file diff --git a/subgames/zeus/mods/zeus_world/script/biomes/forest.lua b/subgames/zeus/mods/zeus_world/script/biomes/forest.lua index 0050f944..c8df11bf 100644 --- a/subgames/zeus/mods/zeus_world/script/biomes/forest.lua +++ b/subgames/zeus/mods/zeus_world/script/biomes/forest.lua @@ -1,178 +1,178 @@ -local identifier = "zeus:world:forest" - -local noise = { - heightmap = { - module = "add", - sources = { - runfile(_PATH .. 'world_noise'), { - -- Features - module = "scale_bias", - source = { - module = "perlin", - frequency = .5, - octaves = 3, - }, - scale = 3, - bias = 0 - } } - } -} - ---local woo = "zeus:default:wood" ---local lea = "zeus:default:leaves" ---local inv = "invalid" +-- local identifier = "zeus:world:forest" -- ---local trunk_layer_0 = { --- { inv, inv, inv, inv, inv }, --- { inv, woo, woo, woo, inv }, --- { inv, woo, woo, woo, inv }, --- { inv, woo, woo, woo, inv }, --- { inv, inv, inv, inv, inv } ---} --- ---local trunk_layer_1 = { --- { inv, inv, inv, inv, inv }, --- { inv, inv, woo, inv, inv }, --- { inv, woo, woo, woo, inv }, --- { inv, inv, woo, inv, inv }, --- { inv, inv, inv, inv, inv } ---} --- ---local trunk_layer_2 = { --- { inv, inv, inv, inv, inv }, --- { inv, inv, inv, inv, inv }, --- { inv, inv, woo, inv, inv }, --- { inv, inv, inv, inv, inv }, --- { inv, inv, inv, inv, inv } ---} --- ---local leaf_layer_1 = { --- { inv, lea, lea, lea, inv }, --- { lea, lea, lea, lea, lea }, --- { lea, lea, woo, lea, lea }, --- { lea, lea, lea, lea, lea }, --- { inv, lea, lea, lea, inv } ---} --- ---local leaf_layer_2 = { --- { inv, inv, inv, inv, inv }, --- { inv, lea, lea, lea, inv }, --- { inv, lea, woo, lea, inv }, --- { inv, lea, lea, lea, inv }, --- { inv, inv, inv, inv, inv } ---} --- ---local leaf_layer_3 = { --- { inv, inv, inv, inv, inv }, --- { inv, lea, lea, inv, inv }, --- { inv, lea, lea, lea, inv }, --- { inv, inv, lea, lea, inv }, --- { inv, inv, inv, inv, inv } ---} --- ---local tree = zepha.create_structure({ --- origin = V(2, 2, 2), --- probability = 0.01, --- schematic = { --- trunk_layer_0, --- trunk_layer_0, --- trunk_layer_0, --- trunk_layer_0, --- trunk_layer_1, --- trunk_layer_1, --- trunk_layer_1, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- trunk_layer_2, --- leaf_layer_2, --- leaf_layer_1, --- leaf_layer_1, --- leaf_layer_1, --- leaf_layer_1, --- leaf_layer_2, --- leaf_layer_3 --- } ---}) --- ---local woo = "zeus:default:wood" ---local lea = "zeus:default:leaves" ---local inv = "invalid" --- ---local shrub_layer_0 = { --- { inv, inv, inv }, --- { inv, woo, inv }, --- { inv, inv, inv } ---} --- ---local shrub_layer_1 = { --- { inv, lea, inv }, --- { lea, woo, lea }, --- { inv, lea, inv } ---} --- ---local shrub_layer_2 = { --- { inv, inv, inv }, --- { inv, lea, inv }, --- { inv, inv, inv } ---} --- ---local shrub = zepha.create_structure({ --- origin = V{1, 1, 1}, --- probability = 0.005, --- schematic = { --- shrub_layer_0, --- shrub_layer_1, --- shrub_layer_2, +-- local noise = { +-- heightmap = { +-- module = "add", +-- sources = { +-- runfile(_PATH .. 'world_noise'), { +-- -- Features +-- module = "scale_bias", +-- source = { +-- module = "perlin", +-- frequency = .5, +-- octaves = 3, +-- }, +-- scale = 3, +-- bias = 0 +-- } } -- } ---}) +-- } -- ---local structures = { tree, shrub } +-- --local woo = "zeus:default:wood" +-- --local lea = "zeus:default:leaves" +-- --local inv = "invalid" +-- -- +-- --local trunk_layer_0 = { +-- -- { inv, inv, inv, inv, inv }, +-- -- { inv, woo, woo, woo, inv }, +-- -- { inv, woo, woo, woo, inv }, +-- -- { inv, woo, woo, woo, inv }, +-- -- { inv, inv, inv, inv, inv } +-- --} +-- -- +-- --local trunk_layer_1 = { +-- -- { inv, inv, inv, inv, inv }, +-- -- { inv, inv, woo, inv, inv }, +-- -- { inv, woo, woo, woo, inv }, +-- -- { inv, inv, woo, inv, inv }, +-- -- { inv, inv, inv, inv, inv } +-- --} +-- -- +-- --local trunk_layer_2 = { +-- -- { inv, inv, inv, inv, inv }, +-- -- { inv, inv, inv, inv, inv }, +-- -- { inv, inv, woo, inv, inv }, +-- -- { inv, inv, inv, inv, inv }, +-- -- { inv, inv, inv, inv, inv } +-- --} +-- -- +-- --local leaf_layer_1 = { +-- -- { inv, lea, lea, lea, inv }, +-- -- { lea, lea, lea, lea, lea }, +-- -- { lea, lea, woo, lea, lea }, +-- -- { lea, lea, lea, lea, lea }, +-- -- { inv, lea, lea, lea, inv } +-- --} +-- -- +-- --local leaf_layer_2 = { +-- -- { inv, inv, inv, inv, inv }, +-- -- { inv, lea, lea, lea, inv }, +-- -- { inv, lea, woo, lea, inv }, +-- -- { inv, lea, lea, lea, inv }, +-- -- { inv, inv, inv, inv, inv } +-- --} +-- -- +-- --local leaf_layer_3 = { +-- -- { inv, inv, inv, inv, inv }, +-- -- { inv, lea, lea, inv, inv }, +-- -- { inv, lea, lea, lea, inv }, +-- -- { inv, inv, lea, lea, inv }, +-- -- { inv, inv, inv, inv, inv } +-- --} +-- -- +-- --local tree = zepha.create_structure({ +-- -- origin = V(2, 2, 2), +-- -- probability = 0.01, +-- -- schematic = { +-- -- trunk_layer_0, +-- -- trunk_layer_0, +-- -- trunk_layer_0, +-- -- trunk_layer_0, +-- -- trunk_layer_1, +-- -- trunk_layer_1, +-- -- trunk_layer_1, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- trunk_layer_2, +-- -- leaf_layer_2, +-- -- leaf_layer_1, +-- -- leaf_layer_1, +-- -- leaf_layer_1, +-- -- leaf_layer_1, +-- -- leaf_layer_2, +-- -- leaf_layer_3 +-- -- } +-- --}) +-- -- +-- --local woo = "zeus:default:wood" +-- --local lea = "zeus:default:leaves" +-- --local inv = "invalid" +-- -- +-- --local shrub_layer_0 = { +-- -- { inv, inv, inv }, +-- -- { inv, woo, inv }, +-- -- { inv, inv, inv } +-- --} +-- -- +-- --local shrub_layer_1 = { +-- -- { inv, lea, inv }, +-- -- { lea, woo, lea }, +-- -- { inv, lea, inv } +-- --} +-- -- +-- --local shrub_layer_2 = { +-- -- { inv, inv, inv }, +-- -- { inv, lea, inv }, +-- -- { inv, inv, inv } +-- --} +-- -- +-- --local shrub = zepha.create_structure({ +-- -- origin = V{1, 1, 1}, +-- -- probability = 0.005, +-- -- schematic = { +-- -- shrub_layer_0, +-- -- shrub_layer_1, +-- -- shrub_layer_2, +-- -- } +-- --}) +-- -- +-- --local structures = { tree, shrub } +-- -- +-- --for i = 1, 5 do +-- -- table.insert(structures, zepha.create_structure({ +-- -- origin = V(), +-- -- probability = 0.01, +-- -- schematic = {{{ "zeus:default:tall_grass_" .. tostring(i) }}} +-- -- })) +-- --end +-- -- +-- --table.insert(structures, zepha.create_structure({ +-- -- origin = V(), +-- -- probability = 0.0025, +-- -- schematic = {{{ "zeus:flowers:flower_red_mushroom" }}} +-- --})) +-- -- +-- --table.insert(structures, zepha.create_structure({ +-- -- origin = V(), +-- -- probability = 0.0025, +-- -- schematic = {{{ "zeus:flowers:flower_brown_mushroom" }}} +-- --})) -- ---for i = 1, 5 do --- table.insert(structures, zepha.create_structure({ --- origin = V(), --- probability = 0.01, --- schematic = {{{ "zeus:default:tall_grass_" .. tostring(i) }}} --- })) ---end +-- local structures = {} -- ---table.insert(structures, zepha.create_structure({ --- origin = V(), --- probability = 0.0025, --- schematic = {{{ "zeus:flowers:flower_red_mushroom" }}} ---})) +-- zepha.register_biome(identifier, { +-- environment = { +-- temperature = 15/100, +-- humidity = 80/100, +-- roughness = 20/100, +-- }, +-- blocks = { +-- top = "zeus:default:podzol", +-- soil = "zeus:default:dirt", +-- rock = "zeus:default:stone" +-- }, +-- tags = { natural = 1, default = 1 }, +-- structures = structures, +-- biome_tint = "#7beb26", +-- noise = noise +-- }) -- ---table.insert(structures, zepha.create_structure({ --- origin = V(), --- probability = 0.0025, --- schematic = {{{ "zeus:flowers:flower_brown_mushroom" }}} ---})) - -local structures = {} - -zepha.register_biome(identifier, { - environment = { - temperature = 15/100, - humidity = 80/100, - roughness = 20/100, - }, - blocks = { - top = "zeus:default:podzol", - soil = "zeus:default:dirt", - rock = "zeus:default:stone" - }, - tags = { natural = 1, default = 1 }, - structures = structures, - biome_tint = "#7beb26", - noise = noise -}) - -return identifier \ No newline at end of file +-- return identifier \ No newline at end of file diff --git a/subgames/zeus/mods/zeus_world/script/biomes/highlands.lua b/subgames/zeus/mods/zeus_world/script/biomes/highlands.lua index 3d78569d..53a56456 100644 --- a/subgames/zeus/mods/zeus_world/script/biomes/highlands.lua +++ b/subgames/zeus/mods/zeus_world/script/biomes/highlands.lua @@ -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 \ No newline at end of file +-- 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 \ No newline at end of file diff --git a/subgames/zeus/mods/zeus_world/script/biomes/plains.lua b/subgames/zeus/mods/zeus_world/script/biomes/plains.lua index adcd383b..9408f696 100644 --- a/subgames/zeus/mods/zeus_world/script/biomes/plains.lua +++ b/subgames/zeus/mods/zeus_world/script/biomes/plains.lua @@ -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, { diff --git a/subgames/zeus/mods/zeus_world/script/init.lua b/subgames/zeus/mods/zeus_world/script/init.lua index 831756cd..49e73745 100644 --- a/subgames/zeus/mods/zeus_world/script/init.lua +++ b/subgames/zeus/mods/zeus_world/script/init.lua @@ -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') \ No newline at end of file