Add a mutex to Chunk, safeguard all existing reads/writes.

* Clean up more imports.
* Create FileManipulator class.
master
Nicole Collings 2020-07-06 14:00:46 -07:00
parent ad169fbb1e
commit 2380c7ea31
56 changed files with 391 additions and 118 deletions

5
.gitignore vendored
View File

@ -1,5 +1,8 @@
lib/*/*
cmake-build-debug
cmake-build-install
cmake-build-release
.hidden
lib/*/*
worlds

View File

@ -8,6 +8,7 @@
<option name="clangTidyChecks" value="*,-android-*,-bugprone-bool-pointer-implicit-conversion,-cert-env33-c,-cert-dcl50-cpp,-cert-dcl59-cpp,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-*,-google-*,google-default-arguments,google-explicit-constructor,google-runtime-member-string-references,google-runtime-operator,-hicpp-braces-around-statements,-hicpp-named-parameter,-hicpp-no-array-decay,-hicpp-no-assembler,-hicpp-no-malloc,-hicpp-function-size,-hicpp-special-member-functions,-hicpp-vararg,-llvm-*,-objc-*,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-simplify-boolean-expr,-readability-braces-around-statements,-readability-identifier-naming,-readability-function-size,-readability-redundant-member-init,-misc-bool-pointer-implicit-conversion,-misc-definitions-in-headers,-misc-unused-alias-decls,-misc-unused-parameters,-misc-unused-using-decls,-modernize-use-using,-modernize-use-default-member-init,-clang-diagnostic-*,-clang-analyzer-*,-cert-msc30-c,-cert-msc50-cpp,-bugprone-integer-division,-modernize-use-auto" />
</inspection_tool>
<inspection_tool class="OCDFAInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OCUnusedMacro" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />

View File

@ -7,7 +7,7 @@ out vec4 outColor;
in vec2 texCoords;
//uniform sampler2D gPosition;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gColorSpec;
uniform sampler2D ssaoSampler;
@ -15,6 +15,7 @@ uniform sampler2D ssaoSampler;
uniform vec3 camPosition;
void main() {
vec3 fragPos = texture(gPosition, texCoords).rgb;
vec3 normal = texture(gNormal, texCoords).rgb;
vec3 color = texture(gColorSpec, texCoords).rgb;
float ssao = texture(ssaoSampler, texCoords).r;
@ -22,29 +23,14 @@ void main() {
//Shade based on Normals
float shading = (0.95 + abs(normal.x) * 0.1) + (normal.y * 0.15);
color *= vec3(shading);
vec3 lighting = color;
//Apply Lighting
// lighting *= 0.1;
//
// float radius = 16;
//
// float lightDist = length(camPosition - fragPos);
// if (lightDist < radius) {
// vec3 lightDir = normalize(camPosition - fragPos);
// vec3 diffuse = max(dot(normal, lightDir) * 0.6 + 0.4, 0.0) * color * vec3(1, 1, 1);
// diffuse *= 1 - min(lightDist / radius, 1);
// lighting += diffuse;
// }
color *= ssao;
//Apply fog color based on distance from camera
// float dist = distance(vec3(0, 0, 0), vec3(fragPos));
// float dist = distance(camPosition, fragPos);
// float nearFog = min(max(dist - 200, 0) / 100, 1);
// float farFog = min(max(dist - 250, 0) / 100, 1);
// color = mix(mix(vec3(lighting), NEAR_FOG, nearFog), FAR_FOG, farFog);
color = lighting * ssao;
//
// color = mix(mix(color, NEAR_FOG, nearFog), FAR_FOG, farFog);
outColor = vec4(color, 1);
}

View File

@ -111,8 +111,8 @@ set(ZEPHA_SRC
def/ClientGame.h
world/chunk/Region.cpp
world/chunk/MapBlock.cpp
util/Util.h
world/block/PointedThing.h
util/Util.h
world/PointedThing.h
game/hud/components/compound/GuiLabelledGraph.cpp
game/hud/components/compound/GuiLabelledGraph.cpp
game/entity/engine/ParticleEntity.cpp
@ -331,6 +331,6 @@ set(ZEPHA_SRC
game/scene/world/graph/FarMeshGenerator.h
game/scene/world/FarMapMeshDetails.h
lua/api/class/LuaGuiElement.cpp
lua/api/class/LuaGuiElement.h world/Dimension.cpp world/Dimension.h)
lua/api/class/LuaGuiElement.h world/Dimension.cpp world/Dimension.h world/fs/FileManipulator.cpp world/fs/FileManipulator.h)
add_library (Zepha_Core ${ZEPHA_SRC})

View File

@ -4,6 +4,12 @@
#include "Client.h"
#include "../util/Timer.h"
#include "scene/GameScene.h"
#include "scene/ConnectScene.h"
#include "scene/MainMenuScene.h"
#include "scene/LuaErrorScene.h"
Client::Client(const std::string& path, const Address &addr, glm::ivec2 dims) :
state(path.substr(0, path.find_last_of('/') + 1), renderer),
renderer(dims),

View File

@ -7,11 +7,6 @@
#include "ClientState.h"
#include "graph/Renderer.h"
#include "graph/scene/SceneManager.h"
#include "scene/MainMenuScene.h"
#include "scene/ConnectScene.h"
#include "scene/GameScene.h"
#include "scene/LuaErrorScene.h"
#include "../util/Timer.h"
#include "../server/LocalServerInstance.h"
class Client {

View File

@ -4,11 +4,11 @@
#pragma once
#include "graph/Renderer.h"
#include "scene/net/ClientNetworkInterpreter.h"
#include "../def/ClientGame.h"
#include "scene/net/ServerConnection.h"
class Renderer;
class ClientState {
public:
ClientState(const std::string& path, Renderer& renderer);

View File

@ -6,6 +6,8 @@
#include "Entity.h"
#include "../graph/Renderer.h"
Entity::Entity() : model(std::make_unique<Model>()) {}
Entity::Entity(std::shared_ptr<Model> model) : animState(*model), model(model) {}

View File

@ -141,11 +141,13 @@ void Renderer::endDeferredCalls() {
light.set(light.uniforms.camPosition, camera.getPos());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, blur.colorBuffer);
glBindTexture(GL_TEXTURE_2D, light.gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, light.gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, light.gColorSpec);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, blur.colorBuffer);
glEnable(GL_BLEND);
renderQuad();

View File

@ -4,7 +4,7 @@
#pragma once
#include "../Renderer.h"
class Renderer;
class Drawable {
public:

View File

@ -4,6 +4,7 @@
#pragma once
#include <vector>
#include "Drawable.h"

View File

@ -2,10 +2,10 @@
// Created by aurailus on 25/11/18.
//
#include <vector>
#include "ChunkMesh.h"
#include "ChunkVertex.h"
void ChunkMesh::create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices) {
indCount = static_cast<GLsizei>(indices.size());

View File

@ -4,13 +4,17 @@
#pragma once
#include <vector>
#include <stdexcept>
#include "Mesh.h"
#include "ChunkVertex.h"
class ChunkVertex;
class ChunkMesh : public Mesh {
public:
ChunkMesh() = default;
ChunkMesh(const ChunkMesh& o) { assert(false); };
ChunkMesh(const ChunkMesh& o) { throw std::runtime_error("No copy constructor for ChunkMeshes"); };
void create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices);

View File

@ -14,12 +14,14 @@ void LightingShader::postCreate() {
uniforms.gPosition = get("gPosition");
uniforms.gNormal = get("gNormal");
uniforms.gColorSpec = get("gColorSpec");
uniforms.ssaoSampler = get("ssaoSampler");
uniforms.camPosition = get("camPosition");
use();
set(uniforms.gPosition, 0);
set(uniforms.gNormal, 1);
set(uniforms.gColorSpec, 2);
set(uniforms.ssaoSampler, 3);
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);

View File

@ -19,6 +19,7 @@ public:
GLint gPosition;
GLint gNormal;
GLint gColorSpec;
GLint ssaoSampler;
GLint camPosition;
};

View File

@ -3,7 +3,8 @@
//
#include "GameGui.h"
#include "components/compound/GuiInventoryList.h"
#include "../graph/Renderer.h"
GameGui::GameGui(LocalInventoryRefs& refs, glm::vec2 bufferSize, ClientGame& defs, Renderer& renderer) :
refs(refs),

View File

@ -5,16 +5,7 @@
#pragma once
#include "GameGuiBuilder.h"
#include "SerialGui.h"
#include "components/basic/GuiText.h"
#include "components/basic/GuiRect.h"
#include "components/basic/GuiContainer.h"
#include "../graph/drawable/DrawableGroup.h"
#include "../inventory/ServerInventoryList.h"
#include "../entity/Entity.h"
#include "../../util/Util.h"
#include "components/compound/GuiInventoryList.h"
#include "../inventory/Inventory.h"
class GameGui {
public:

View File

@ -3,8 +3,11 @@
//
#include <utility>
#include "GuiComponent.h"
#include "../../graph/Renderer.h"
GuiComponent::GuiComponent(const std::string& key) :
key(key) {}

View File

@ -10,6 +10,8 @@
#include "../../entity/Entity.h"
class Window;
class GuiComponent : public Drawable {
public:
enum class CallbackType { PRIMARY, SECONDARY, HOVER };

View File

@ -4,6 +4,8 @@
#include "GuiModel.h"
#include "../../SerialGui.h"
#include "../../../graph/Renderer.h"
#include "../../../../def/ClientGame.h"
#include "../../../../def/model/ModelStore.h"

View File

@ -7,11 +7,10 @@
#include <string>
#include "GuiContainer.h"
#include "../../../../def/ItemDef.h"
#include "../../SerialGui.h"
class ClientGame;
class ModelStore;
class LuaGuiElement;
class GuiModel : public GuiComponent {
public:

View File

@ -6,6 +6,7 @@
#include "ConnectScene.h"
#include "../graph/Renderer.h"
#include "../../util/net/Packet.h"
#include "../../util/net/PacketType.h"
#include "../../util/net/PacketView.h"

View File

@ -4,6 +4,7 @@
#include "GameScene.h"
#include "../graph/Renderer.h"
#include "../../util/net/Packet.h"
#include "../../util/net/PacketView.h"

View File

@ -4,11 +4,11 @@
#pragma once
#include "world/Player.h"
#include "../ClientState.h"
#include "../hud/DebugGui.h"
#include "../graph/scene/Scene.h"
#include "world/Player.h"
#include "../hud/DebugGui.h"
class GameScene : public Scene {
public:
explicit GameScene(ClientState& state);

View File

@ -3,6 +3,8 @@
//
#include "LuaErrorScene.h"
#include "../graph/Renderer.h"
#include "../../def/texture/Font.h"
#include "../hud/components/basic/GuiRect.h"
#include "../hud/components/basic/GuiText.h"

View File

@ -5,7 +5,9 @@
#pragma once
#include <string>
#include "../graph/scene/Scene.h"
#include "../hud/components/basic/GuiContainer.h"
class LuaErrorScene : public Scene {

View File

@ -4,6 +4,10 @@
#include "MainMenuScene.h"
#include "../graph/Renderer.h"
#include "../hud/components/basic/GuiText.h"
#include "../hud/components/compound/GuiImageButton.h"
MainMenuScene::MainMenuScene(ClientState& state) :
Scene(state),
sandbox(sandboxArea, state, menuContainer) {

View File

@ -5,14 +5,13 @@
#pragma once
#include <json/json.hpp>
#include "../../game/ClientState.h"
#include "../../game/graph/scene/Scene.h"
#include "../hud/components/basic/GuiText.h"
#include "../hud/components/basic/GuiContainer.h"
#include "../hud/components/compound/GuiImageButton.h"
#include "menu/Subgame.h"
#include "menu/MenuSandbox.h"
class ClientState;
using nlohmann::json;
class MainMenuScene : public Scene {

View File

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

View File

@ -101,6 +101,7 @@ unsigned short LocalWorld::getBiome(glm::vec3 pos) {
auto local = Space::Block::relative::toChunk(pos);
auto chunk = getChunk(chunkPos);
auto l = chunk->aquireLock();
if (chunk != nullptr) return chunk->getBiome(local);
return BiomeAtlas::INVALID;
}

View File

@ -90,11 +90,6 @@ void MeshGenStream::Thread::exec() {
auto& u = tasks[i];
if (!u.busy) continue;
if (u.thisChunk == nullptr) {
std::cout << Util::vecToString(u.thisChunk->pos) << std::endl;
continue;
}
ChunkMeshGenerator m(u.meshDetails, game.defs, game.biomes, u.thisChunk, u.adjacentChunks, offsetSamplers);
hasNoTasks = false;
u.busy = false;

View File

@ -5,6 +5,7 @@
#include "Player.h"
#include "../../../util/Ray.h"
#include "../../graph/Renderer.h"
#include "../../../world/chunk/Chunk.h"
Player::Player(LocalWorld& world, ClientGame& defs, Renderer& renderer, LocalInventoryRefs& refs) :
@ -141,19 +142,22 @@ void Player::updateCamera() {
void Player::findPointedThing(Input &input) {
glm::ivec3 chunkPos = {};
std::unique_lock<std::mutex> lock {};
std::shared_ptr<Chunk> blockChunk = nullptr;
for (Ray ray(this); ray.getLength() < LOOK_DISTANCE; ray.step(LOOK_PRECISION)) {
glm::vec3 rayEnd = ray.getEnd();
glm::ivec3 roundedPos = glm::floor(rayEnd);
auto currChunkPos = Space::Chunk::world::fromBlock(roundedPos);
if (glm::ivec3(currChunkPos) != chunkPos || blockChunk == nullptr) {
glm::ivec3 currChunkPos = Space::Chunk::world::fromBlock(roundedPos);
if (currChunkPos != chunkPos || blockChunk == nullptr) {
chunkPos = currChunkPos;
blockChunk = world.getChunk(chunkPos);
}
if (blockChunk == nullptr) continue;
if (blockChunk == nullptr) continue;
lock = blockChunk->aquireLock();
}
unsigned int blockID = blockChunk->getBlock(Space::Block::relative::toChunk(roundedPos));
auto& boxes = game.defs.blockFromId(blockID).sBoxes;

View File

@ -8,9 +8,10 @@
#include "../../graph/drawable/Drawable.h"
#include "../../hud/GameGui.h"
#include "../../../world/block/PointedThing.h"
#include "../../../world/PointedThing.h"
#include "../../entity/engine/WireframeEntity.h"
class Input;
class LuaGuiElement;
class LocalInventory;
class LocalInventoryRefs;

View File

@ -66,8 +66,8 @@ private:
std::thread thread;
};
MapGen* gen;
std::shared_ptr<MapGenProps> props;
MapGen* gen;
std::vector<Thread> threads;
std::list<std::unique_ptr<PacketView>> queuedPacketTasks;

View File

@ -10,6 +10,10 @@
#include "../ChunkMeshDetails.h"
#include "../../../../util/Vec.h"
#include "../../../../world/chunk/Chunk.h"
#include "../../../../def/item/BlockModel.h"
#include "../../../../def/gen/NoiseSample.h"
#include "../../../../def/gen/LocalBiomeAtlas.h"
#include "../../../../def/LocalDefinitionAtlas.h"
ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
std::shared_ptr<Chunk> chunk, std::array<std::shared_ptr<Chunk>, 6> adjacent,
@ -24,6 +28,11 @@ ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefin
meshDetails->vertices.reserve(5000);
meshDetails->indices.reserve(7000);
// Lock the related chunks
std::array<std::unique_lock<std::mutex>, 7> locks;
locks[0] = std::move(chunk->aquireLock());
for (unsigned int i = 0; i < 6; i++) locks[i+1] = std::move(adjacent[i]->aquireLock());
const auto& blockData = chunk->cGetBlocks();
const auto& biomeData = chunk->cGetBiomes();

View File

@ -4,15 +4,16 @@
#pragma once
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#define GLM_ENABLE_EXPERIMENTAL
#pragma clang diagnostic pop
#include "../../../../def/ClientGame.h"
#include "../../../../def/gen/NoiseSample.h"
#include <memory>
class LocalDefinitionAtlas;
class ChunkMeshDetails;
class LocalBiomeAtlas;
class NoiseSample;
class BlockDef;
class MeshPart;
class Chunk;
class ChunkMeshGenerator {

View File

@ -5,7 +5,8 @@
#pragma once
#include <glm/vec3.hpp>
#include "../../../graph/Renderer.h"
class Renderer;
struct ChunkRenderElem {
virtual void draw(Renderer& renderer) = 0;

View File

@ -2,10 +2,16 @@
// Created by aurailus on 15/12/18.
//
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "MeshChunk.h"
#include "../../../graph/Renderer.h"
#include "../../../graph/meshtypes/ChunkMesh.h"
void MeshChunk::create(std::vector<ChunkVertex> &vertices, std::vector<unsigned int> &indices) {
this->mesh = std::make_unique<ChunkMesh>();
this->mesh = std::make_shared<ChunkMesh>();
mesh->create(vertices, indices);
}

View File

@ -5,11 +5,14 @@
#pragma once
#include <memory>
#include <vector>
#include "ChunkRenderElem.h"
#include "../../../graph/drawable/Drawable.h"
#include "../../../graph/meshtypes/ChunkVertex.h"
#include "../../../graph/meshtypes/ChunkMesh.h"
class ChunkMesh;
class ChunkVertex;
class MeshChunk : public ChunkRenderElem, Drawable {
public:
MeshChunk() = default;
@ -21,6 +24,6 @@ public:
void setPos(glm::vec3 pos);
glm::vec3 getPos() override;
private:
std::unique_ptr<ChunkMesh> mesh = nullptr;
std::shared_ptr<ChunkMesh> mesh = nullptr;
glm::vec3 pos {};
};

View File

@ -5,11 +5,12 @@
#include "LocalLuaParser.h"
#include "../ErrorFormatter.h"
#include "../../game/ClientState.h"
#include "../../game/graph/Renderer.h"
#include "../register/RegisterBlocks.h"
#include "../register/RegisterItems.h"
#include "../register/RegisterBiomes.h"
#include "../register/RegisterKeybinds.h"
#include "../../game/ClientState.h"
// Usertypes
#include "../api/class/LuaGuiElement.h"

View File

@ -21,7 +21,7 @@ Server::Server(unsigned short port, const std::string& subgame) :
world(seed, defs, clientList) {
defs.init(world);
world.init();
world.init("world");
config.init();
std::cout << Log::info << "Server started successfully, listening for clients." << Log::endl;

View File

@ -12,6 +12,7 @@
#include "../conn/ServerClient.h"
#include "../../world/chunk/Chunk.h"
#include "../../world/chunk/MapBlock.h"
#include "../../world/fs/FileManipulator.h"
ServerWorld::ServerWorld(unsigned int seed, ServerGame& game, ClientList& clients) :
clientList(clients),
@ -51,8 +52,11 @@ ServerWorld::ServerWorld(unsigned int seed, ServerGame& game, ClientList& client
}
}
void ServerWorld::init() {
void ServerWorld::init(const std::string& worldDir) {
genStream = std::make_unique<ServerGenStream>(seed, game);
fileManip = std::make_shared<FileManipulator>("worlds/" + worldDir + "/");
generateMapBlock({0, 0, 0});
}
void ServerWorld::update(double delta) {
@ -67,6 +71,7 @@ void ServerWorld::update(double delta) {
for (const auto& chunk : mb.chunks) {
changed.insert(chunk->pos);
dimension.setChunk(chunk);
// fileManip->commitChunk(*chunk);
}
auto resend = dimension.calculateEdgeLight(mb.pos);
@ -178,7 +183,11 @@ void ServerWorld::sendChunk(const std::shared_ptr<Chunk>& chunk, ServerClient &p
if (chunk == nullptr || !chunk->generated) return;
Packet r(PacketType::CHUNK);
auto l = chunk->aquireLock();
r.data = chunk->serialize();
l.release();
r.sendTo(peer.peer, PacketChannel::CHUNK);
}

View File

@ -13,6 +13,7 @@
class ServerGame;
class ClientList;
class ServerClient;
class FileManipulator;
class ServerGenStream;
class ServerWorld : public World {
@ -22,7 +23,7 @@ public:
explicit ServerWorld(unsigned int seed, ServerGame& game, ClientList& clients);
void init();
void init(const std::string& worldDir);
void update(double delta) override;
unsigned int getBlock(glm::ivec3 pos) override;
@ -44,6 +45,9 @@ private:
unsigned int seed;
ServerGame& game;
ClientList& clientList;
std::string worldDir;
std::shared_ptr<FileManipulator> fileManip;
unsigned int generatedMapBlocks = 0;
std::vector<glm::ivec3> generateOrder;

View File

@ -63,6 +63,16 @@ template <> inline Serializer& Serializer::append<unsigned short>(const unsigned
return *this;
}
template <> inline Serializer& Serializer::append<char>(const char& elem) {
data += elem;
return *this;
}
template <> inline Serializer& Serializer::append<unsigned char>(const unsigned char& elem) {
data += elem;
return *this;
}
template <> inline Serializer& Serializer::append<float>(const float& elem) {
float_union cv = { elem };
data += cv.bytes[0];

View File

@ -8,9 +8,12 @@
#include "../def/DefinitionAtlas.h"
bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return false;
auto l = chunk->aquireLock();
if (!DimensionBase::setBlock(pos, block)) return false;
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
auto &def = defs.blockFromId(block);
glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos));
@ -22,6 +25,8 @@ bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
if (def.lightPropagates) reflowLight(pos);
if (!def.lightPropagates && getLight(pos, chunk.get()).w != 0) removeSunlight(pos);
l.release();
propogateRemoveNodes();
return true;
@ -55,11 +60,19 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::calculateEdgeLight(glm::iv
}
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
std::vector<std::unique_lock<std::mutex>> collectedLocks;
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
for (unsigned int channel = 0; channel < lightAddQueue.size(); channel++) {
while (!lightAddQueue[channel].empty()) {
LightAddNode& node = lightAddQueue[channel].front();
Chunk* chunk = node.chunk;
if (!chunksUpdated.count(chunk->pos)) {
chunksUpdated.insert(chunk->pos);
collectedLocks.push_back(std::move(chunk->aquireLock()));
}
unsigned char lightLevel = node.chunk->getLight(node.index, channel);
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
@ -71,8 +84,11 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
else {
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
if (!chunk) continue;
chunksUpdated.insert(chunk->pos);
chunk->dirty = true;
if (!chunksUpdated.count(chunk->pos)) {
chunksUpdated.insert(chunk->pos);
collectedLocks.push_back(std::move(chunk->aquireLock()));
chunk->dirty = true;
}
}
bool sunDown = (channel == SUNLIGHT_CHANNEL && lightLevel == 15 && i.y == -1);
@ -91,6 +107,7 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
}
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
std::vector<std::unique_lock<std::mutex>> collectedLocks;
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
for (unsigned int channel = 0; channel < lightRemoveQueue.size(); channel++) {
@ -106,8 +123,11 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
else {
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
if (!chunk) continue;
chunksUpdated.insert(chunk->pos);
chunk->dirty = true;
if (!chunksUpdated.count(chunk->pos)) {
chunksUpdated.insert(chunk->pos);
collectedLocks.push_back(std::move(chunk->aquireLock()));
chunk->dirty = true;
}
}
unsigned char checkLight = chunk->getLight(ind, channel);
@ -147,6 +167,9 @@ glm::ivec4 Dimension::getLight(glm::ivec3 worldPos, Chunk *chunk) {
}
void Dimension::calculateHorizontalEdge(std::shared_ptr<Chunk> a, std::shared_ptr<Chunk> b) {
auto l1 = a->aquireLock();
auto l2 = b->aquireLock();
for (unsigned int j = 0; j < 256; j++) {
glm::ivec3 diff = a->pos - b->pos;
@ -166,6 +189,9 @@ void Dimension::calculateHorizontalEdge(std::shared_ptr<Chunk> a, std::shared_pt
}
void Dimension::calculateVerticalEdge(std::shared_ptr<Chunk> above, std::shared_ptr<Chunk> below) {
auto l1 = above->aquireLock();
auto l2 = below->aquireLock();
for (unsigned int j = 0; j < 256; j++) {
unsigned int xx = j / 16;
unsigned int zz = j % 16;

View File

@ -60,13 +60,16 @@ void DimensionBase::removeChunk(glm::ivec3 pos){
unsigned int DimensionBase::getBlock(glm::ivec3 pos) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (chunk) return chunk->getBlock(Space::Block::relative::toChunk(pos));
return 0;
if (!chunk) return 0;
auto l = chunk->aquireLock();
return chunk->getBlock(Space::Block::relative::toChunk(pos));
}
bool DimensionBase::setBlock(glm::ivec3 pos, unsigned int block) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return false;
auto l = chunk->aquireLock();
auto &def = defs.blockFromId(block);
return chunk->setBlock(Space::Block::relative::toChunk(pos), block);

View File

@ -6,6 +6,7 @@
#include "../world/chunk/Chunk.h"
#include "../world/chunk/Region.h"
#include "../game/graph/Renderer.h"
#include "../util/net/PacketView.h"
#include "../world/chunk/MapBlock.h"
#include "../lua/api/class/LocalLuaEntity.h"

View File

@ -4,8 +4,8 @@
#pragma once
#include "../../def/item/BlockDef.h"
#include "../../def/ClientGame.h"
#include "../def/item/BlockDef.h"
#include "../def/ClientGame.h"
class PointedThing {
public:

View File

@ -21,6 +21,18 @@ Chunk::Chunk(const std::vector<unsigned int>& blocks, const std::vector<unsigned
recalculateRenderableBlocks();
}
Chunk::Chunk(const Chunk& o) :
partial(o.partial),
generated(o.generated),
dirty(o.dirty),
shouldRender(o.shouldRender),
pos(o.pos),
blocks(o.blocks),
biomes(o.biomes),
blockLight(o.blockLight),
sunLight(o.sunLight),
renderableBlocks(o.renderableBlocks) {}
bool Chunk::setBlock(unsigned int ind, unsigned int blk) {
if (!RIE::write(ind, blk, blocks, 4096)) return false;
if (blk == DefinitionAtlas::AIR && !(renderableBlocks = std::max(renderableBlocks - 1, 0))) shouldRender = false;
@ -64,7 +76,7 @@ std::string Chunk::serialize() {
void Chunk::deserialize(Deserializer& d) {
std::string gzipped = d.read<std::string>();
if (!gzip::is_compressed(gzipped.data(), gzipped.length())) throw "Invalid Blocks GZip Data.";
if (!gzip::is_compressed(gzipped.data(), gzipped.length())) throw "Chunk contains invalid gzipped data.";
std::vector<unsigned char> sunLight {};
std::vector<unsigned short> blockLight {};
@ -103,4 +115,4 @@ void Chunk::recalculateRenderableBlocks() {
shouldRender = true;
}
}
}
}

View File

@ -8,6 +8,7 @@
#include <array>
#include <vector>
#include <glm/vec3.hpp>
#include <mutex>
#include "../../util/RIE.h"
#include "../../util/Space.h"
@ -36,6 +37,9 @@ public:
Chunk() = default;
explicit Chunk(const std::vector<unsigned int>& blocks, const std::vector<unsigned short>& biomes);
Chunk(const std::vector<unsigned int>& blocks, const std::vector<unsigned short>& biomes, glm::ivec3 pos);
Chunk(const Chunk& o);
inline std::unique_lock<std::mutex> aquireLock();
inline unsigned int getBlock(unsigned int ind) const;
bool setBlock(unsigned int ind, unsigned int blk);
@ -72,6 +76,8 @@ public:
glm::ivec3 pos;
private:
std::mutex m;
std::vector<unsigned int> blocks {0, 0};
std::vector<unsigned short> biomes {0, 0};
@ -84,6 +90,11 @@ private:
inline void setSunlight(unsigned int ind, unsigned char val);
};
std::unique_lock<std::mutex> Chunk::aquireLock() {
std::unique_lock<std::mutex> lock(m, std::defer_lock);
return std::move(lock);
}
inline unsigned int Chunk::getBlock(const glm::ivec3& pos) const {
if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return 0; // Invalid
return getBlock(Space::Block::index(pos));

View File

@ -1,4 +1,5 @@
//
// The MapBlock class, contains 64 Chunks in a 4^3 cube.
// Created by aurailus on 18/04/19.
//

View File

@ -1,6 +1,10 @@
//
// Created by aurailus on 04/04/19.
//
//
// The Region class, contains 64 MapBlocks in a 4^3 cube.
// Created by aurailus on 18/04/19.
//
#pragma once

View File

@ -0,0 +1,120 @@
//
// Created by aurailus on 2020-06-24.
//
// File Format:
// 12 bytes -- Region Location Vec3
// 2 * 4096 bytes - Chunk offset within the file. -1 means it doesn't exist
// 1024 byte subsections for containing Chunks.
//
// Chunk Format:
// 4 bytes - Data length
// [remaining] - Serialized Chunk data
//
#include <fstream>
#include <iostream>
#include "FileManipulator.h"
#include "../chunk/Chunk.h"
#include "../../util/Util.h"
#include "../../util/net/Serializer.h"
#include "../../util/net/Deserializer.h"
FileManipulator::FileManipulator(const std::string &worldPath) :
path(worldPath) {
}
void FileManipulator::commitChunk(Chunk &chunk) {
// return;
glm::ivec3 reg = Space::Region::world::fromChunk(chunk.pos);
unsigned int chunkInd = Space::Chunk::index(chunk.pos);
std::string fileName = std::to_string(reg.x) + "_" + std::to_string(reg.y) + "_" + std::to_string(reg.z);
std::string filePath = path + "/" + fileName;
createRegionFileIfNotExists(reg);
std::string chunkData = chunk.serialize();
unsigned int dataBlockSize = floor(chunkData.length() / BLOCK_SIZE);
std::fstream file(filePath, std::ios::in|std::ios::out|std::ios::binary);
if (!file.is_open()) throw std::runtime_error("Couldn't open file.");
std::array<short, 4096> chunkOffsets {};
populateChunkOffsets(file, chunkOffsets);
unsigned int currentBlock = chunkOffsets[chunkInd];
unsigned int nextBlock = (chunkInd == 63 ? 10000 : chunkOffsets[chunkInd + 1]);
if (dataBlockSize > nextBlock - currentBlock)
shiftChunks(file, chunkOffsets, chunkInd + 1, dataBlockSize - (nextBlock - currentBlock));
writeChunk(file, chunkOffsets[chunkInd], chunkData);
file.close();
}
void FileManipulator::writeChunk(std::fstream& file, unsigned int offset, const std::string& data) {
file.seekp(META_OFFSET + offset * BLOCK_SIZE);
file.write(data.data(), data.length());
}
void FileManipulator::shiftChunks(std::fstream &file, std::array<short, 4096>& offsets, unsigned int ind, unsigned int amt) {
std::cout << "Shifting by " << amt << std::endl;
unsigned int startPos = offsets[ind] * BLOCK_SIZE + META_OFFSET;
unsigned int endPos; {
char *buff = new char[4];
file.seekg(META_OFFSET + offsets[63] * BLOCK_SIZE);
file.read(buff, 4);
endPos = META_OFFSET + BLOCK_SIZE * offsets[63] + Deserializer(buff, 4).read<unsigned int>();
}
unsigned int len = endPos - startPos;
char* buff = new char[len];
file.seekg(offsets[ind]);
file.read(buff, len);
file.seekp(offsets[ind] + amt * BLOCK_SIZE);
file.write(buff, len);
delete[] buff;
for (unsigned int i = ind; i < 4096; i++) {
offsets[i] += amt;
Serializer s;
s.append<short>(offsets[i]);
file.seekp(12 + i * 2);
file.write(s.data.data(), s.data.length());
file.close();
}
std::cout << "Shift done" << std::endl;
}
void FileManipulator::populateChunkOffsets(std::fstream& file, std::array<short, 4096>& offsets) {
file.seekg(12);
char* buff = new char[2];
for (unsigned int i = 0; i < 4096; i++) {
file.read(buff, 2);
offsets[i] = Deserializer(buff, 2).read<short>();
}
delete[] buff;
}
void FileManipulator::createRegionFileIfNotExists(glm::ivec3 pos) {
std::string fileName = std::to_string(pos.x) + "_" + std::to_string(pos.y) + "_" + std::to_string(pos.z);
std::string filePath = path + fileName;
if (cf_file_exists(filePath.data())) return;
std::fstream file(filePath, std::ios::out|std::ios::binary);
if (!file.is_open()) throw std::runtime_error("Couldn't open file.");
file.seekp(0);
Serializer s;
s.append(pos);
for (int i = 0; i < 4096; i++) s.append<short>(i);
for (int i = 0; i < 4096 * BLOCK_SIZE; i++) s.append<char>(0);
file.write(s.data.data(), s.data.length());
file.close();
}

View File

@ -0,0 +1,30 @@
//
// FileManipulator reads and writes world files.
// Created by aurailus on 2020-06-24.
//
#pragma once
#include <array>
#include <string>
#include <glm/vec3.hpp>
#include <cute_files/cute_files.h>
class Chunk;
class FileManipulator {
static constexpr unsigned int META_OFFSET = 12 + 2 * 4096;
static constexpr unsigned int BLOCK_SIZE = 256;
public:
FileManipulator(const std::string& worldPath);
void commitChunk(Chunk& chunk);
private:
static void writeChunk(std::fstream& file, unsigned int offset, const std::string& data);
static void shiftChunks(std::fstream& file, std::array<short, 4096>& offsets, unsigned int ind, unsigned int amt);
static void populateChunkOffsets(std::fstream& file, std::array<short, 4096>& offsets);
void createRegionFileIfNotExists(glm::ivec3 pos);
std::string path;
};

View File

@ -4,6 +4,7 @@ for i = 1, 5, 1 do
solid = false,
name = "Tall Grass",
model = "base:cross_plant",
light_propagates = true,
textures = {
"tint(0, zeus:default:tallgrass_"..i..")"
},

View File

@ -1,31 +1,39 @@
local woo = "zeus:default:wood"
local lea = "zeus:default:leaves"
local inv = "invalid"
-- 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},
-- schematic = {
-- shrub_layer_0,
-- shrub_layer_1,
-- shrub_layer_2,
-- }
-- })
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},
origin = V{},
schematic = {
shrub_layer_0,
shrub_layer_1,
shrub_layer_2,
{{"zeus:default:tallgrass_4"}}
}
})