Added thread safety to chunks & dimensions, reimplemented animations.

* Fixed air becoming invalid when placed with lua.
* Reimplemented client-side animations.
* Update AnimationManager Usertype to new format.
* Updated AnimationState & segment to be less icky.
* Updated some entity textures, added Mouse model and textures.
master
Nicole Collings 2020-08-06 16:15:23 -07:00
parent 5d46a12077
commit 71cbe034dd
54 changed files with 472 additions and 418 deletions

View File

@ -23,4 +23,7 @@
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectPlainTextFileTypeManager">
<file url="file://$PROJECT_DIR$/src/util/Lock.cpp" />
</component>
</project>

View File

@ -215,9 +215,8 @@ add_library(Zepha_Core
lua/ServerLuaParser.h
lua/ServerModHandler.cpp
lua/ServerModHandler.h
lua/usertype/cAnimationManager.h
lua/usertype/LocalLuaAnimationManager.cpp
lua/usertype/LocalLuaAnimationManager.h
lua/usertype/AnimationManager.cpp
lua/usertype/AnimationManager.h
lua/usertype/Player.cpp
lua/usertype/Player.h
lua/usertype/LuaGuiElement.cpp
@ -313,4 +312,4 @@ add_library(Zepha_Core
game/entity/Collision.cpp
game/entity/Collision.h
net/server/conn/ServerClient.cpp
net/server/conn/ServerClient.h lua/modules/Dimension.cpp lua/modules/Dimension.h util/CovariantPtr.h lua/usertype/Entity.cpp lua/usertype/Entity.h game/entity/LuaEntity.cpp game/entity/LuaEntity.h game/entity/LocalLuaEntity.cpp game/entity/LocalLuaEntity.h)
net/server/conn/ServerClient.h lua/modules/Dimension.cpp lua/modules/Dimension.h util/CovariantPtr.h lua/usertype/Entity.cpp lua/usertype/Entity.h game/entity/LuaEntity.cpp game/entity/LuaEntity.h game/entity/LocalLuaEntity.cpp game/entity/LocalLuaEntity.h util/Lockable.h)

View File

@ -25,6 +25,7 @@ LocalDefinitionAtlas::LocalDefinitionAtlas(TextureAtlas& atlas) {
BlockModel nullModel {};
BlockDef* air = new BlockDef();
air->identifier = "air";
air->index = 1;
air->name = "Air";
air->maxStackSize = 64;
air->model = nullModel;

View File

@ -23,6 +23,7 @@ ServerDefinitionAtlas::ServerDefinitionAtlas() {
BlockModel nullModel {};
BlockDef* air = new BlockDef();
air->identifier = "air";
air->index = 1;
air->name = "Air";
air->maxStackSize = 64;
air->model = nullModel;

View File

@ -7,7 +7,6 @@
#include <string>
struct AnimationSegment {
std::string animationName;
unsigned int startFrame;
unsigned int endFrame;
std::string name;
glm::ivec2 range;
};

View File

@ -10,49 +10,40 @@
AnimationState::AnimationState(Model &source) {
const ModelAnimation& animation = source.getAnimation();
currentFrame = 100;
ticksPerSecond = animation.ticksPerSecond;
duration = animation.duration;
endFrame = duration;
range = {0, duration};
}
void AnimationState::setAnimations(const std::vector<AnimationSegment> &anims) {
for (auto& anim : anims) {
defineAnimation(anim.animationName, anim.startFrame, anim.endFrame);
}
for (auto& anim : anims) defineAnimation(anim.name, anim.range);
}
void AnimationState::defineAnimation(const std::string& animationName, unsigned int startFrame, unsigned int endFrame) {
animations.emplace(animationName, AnimationSegment {animationName, startFrame, endFrame});
void AnimationState::defineAnimation(const std::string& name, glm::ivec2 range) {
animations.emplace(name, AnimationSegment {name, range});
}
void AnimationState::update(double delta) {
if (playing) {
float frame = currentFrame + (delta * ticksPerSecond);
if (loop) frame = fmod(frame - startFrame, endFrame - startFrame) + startFrame;
else frame = fmin(frame, endFrame);
if (loop) frame = fmod(frame - range.x, range.y - range.x) + range.x;
else frame = fmin(frame, range.y);
if (frame == endFrame) playing = false;
if (frame == range.y) playing = false;
currentFrame = frame;
}
}
void AnimationState::setAnimNamed(const std::string &animationName, double interpolateTime, bool loop) {
auto& anim = animations[animationName];
setAnimRange(anim.startFrame, anim.endFrame, 0, loop);
void AnimationState::setAnim(const std::string& name, double interp, bool loop) {
auto& anim = animations[name];
setAnim(anim.range, interp, loop);
}
void AnimationState::setAnimRange(unsigned int startFrame, unsigned int endFrame, double interpolateTime, bool loop) {
//TODO: Interpolate
this->startFrame = startFrame;
this->endFrame = endFrame;
currentFrame = startFrame;
void AnimationState::setAnim(glm::ivec2 range, double interp, bool loop) {
this->range = range;
this->loop = loop;
currentFrame = range.x;
}
void AnimationState::setPlaying(bool playing) {
@ -68,5 +59,5 @@ double AnimationState::getFrame() {
}
glm::ivec2 AnimationState::getBounds() {
return {startFrame, endFrame};
return range;
}

View File

@ -9,8 +9,9 @@
#include <string>
#include <glm/vec2.hpp>
#include "AnimationSegment.h"
class Model;
class AnimationSegment;
class AnimationState {
public:
@ -20,25 +21,25 @@ public:
void update(double delta);
void setAnimations(const std::vector<AnimationSegment>& anims);
void defineAnimation(const std::string& animationName, unsigned int startFrame, unsigned int endFrame);
void defineAnimation(const std::string& name, glm::ivec2 range);
void setAnimNamed(const std::string& animationName, double interpolateTime, bool loop);
void setAnimRange(unsigned int startFrame, unsigned int endFrame, double interpolateTime, bool loop);
void setAnim(const std::string& name, double interp, bool loop);
void setAnim(glm::ivec2 range, double interp, bool loop);
void setPlaying(bool playing);
void setFrame(double frame);
double getFrame();
void setFrame(double frame);
glm::ivec2 getBounds();
private:
std::map<std::string, AnimationSegment> animations;
unsigned int startFrame = 0;
unsigned int endFrame = 0;
glm::ivec2 range;
bool playing = false;
bool loop = false;
bool playing = false;
double currentFrame = 0;
double ticksPerSecond = 0;

View File

@ -18,16 +18,16 @@ DrawableEntity::DrawableEntity(SubgamePtr game, DimensionPtr dim) :
DrawableEntity::DrawableEntity(SubgamePtr game, DimensionPtr dim, std::shared_ptr<Model> model) :
Entity(game, dim),
model(model), animState(*model) {}
model(model) {}
void DrawableEntity::setModel(std::shared_ptr<Model> model) {
animState = AnimationState(*model);
animation = AnimationState(*model);
this->model = std::move(model);
animState.setPlaying(true);
animation.setPlaying(true);
}
void DrawableEntity::update(double delta) {
animState.update(delta);
animation.update(delta);
float factor = static_cast<float>(fmin(delta * 8, 1));
@ -102,28 +102,11 @@ void DrawableEntity::interpScale(glm::vec3 scale) {
Entity::setScale(scale);
}
void DrawableEntity::setAnimations(const std::vector<AnimationSegment>& anims) {
animState.setAnimations(anims);
}
void DrawableEntity::playAnimation(const std::string &anim, bool loop) {
animState.setAnimNamed(anim, 0, loop);
}
void DrawableEntity::playRange(unsigned int start, unsigned int end, bool loop) {
animState.setAnimRange(start, end, 0, loop);
}
void DrawableEntity::setPlaying(bool playing, unsigned int offset) {
animState.setPlaying(playing);
if (offset != UINT_MAX) animState.setFrame(offset + animState.getFrame());
}
void DrawableEntity::draw(Renderer& renderer) {
if (visible) {
renderer.setModelMatrix(getModelMatrix());
model->getTransformsByFrame(animState.getFrame(), animState.getBounds(), transforms);
model->getTransformsByFrame(animation.getFrame(), animation.getBounds(), transforms);
renderer.setBones(transforms);
for (const auto& mesh : model->meshes) mesh->draw();

View File

@ -12,9 +12,6 @@
#include "Entity.h"
#include "../graph/drawable/Drawable.h"
#include "AnimationState.h"
#include "AnimationSegment.h"
class DrawableEntity : virtual public Entity, public Drawable {
public:
DrawableEntity(const DrawableEntity& o) = delete;
@ -45,17 +42,11 @@ public:
virtual void setScale(glm::vec3 scale) override;
virtual void interpScale(glm::vec3 scale);
void setAnimations(const std::vector<AnimationSegment>& anims);
void playAnimation(const std::string& anim, bool loop);
void playRange(unsigned int start, unsigned int end, bool loop);
void setPlaying(bool playing, unsigned int offset);
void draw(Renderer& renderer) override;
void cleanup();
~DrawableEntity() override;
AnimationState animState {};
DrawableEntity* parent = nullptr;
protected:
glm::mat4 getModelMatrix();

View File

@ -6,6 +6,7 @@
#include <glm/vec3.hpp>
#include "AnimationState.h"
#include "../../util/CovariantPtr.h"
#include "../../def/item/SelectionBox.h"
@ -47,6 +48,7 @@ public:
SubgamePtr getGame();
AnimationState animation {};
protected:
SubgamePtr game = nullptr;
DimensionPtr dim = nullptr;

View File

@ -48,7 +48,7 @@ void GuiModel::update(double delta) {
}
void GuiModel::animate(glm::vec2 range) {
entity.playRange(range.x, range.y, true);
entity.animation.setAnim(range, 0, true);
}
void GuiModel::setRotationX(float x) {

View File

@ -291,24 +291,20 @@ void LocalPlayer::findPointedThing(Input &input) {
static constexpr float LOOK_PRECISION = 0.01f;
glm::ivec3 chunkPos = {};
std::unique_lock<std::mutex> lock {};
std::shared_ptr<Chunk> blockChunk = nullptr;
std::shared_ptr<Chunk> chunk = nullptr;
for (Ray ray(*this); ray.getLength() < LOOK_DISTANCE; ray.step(LOOK_PRECISION)) {
glm::vec3 rayEnd = ray.getEnd();
glm::ivec3 roundedPos = glm::floor(rayEnd);
glm::ivec3 currChunkPos = Space::Chunk::world::fromBlock(roundedPos);
if (currChunkPos != chunkPos || blockChunk == nullptr) {
if (currChunkPos != chunkPos || chunk == nullptr) {
chunkPos = currChunkPos;
blockChunk = dim->getChunk(chunkPos);
if (blockChunk == nullptr) continue;
lock = blockChunk->aquireLock();
chunk = dim->getChunk(chunkPos);
if (chunk == nullptr) continue;
}
unsigned int blockID = blockChunk->getBlock(Space::Block::relative::toChunk(roundedPos));
unsigned int blockID = chunk->getBlock(Space::Block::relative::toChunk(roundedPos));
auto& boxes = game->getDefs().blockFromId(blockID).sBoxes;
for (auto& sBox : boxes) {

View File

@ -32,13 +32,10 @@ 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());
auto l = chunk->getReadLock();
RIE::expand<unsigned int, 4096>(chunk->cGetBlocks(), eBlocks);
RIE::expand<unsigned short, 4096>(chunk->cGetBiomes(), eBiomes);
l.unlock();
BlockDef* block = nullptr;
BiomeDef* biome = nullptr;

View File

@ -20,9 +20,9 @@
#include "usertype/Dimension.h"
#include "usertype/ItemStack.h"
#include "usertype/InventoryList.h"
#include "usertype/AnimationManager.h"
#include "usertype/LuaGuiElement.h"
#include "usertype/cAnimationManager.h"
// Modules
#include "modules/Time.h"
@ -63,7 +63,6 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) {
core["__builtin"] = lua.create_table();
// Types
ClientApi::animation_manager (lua);
ClientApi::gui_element (lua);
Api::Usertype::Target::bind(Api::State::CLIENT, lua, core);
@ -73,6 +72,7 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) {
Api::Usertype::ItemStack::bind(Api::State::CLIENT, lua, core);
Api::Usertype::LocalPlayer::bind(Api::State::CLIENT, lua, core);
Api::Usertype::InventoryList::bind(Api::State::CLIENT, lua, core);
Api::Usertype::AnimationManager::bind(Api::State::CLIENT, lua, core);
core["client"] = true;
core["player"] = Api::Usertype::LocalPlayer(player);

View File

@ -23,6 +23,7 @@
#include "usertype/Dimension.h"
#include "usertype/ItemStack.h"
#include "usertype/InventoryList.h"
#include "usertype/AnimationManager.h"
// Modules
#include "modules/Time.h"
@ -101,6 +102,7 @@ void ServerLuaParser::loadApi(WorldPtr world) {
Api::Usertype::ItemStack::bind(Api::State::SERVER, lua, core);
Api::Usertype::ServerPlayer::bind(Api::State::SERVER, lua, core);
Api::Usertype::InventoryList::bind(Api::State::SERVER, lua, core);
Api::Usertype::AnimationManager::bind(Api::State::SERVER, lua, core);
core["server"] = true;
core["players"] = lua.create_table();

View File

@ -0,0 +1,56 @@
//
// Created by aurailus on 2020-01-14.
//
#include "AnimationManager.h"
#include "../Lua.h"
#include "../../game/entity/LuaEntity.h"
#include "../../game/entity/DrawableEntity.h"
#include "../../game/entity/AnimationSegment.h"
Api::Usertype::AnimationManager::AnimationManager(EntityPtr entity) :
entity(entity) {}
Api::Usertype::AnimationManager& Api::Usertype::AnimationManager::define(sol::table anims) {
std::vector<AnimationSegment> animations;
for (auto& ref : anims) {
std::string n = ref.first.as<std::string>();
sol::table t = ref.second.as<sol::table>();
animations.push_back({n, {static_cast<unsigned int>(t.get<float>(1)), static_cast<unsigned int>(t.get<float>(2))}});
}
entity->animation.setAnimations(animations);
return *this;
}
Api::Usertype::AnimationManager& Api::Usertype::AnimationManager::set_anim(sol::object anim, sol::optional<bool> loop) {
if (anim.is<std::string>()) entity->animation.setAnim(anim.as<std::string>(), 0, loop.value_or(true));
else if (anim.is<sol::table>()) entity->animation.setAnim(
glm::ivec2 {anim.as<sol::table>().get<unsigned int>(1), anim.as<sol::table>().get<unsigned int>(2)}, 0, loop.value_or(true));
return *this;
}
Api::Usertype::AnimationManager& Api::Usertype::AnimationManager::play(sol::optional<unsigned int> offset) {
entity->animation.setPlaying(true);
if (offset) entity->animation.setFrame(entity->animation.getFrame() + *offset);
return *this;
}
Api::Usertype::AnimationManager& Api::Usertype::AnimationManager::pause(sol::optional<unsigned int> offset) {
entity->animation.setPlaying(false);
if (offset) entity->animation.setFrame(entity->animation.getFrame() + *offset);
return *this;
}
void Api::Usertype::AnimationManager::bind(State, sol::state &lua, sol::table &core) {
lua.new_usertype<AnimationManager>("AnimationManager",
"define", &AnimationManager::define,
"set_anim", &AnimationManager::set_anim,
"play", &AnimationManager::play,
"pause", &AnimationManager::pause
);
}

View File

@ -0,0 +1,26 @@
//
// Created by aurailus on 2020-01-14.
//
#pragma once
#include "../Lua.h"
#include "../../util/CovariantPtr.h"
#include "SubgameUsertype.h"
namespace Api::Usertype {
class AnimationManager : public SubgameUsertype {
public:
AnimationManager(EntityPtr entity);
EntityPtr entity;
AnimationManager& define(sol::table anims);
AnimationManager& set_anim(sol::object anim, sol::optional<bool> loop);
AnimationManager& play(sol::optional<unsigned int> offset);
AnimationManager& pause(sol::optional<unsigned int> offset);
static void bind(State state, sol::state& lua, sol::table& core);
};
}

View File

@ -139,8 +139,8 @@ void Api::Usertype::Entity::bind(State, sol::state &lua, sol::table &core) {
"yaw", sol::property(&Entity::get_yaw, &Entity::set_yaw),
"roll", sol::property(&Entity::get_roll, &Entity::set_roll),
"scale", sol::property(&Entity::get_scale, &Entity::set_scale),
"dim", sol::property(&Entity::get_dimension)
"dim", sol::property(&Entity::get_dimension),
// "anims", sol::readonly(&Entity::manager)
"anims", sol::readonly(&Entity::animation)
);
}

View File

@ -9,16 +9,16 @@
#include "SubgameUsertype.h"
#include "Dimension.h"
#include "AnimationManager.h"
#include "../../util/CovariantPtr.h"
namespace Api::Usertype {
class Entity : public SubgameUsertype {
public:
Entity(EntityPtr entity) : entity(entity) {}
Entity(EntityPtr entity) : entity(entity), animation(entity) {}
EntityPtr entity;
// LocalLuaAnimationManager manager;
AnimationManager animation;
unsigned int get_id();

View File

@ -1,44 +0,0 @@
//
// Created by aurailus on 2020-01-14.
//
#include "LocalLuaAnimationManager.h"
#include "../Lua.h"
#include "../../game/entity/DrawableEntity.h"
#include "../../game/entity/AnimationSegment.h"
LocalLuaAnimationManager::LocalLuaAnimationManager(DrawableEntity &entity) :
entity(entity) {}
void LocalLuaAnimationManager::define(sol::table anims) {
std::vector<AnimationSegment> animations;
for (auto& ref : anims) {
std::string n = ref.first.as<std::string>();
sol::table t = ref.second.as<sol::table>();
animations.push_back({n, static_cast<unsigned int>(t.get<float>(1)), static_cast<unsigned int>(t.get<float>(2))});
}
entity.setAnimations(animations);
}
LocalLuaAnimationManager& LocalLuaAnimationManager::set_anim(sol::object anim, sol::optional<bool> loop) {
if (anim.is<std::string>()) {
entity.playAnimation(anim.as<std::string>(), loop.value_or(true));
}
else if (anim.is<sol::table>()) {
entity.playRange(anim.as<sol::table>().get<unsigned int>(1), anim.as<sol::table>().get<unsigned int>(2), loop.value_or(true));
}
return *this;
}
LocalLuaAnimationManager& LocalLuaAnimationManager::play(sol::optional<unsigned int> offset) {
entity.setPlaying(true, offset.value_or(UINT_MAX));
return *this;
}
LocalLuaAnimationManager& LocalLuaAnimationManager::pause(sol::optional<unsigned int> offset) {
entity.setPlaying(false, offset.value_or(UINT_MAX));
return *this;
}

View File

@ -1,21 +0,0 @@
//
// Created by aurailus on 2020-01-14.
//
#pragma once
#include "../Lua.h"
class DrawableEntity;
class LocalLuaAnimationManager {
public:
LocalLuaAnimationManager(DrawableEntity& entity);
void define(sol::table anims);
LocalLuaAnimationManager& set_anim(sol::object anim, sol::optional<bool> loop);
LocalLuaAnimationManager& play(sol::optional<unsigned int> offset);
LocalLuaAnimationManager& pause(sol::optional<unsigned int> offset);
private:
DrawableEntity& entity;
};

View File

@ -1,18 +0,0 @@
//
// Created by aurailus on 2020-01-14.
//
#pragma once
#include "LocalLuaAnimationManager.h"
namespace ClientApi {
void animation_manager(sol::state& lua) {
lua.new_usertype<LocalLuaAnimationManager>("AnimationManager",
"define", &LocalLuaAnimationManager::define,
"set_anim", &LocalLuaAnimationManager::set_anim,
"play", &LocalLuaAnimationManager::play,
"pause", &LocalLuaAnimationManager::pause
);
}
}

View File

@ -68,8 +68,7 @@ void ServerPacketStream::Thread::exec() {
Serializer s {};
for (unsigned int i = 0; i < 64; i++) {
auto chunk = (*j.mapBlock)[i];
auto l = chunk->aquireLock();
auto chunk = j.mapBlock->get(i);
s.append(chunk->serialize());
}

View File

@ -80,7 +80,7 @@ void ServerWorld::update(double delta) {
for (const auto& chunk : data.chunks) {
generatedMapBlocks.insert(data.pos);
updatedChunks.insert(glm::ivec4(chunk->pos, data.pos.w));
updatedChunks.insert(glm::ivec4(chunk->getPos(), data.pos.w));
dimension->setChunk(chunk);
}
@ -112,7 +112,7 @@ void ServerWorld::update(double delta) {
// Packet p(PacketType::CHUNK);
// auto l = chunk->aquireLock();
// p.data = chunk->serialize();
// l.release();
// l.unlock();
//
// for (auto& client : clientList.clients) {
// if (!client->hasPlayer) continue;

25
src/util/Lockable.h Normal file
View File

@ -0,0 +1,25 @@
//
// Created by aurailus on 2020-08-06.
//
#pragma once
#include <shared_mutex>
using MutexType = std::shared_timed_mutex;
using ReadLock = std::shared_lock<MutexType>;
using WriteLock = std::unique_lock<MutexType>;
class Lockable {
public:
ReadLock getReadLock() const {
return ReadLock {const_cast<MutexType&>(mutex)};
};
WriteLock getWriteLock() {
return WriteLock {mutex};
};
private:
MutexType mutex;
};

View File

@ -10,9 +10,11 @@
#include "../def/DefinitionAtlas.h"
bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
auto l = getReadLock();
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
l.unlock();
if (!chunk) return false;
auto l = chunk->aquireLock();
if (!DimensionBase::setBlock(pos, block)) return false;
@ -27,46 +29,47 @@ 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;
}
unsigned int Dimension::nextEntityInd() {
auto l = getWriteLock();
return entityInd++;
}
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::calculateEdgeLight(glm::ivec3 mbPos) {
bool ypos = mapBlockGenerated(mbPos + glm::ivec3 {0, 1, 0});
bool yneg = mapBlockGenerated(mbPos + glm::ivec3 {0, -1, 0});
bool xpos = mapBlockGenerated(mbPos + glm::ivec3 {1, 0, 0});
bool xneg = mapBlockGenerated(mbPos + glm::ivec3 {-1, 0, 0});
bool zpos = mapBlockGenerated(mbPos + glm::ivec3 {0, 0, 1});
bool zneg = mapBlockGenerated(mbPos + glm::ivec3 {0, 0, -1});
for (unsigned int i = 0; i < 64; i++) {
glm::ivec3 l = Space::Chunk::fromIndex(i);
glm::ivec3 chunkPos = mbPos * 4 + l;
auto self = getChunk(chunkPos);
if (yneg && l.y == 0) calculateVerticalEdge(self, getChunk(chunkPos + glm::ivec3 {0, -1, 0}));
else if (ypos && l.y == 3) calculateVerticalEdge(getChunk(chunkPos + glm::ivec3 {0, 1, 0}), self);
if (xpos && l.x == 3) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {1, 0, 0}));
else if (xneg && l.x == 0) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {-1, 0, 0}));
if (zpos && l.z == 3) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {0, 0, 1}));
else if (zneg && l.z == 0) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {0, 0, -1}));
}
return propogateRemoveNodes();
}
//std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::calculateEdgeLight(glm::ivec3 mbPos) {
// bool ypos = mapBlockGenerated(mbPos + glm::ivec3 {0, 1, 0});
// bool yneg = mapBlockGenerated(mbPos + glm::ivec3 {0, -1, 0});
// bool xpos = mapBlockGenerated(mbPos + glm::ivec3 {1, 0, 0});
// bool xneg = mapBlockGenerated(mbPos + glm::ivec3 {-1, 0, 0});
// bool zpos = mapBlockGenerated(mbPos + glm::ivec3 {0, 0, 1});
// bool zneg = mapBlockGenerated(mbPos + glm::ivec3 {0, 0, -1});
//
// for (unsigned int i = 0; i < 64; i++) {
// glm::ivec3 l = Space::Chunk::fromIndex(i);
// glm::ivec3 chunkPos = mbPos * 4 + l;
//
// auto self = getChunk(chunkPos);
//
// if (yneg && l.y == 0) calculateVerticalEdge(self, getChunk(chunkPos + glm::ivec3 {0, -1, 0}));
// else if (ypos && l.y == 3) calculateVerticalEdge(getChunk(chunkPos + glm::ivec3 {0, 1, 0}), self);
//
// if (xpos && l.x == 3) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {1, 0, 0}));
// else if (xneg && l.x == 0) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {-1, 0, 0}));
//
// if (zpos && l.z == 3) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {0, 0, 1}));
// else if (zneg && l.z == 0) calculateHorizontalEdge(self, getChunk(chunkPos + glm::ivec3 {0, 0, -1}));
// }
//
// return propogateRemoveNodes();
//}
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
std::vector<std::unique_lock<std::mutex>> collectedLocks;
auto l = getWriteLock();
//TODO: Test if I need to do additional locking here (or shared ptring)
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
for (unsigned int channel = 0; channel < lightAddQueue.size(); channel++) {
@ -74,13 +77,10 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
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()));
}
if (!chunksUpdated.count(chunk->getPos())) chunksUpdated.insert(chunk->getPos());
unsigned char lightLevel = node.chunk->getLight(node.index, channel);
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index);
for (const auto& i : Vec::TO_VEC) {
glm::ivec3 check = worldPos + i;
@ -90,10 +90,9 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
else {
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
if (!chunk) continue;
if (!chunksUpdated.count(chunk->pos)) {
chunksUpdated.insert(chunk->pos);
collectedLocks.push_back(std::move(chunk->aquireLock()));
chunk->dirty = true;
if (!chunksUpdated.count(chunk->getPos())) {
chunksUpdated.insert(chunk->getPos());
chunk->setDirty(true);
}
}
@ -113,13 +112,14 @@ 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;
auto l = getWriteLock();
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
for (unsigned int channel = 0; channel < lightRemoveQueue.size(); channel++) {
while (!lightRemoveQueue[channel].empty()) {
LightRemoveNode& node = lightRemoveQueue[channel].front();
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index);
for (const auto& i : Vec::TO_VEC) {
glm::ivec3 check = worldPos + i;
@ -129,10 +129,9 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
else {
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
if (!chunk) continue;
if (!chunksUpdated.count(chunk->pos)) {
chunksUpdated.insert(chunk->pos);
collectedLocks.push_back(std::move(chunk->aquireLock()));
chunk->dirty = true;
if (!chunksUpdated.count(chunk->getPos())) {
chunksUpdated.insert(chunk->getPos());
chunk->setDirty(true);
}
}
@ -156,6 +155,8 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
}
}
l.unlock();
auto otherChunksUpdated = propogateAddNodes();
chunksUpdated.insert(otherChunksUpdated.begin(), otherChunksUpdated.end());
@ -163,7 +164,7 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
}
bool Dimension::containsWorldPos(Chunk *chunk, glm::ivec3 pos) {
return chunk && Space::Chunk::world::fromBlock(pos) == chunk->pos;
return chunk && Space::Chunk::world::fromBlock(pos) == chunk->getPos();
}
glm::ivec4 Dimension::getLight(glm::ivec3 worldPos, Chunk *chunk) {
@ -173,11 +174,8 @@ 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;
glm::ivec3 diff = a->getPos() - b->getPos();
glm::ivec3 aPos = {
(diff.x == 0 ? j % 16 : diff.x == 1 ? 0 : 15), j / 16,
@ -189,15 +187,12 @@ void Dimension::calculateHorizontalEdge(std::shared_ptr<Chunk> a, std::shared_pt
auto lightA = a->getLight(Space::Block::index(aPos), 3);
auto lightB = b->getLight(Space::Block::index(bPos), 3);
if (lightA > lightB + 1) setAndReflowSunlight(b->pos * 16 + bPos, lightA - 1);
else if (lightB > lightA + 1) setAndReflowSunlight(a->pos * 16 + aPos, lightB - 1);
if (lightA > lightB + 1) setAndReflowSunlight(b->getPos() * 16 + bPos, lightA - 1);
else if (lightB > lightA + 1) setAndReflowSunlight(a->getPos() * 16 + aPos, lightB - 1);
}
}
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;
@ -205,7 +200,7 @@ void Dimension::calculateVerticalEdge(std::shared_ptr<Chunk> above, std::shared_
auto lightAbove = above->getLight(Space::Block::index({xx, 0, zz}), 3);
auto lightBelow = below->getLight(Space::Block::index({xx, 15, zz}), 3);
if (lightBelow > lightAbove) removeSunlight(below->pos * 16 + glm::ivec3{xx, 15, zz});
if (lightBelow > lightAbove) removeSunlight(below->getPos() * 16 + glm::ivec3{xx, 15, zz});
}
}
@ -217,6 +212,7 @@ void Dimension::addBlockLight(glm::ivec3 pos, glm::ivec3 light) {
startChunk->setLight(ind, 1, light.y);
startChunk->setLight(ind, 2, light.z);
auto l = getWriteLock();
lightAddQueue[0].emplace(ind, startChunk.get());
lightAddQueue[1].emplace(ind, startChunk.get());
lightAddQueue[2].emplace(ind, startChunk.get());
@ -231,6 +227,7 @@ void Dimension::removeBlockLight(glm::ivec3 pos) {
startChunk->setLight(ind, 1, 0);
startChunk->setLight(ind, 2, 0);
auto l = getWriteLock();
lightRemoveQueue[0].emplace(ind, val.x, startChunk.get());
lightRemoveQueue[1].emplace(ind, val.y, startChunk.get());
lightRemoveQueue[2].emplace(ind, val.z, startChunk.get());
@ -255,6 +252,7 @@ void Dimension::reflowLight(glm::ivec3 pos) {
chunk->setLight(ind, placeLight);
auto l = getWriteLock();
lightAddQueue[0].emplace(ind, chunk.get());
lightAddQueue[1].emplace(ind, chunk.get());
lightAddQueue[2].emplace(ind, chunk.get());
@ -267,6 +265,7 @@ void Dimension::removeSunlight(glm::ivec3 pos) {
unsigned int light = chunk->getLight(ind, 3);
chunk->setLight(ind, 3, 0);
auto l = getWriteLock();
lightRemoveQueue[SUNLIGHT_CHANNEL].emplace(ind, light, chunk.get());
}
@ -275,5 +274,6 @@ void Dimension::setAndReflowSunlight(glm::ivec3 pos, unsigned char level) {
unsigned int ind = Space::Block::index(pos);
chunk->setLight(ind, 3, level);
auto l = getWriteLock();
lightAddQueue[SUNLIGHT_CHANNEL].emplace(ind, chunk.get());
}

View File

@ -35,7 +35,7 @@ public:
// Calculate light propogation around MapBlock edges,
// Called after a new mapblock is inserted into the dimension.
relitChunks calculateEdgeLight(glm::ivec3 mbPos);
// relitChunks calculateEdgeLight(glm::ivec3 mbPos);
protected:
// Lighting propagation.

View File

@ -26,19 +26,21 @@ void DimensionBase::update(double delta) {
updateBlockDamage(delta);
}
std::shared_ptr<Region> DimensionBase::getRegion(glm::ivec3 regionPosition) {
std::shared_ptr<Region> DimensionBase::getRegion(glm::ivec3 regionPosition) const {
auto l = getReadLock();
if (!regions.count(regionPosition)) return nullptr;
return regions[regionPosition];
return regions.at(regionPosition);
}
void DimensionBase::removeRegion(glm::ivec3 pos) {
auto l = getWriteLock();
regions.erase(pos);
}
std::shared_ptr<MapBlock> DimensionBase::getMapBlock(glm::ivec3 mapBlockPosition) {
std::shared_ptr<MapBlock> DimensionBase::getMapBlock(glm::ivec3 mapBlockPosition) const {
auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
if (!region) return nullptr;
return (*region)[Space::MapBlock::index(mapBlockPosition)];
return region->get(Space::MapBlock::index(mapBlockPosition));
}
void DimensionBase::removeMapBlock(glm::ivec3 pos) {
@ -54,15 +56,15 @@ bool DimensionBase::mapBlockGenerated(glm::ivec3 mapBlockPosition) {
return mb && mb->generated;
}
std::shared_ptr<Chunk> DimensionBase::getChunk(glm::ivec3 chunkPosition) {
std::shared_ptr<Chunk> DimensionBase::getChunk(glm::ivec3 chunkPosition) const {
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition));
if (!mapBlock) return nullptr;
return (*mapBlock)[Space::Chunk::index(chunkPosition)];
return mapBlock->get(Space::Chunk::index(chunkPosition));
}
void DimensionBase::setChunk(std::shared_ptr<Chunk> chunk) {
auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->pos));
mapBlock->set(Space::Chunk::index(chunk->pos), chunk);
auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->getPos()));
mapBlock->set(Space::Chunk::index(chunk->getPos()), chunk);
}
void DimensionBase::removeChunk(glm::ivec3 pos){
@ -73,10 +75,9 @@ void DimensionBase::removeChunk(glm::ivec3 pos){
if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos));
}
unsigned int DimensionBase::getBlock(glm::ivec3 pos) {
unsigned int DimensionBase::getBlock(glm::ivec3 pos) const {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return 0;
auto l = chunk->aquireLock();
return chunk->getBlock(Space::Block::relative::toChunk(pos));
}
@ -84,38 +85,30 @@ unsigned int DimensionBase::getBlock(glm::ivec3 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();
return chunk->setBlock(Space::Block::relative::toChunk(pos), block);
}
double DimensionBase::getBlockDamage(glm::ivec3 pos) const {
double damage = blockDamages.count(pos) ? blockDamages.at(pos).curr : 0;
std::cout << damage << std::endl;
return damage;
auto l = getReadLock();
return blockDamages.count(pos) ? blockDamages.at(pos).curr : 0;
}
double DimensionBase::setBlockDamage(glm::ivec3 pos, double damage) {
if (blockDamages.count(pos)) blockDamages[pos].curr = damage;
else blockDamages.insert({pos, Damage { damage, static_cast<double>(game->getDefs().blockFromId(getBlock(pos)).health)}});
else {
double health = game->getDefs().blockFromId(getBlock(pos)).health;
auto l = getWriteLock();
blockDamages.insert({pos, Damage { damage, health }});
}
return getBlockDamage(pos);
// double totalDamage = World::setBlockDamage(pos, damage);
// BlockCrackEntity* block = nullptr;
// if (crackEntities.count(pos)) block = crackEntities[pos];
// else block = new BlockCrackEntity(game.defs->blockFromId(getBlock(pos)), game.textures, pos);
// block->setDamage(damage);
// block->time = 0;
//
// return totalDamage;
}
unsigned int DimensionBase::getBiome(glm::ivec3 pos) {
unsigned int DimensionBase::getBiome(glm::ivec3 pos) const {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return 0;
auto l = chunk->aquireLock();
return chunk->getBiome(Space::Block::relative::toChunk(pos));
}
@ -123,12 +116,12 @@ unsigned int DimensionBase::getBiome(glm::ivec3 pos) {
bool DimensionBase::setBiome(glm::ivec3 pos, unsigned int biome) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return false;
auto l = chunk->aquireLock();
return chunk->setBiome(Space::Block::relative::toChunk(pos), biome);
}
std::shared_ptr<Region> DimensionBase::getOrCreateRegion(glm::ivec3 pos) {
auto l = getWriteLock();
if (regions[pos]) return regions[pos];
regions[pos] = std::make_shared<Region>(pos);
return regions[pos];
@ -138,9 +131,9 @@ std::shared_ptr<MapBlock> DimensionBase::getOrCreateMapBlock(glm::ivec3 mapBlock
auto region = getOrCreateRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
unsigned int index = Space::MapBlock::index(mapBlockPosition);
if ((*region)[index] != nullptr) return (*region)[index];
if (region->get(index) != nullptr) return region->get(index);
region->set(index, std::make_shared<MapBlock>(mapBlockPosition));
return (*region)[index];
return region->get(index);
}
SubgamePtr DimensionBase::getGame() {
@ -151,22 +144,21 @@ World& DimensionBase::getWorld() {
return world;
}
void DimensionBase::updateBlockDamage(double delta) {
for (auto it = blockDamages.begin(); it != blockDamages.end();) {
if (it->second.curr > it->second.max) {
setBlock(it->first, DefinitionAtlas::AIR);
it = blockDamages.erase(it);
}
else it++;
}
// for (auto it = blockDamages.begin(); it != blockDamages.end();) {
// if (it->second.curr > it->second.max) {
// setBlock(it->first, DefinitionAtlas::AIR);
// it = blockDamages.erase(it);
// }
// else it++;
// }
}
std::shared_ptr<Chunk> DimensionBase::combinePartials(std::shared_ptr<Chunk> a, std::shared_ptr<Chunk> b) {
std::shared_ptr<Chunk> src;
std::shared_ptr<Chunk> res;
if (a->generated) {
if (a->isGenerated()) {
res = a;
src = b;
}
@ -179,8 +171,8 @@ std::shared_ptr<Chunk> DimensionBase::combinePartials(std::shared_ptr<Chunk> a,
if (src->getBlock(i) > DefinitionAtlas::INVALID) res->setBlock(i, src->getBlock(i));
}
res->generated = src->generated || res->generated;
res->partial = !res->generated;
res->setGenerated(src->isGenerated() || res->isGenerated());
res->setPartial(!res->isGenerated());
res->countRenderableBlocks();
return res;
}

View File

@ -9,6 +9,7 @@
#include <unordered_map>
#include "../util/Vec.h"
#include "../util/Lockable.h"
#include "../util/CovariantPtr.h"
class World;
@ -18,7 +19,7 @@ class Subgame;
class MapBlock;
class DefinitionAtlas;
class DimensionBase {
class DimensionBase : protected Lockable {
public:
DimensionBase(SubgamePtr game, World& world, const std::string& identifier, unsigned int ind);
@ -27,25 +28,25 @@ public:
virtual void update(double delta);
std::shared_ptr<Region> getRegion(glm::ivec3 regionPosition);
std::shared_ptr<Region> getRegion(glm::ivec3 regionPosition) const;
void removeRegion(glm::ivec3 pos);
std::shared_ptr<MapBlock> getMapBlock(glm::ivec3 mapBlockPosition);
std::shared_ptr<MapBlock> getMapBlock(glm::ivec3 mapBlockPosition) const;
virtual void removeMapBlock(glm::ivec3 pos);
bool mapBlockGenerated(glm::ivec3 mapBlockPosition);
std::shared_ptr<Chunk> getChunk(glm::ivec3 chunkPosition);
std::shared_ptr<Chunk> getChunk(glm::ivec3 chunkPosition) const;
virtual void setChunk(std::shared_ptr<Chunk> chunk);
virtual void removeChunk(glm::ivec3 pos);
unsigned int getBlock(glm::ivec3 pos);
unsigned int getBlock(glm::ivec3 pos) const;
virtual bool setBlock(glm::ivec3 pos, unsigned int block);
virtual double getBlockDamage(glm::ivec3 pos) const;
virtual double setBlockDamage(glm::ivec3 pos, double damage);
unsigned int getBiome(glm::ivec3 pos);
unsigned int getBiome(glm::ivec3 pos) const;
virtual bool setBiome(glm::ivec3 pos, unsigned int biome);
SubgamePtr getGame();

View File

@ -34,7 +34,7 @@ void LocalDimension::update(double delta) {
for (auto it = regions.cbegin(); it != regions.cend();) {
bool remove = false;
for (unsigned short m = 0; m < 64; m++) {
auto mapBlock = it->second->operator[](m);
auto mapBlock = it->second->get(m);
if (!mapBlock) continue;
if (abs(clientMapBlock.x - mapBlock->pos.x) > LocalDimension::MB_STORE_H + 1
@ -42,14 +42,15 @@ void LocalDimension::update(double delta) {
|| abs(clientMapBlock.z - mapBlock->pos.z) > LocalDimension::MB_STORE_H + 1) {
for (unsigned short c = 0; c < 64; c++) {
auto chunk = mapBlock->operator[](c);
auto chunk = mapBlock->get(c);
if (!chunk) continue;
removeMeshChunk(chunk->pos);
removeMeshChunk(chunk->getPos());
}
it->second->remove(m);
if (it->second->count <= 0) {
remove = true;
auto l = getWriteLock();
it = regions.erase(it);
break;
}
@ -71,17 +72,18 @@ bool LocalDimension::setBlock(glm::ivec3 pos, unsigned int block) {
auto chunkPos = Space::Chunk::world::fromBlock(pos);
auto chunk = getChunk(chunkPos);
chunk->dirty = true;
chunk->setDirty(true);
auto lp = Space::Block::relative::toChunk(pos);
auto cp = Space::Chunk::world::fromBlock(pos);
if (lp.x == 15 && getChunk(cp + glm::ivec3 {1, 0, 0})) getChunk(cp + glm::ivec3 {1, 0, 0})->dirty = true;
else if (lp.x == 0 && getChunk(cp + glm::ivec3 {-1, 0, 0})) getChunk(cp + glm::ivec3 {-1, 0, 0})->dirty = true;
if (lp.y == 15 && getChunk(cp + glm::ivec3 {0, 1, 0})) getChunk(cp + glm::ivec3 {0, 1, 0})->dirty = true;
else if (lp.y == 0 && getChunk(cp + glm::ivec3 {0, -1, 0})) getChunk(cp + glm::ivec3 {0, -1, 0})->dirty = true;
if (lp.z == 15 && getChunk(cp + glm::ivec3 {0, 0, 1})) getChunk(cp + glm::ivec3 {0, 0, 1})->dirty = true;
else if (lp.z == 0 && getChunk(cp + glm::ivec3 {0, 0, -1})) getChunk(cp + glm::ivec3 {0, 0, -1})->dirty = true;
std::shared_ptr<Chunk> tempChunk;
if (lp.x == 15 && (tempChunk = getChunk(cp + glm::ivec3 {1, 0, 0}))) tempChunk->setDirty(true);
else if (lp.x == 0 && (tempChunk = getChunk(cp + glm::ivec3 {-1, 0, 0}))) tempChunk->setDirty(true);
if (lp.y == 15 && (tempChunk = getChunk(cp + glm::ivec3 {0, 1, 0}))) tempChunk->setDirty(true);
else if (lp.y == 0 && (tempChunk = getChunk(cp + glm::ivec3 {0, -1, 0}))) tempChunk->setDirty(true);
if (lp.z == 15 && (tempChunk = getChunk(cp + glm::ivec3 {0, 0, 1}))) tempChunk->setDirty(true);
else if (lp.z == 0 && (tempChunk = getChunk(cp + glm::ivec3 {0, 0, -1}))) tempChunk->setDirty(true);
attemptMeshChunk(chunk, true);
return true;
@ -254,7 +256,6 @@ void LocalDimension::finishMeshes() {
auto finishedMeshes = meshGenStream->update();
for (ChunkMeshDetails* meshDetails : finishedMeshes) {
if (!meshDetails->vertices.empty()) {
auto meshChunk = std::make_shared<MeshChunk>();
meshChunk->create(meshDetails->vertices, meshDetails->indices);
@ -270,21 +271,15 @@ void LocalDimension::finishMeshes() {
}
void LocalDimension::attemptMeshChunk(const std::shared_ptr<Chunk>& chunk, bool priority, bool updateAdjacents) {
static const std::vector<glm::ivec3> dirs {
glm::ivec3 {1, 0, 0}, glm::ivec3 {-1, 0, 0},
glm::ivec3 {0, 1, 0}, glm::ivec3 {0, -1, 0},
glm::ivec3 {0, 0, 1}, glm::ivec3 {0, 0, -1}};
bool renderable = true;
for (auto dir : dirs) if (!getAdjacentExists(chunk->pos + dir, updateAdjacents)) renderable = false;
for (auto dir : Vec::TO_VEC) if (!getAdjacentExists(chunk->getPos() + dir, updateAdjacents)) renderable = false;
if (!renderable) return;
if (!chunk->dirty) return;
if (!chunk->shouldRender) removeMeshChunk(chunk->pos);
if (!chunk->isDirty()) return;
if (!chunk->chunkShouldRender()) removeMeshChunk(chunk->getPos());
meshGenStream->queue(chunk->pos, priority);
chunk->dirty = false;
meshGenStream->queue(chunk->getPos(), priority);
chunk->setDirty(false);
}
bool LocalDimension::getAdjacentExists(glm::vec3 pos, bool updateAdjacents) {

View File

@ -45,13 +45,6 @@ void ServerDimension::update(double delta) {
// }
}
bool ServerDimension::setBlock(glm::ivec3 pos, unsigned int block) {
bool manip = Dimension::setBlock(pos, block);
if (!manip) return false;
glm::vec3 mb = Space::MapBlock::world::fromBlock(pos);
return true;
}
double ServerDimension::blockHit(const Target &target, PlayerPtr player) {
double timeout = 0, damage = 0;
sol::tie(damage, timeout) = game->getParser().safe_function(game->getParser().core["block_hit"],
@ -88,11 +81,9 @@ void ServerDimension::blockPlaceOrInteract(const Target &target, PlayerPtr playe
}
void ServerDimension::setChunk(std::shared_ptr<Chunk> chunk) {
std::shared_ptr<Chunk> existing = getChunk(chunk->pos);
std::shared_ptr<Chunk> existing = getChunk(chunk->getPos());
if (existing != nullptr) chunk = combinePartials(chunk, existing);
Dimension::setChunk(chunk);
glm::vec3 mb = Space::MapBlock::world::fromChunk(chunk->pos);
}
void ServerDimension::addLuaEntity(Api::Usertype::Entity entity) {

View File

@ -21,7 +21,6 @@ public:
virtual void update(double delta) override;
void setChunk(std::shared_ptr<Chunk> chunk) override;
bool setBlock(glm::ivec3 pos, unsigned int block) override;
virtual void blockPlace(const Target &target, PlayerPtr player) override;
virtual void blockPlaceOrInteract(const Target &target, PlayerPtr player) override;

View File

@ -5,14 +5,13 @@
#include <gzip/compress.hpp>
#include <gzip/decompress.hpp>
#include <gzip/utils.hpp>
#include <iostream>
#include "Chunk.h"
#include "../../def/DefinitionAtlas.h"
#include "../../util/Util.h"
#include "../../net/Serializer.h"
#include "../../net/Deserializer.h"
#include "../../util/Util.h"
#include "../../def/DefinitionAtlas.h"
Chunk::Chunk(const Chunk& o) :
pos(o.pos),
@ -35,12 +34,16 @@ Chunk::Chunk(glm::ivec3 pos, const std::vector<unsigned int>& blocks, const std:
}
bool Chunk::setBlock(unsigned int ind, unsigned int blk) {
auto l = getWriteLock();
if (!RIE::write(ind, blk, blocks, 4096)) return false;
l.unlock();
if (blk == DefinitionAtlas::AIR && !(renderableBlocks = std::max(renderableBlocks - 1, 0))) shouldRender = false;
else if (blk != DefinitionAtlas::AIR && getBlock(ind) == DefinitionAtlas::AIR) {
else if (blk != DefinitionAtlas::AIR) {
shouldRender = true;
renderableBlocks++;
}
return true;
}
@ -53,6 +56,8 @@ const std::vector<unsigned short> &Chunk::cGetBiomes() const {
}
std::string Chunk::serialize() {
auto l = getReadLock();
std::vector<unsigned short> blockLight = std::vector<unsigned short>(4096);
std::vector<unsigned char> sunLight = std::vector<unsigned char>(2048);
@ -68,6 +73,8 @@ std::string Chunk::serialize() {
sunLight[i] = sl.ch;
}
l.unlock();
Serializer s;
std::string temp = Serializer().append(pos).append(blocks).append(biomes).append(blockLight).append(sunLight).data;
s.append<std::string>(gzip::compress(temp.data(), temp.size()));
@ -76,6 +83,8 @@ std::string Chunk::serialize() {
}
void Chunk::deserialize(Deserializer& d) {
auto l = getWriteLock();
std::string gzipped = d.read<std::string>();
if (!gzip::is_compressed(gzipped.data(), gzipped.length())) throw std::runtime_error("Chunk contains invalid gzipped data.");
@ -100,10 +109,13 @@ void Chunk::deserialize(Deserializer& d) {
this->sunLight[i] = sl.s;
}
l.unlock();
countRenderableBlocks();
}
void Chunk::countRenderableBlocks() {
auto l = getReadLock();
shouldRender = false;
renderableBlocks = 0;

View File

@ -10,12 +10,14 @@
#include <vector>
#include <glm/vec3.hpp>
#include "../../util/Lockable.h"
#include "../../util/RIE.h"
#include "../../util/Space.h"
class Deserializer;
class Chunk {
class Chunk : public Lockable {
public:
friend class MapGen;
@ -39,7 +41,20 @@ public:
Chunk(glm::ivec3 pos, bool partial = false);
Chunk(glm::ivec3 pos, const std::vector<unsigned int>& blocks, const std::vector<unsigned short>& biomes);
inline std::unique_lock<std::mutex> aquireLock();
inline glm::ivec3 getPos() const;
inline void setPos(glm::ivec3 pos);
inline bool isDirty() const;
inline void setDirty(bool dirty);
inline bool chunkShouldRender() const;
inline void setShouldRender(bool shouldRender);
inline bool isPartial() const;
inline void setPartial(bool partial);
inline bool isGenerated() const;
inline void setGenerated(bool generated);
inline unsigned int getBlock(unsigned int ind) const;
bool setBlock(unsigned int ind, unsigned int blk);
@ -66,6 +81,8 @@ public:
void deserialize(Deserializer& d);
void countRenderableBlocks();
private:
glm::ivec3 pos {};
bool partial = false;
bool generated = false;
@ -73,10 +90,6 @@ public:
bool dirty = true;
bool shouldRender = true;
glm::ivec3 pos {};
private:
std::mutex m;
std::vector<unsigned int> blocks {0, 0};
std::vector<unsigned short> biomes {0, 0};
@ -89,76 +102,4 @@ 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));
}
inline bool Chunk::setBlock(const glm::ivec3& pos, unsigned int blk) {
if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false;
return setBlock(Space::Block::index(pos), blk);
}
inline unsigned int Chunk::getBlock(unsigned int ind) const {
if (ind >= 4096) return 0; // Invalid
return RIE::read<unsigned int>(ind, blocks, 4096);
}
inline unsigned short Chunk::getBiome(unsigned int ind) const {
if (ind >= 4096) return 0; // Invalid
return RIE::read<unsigned short>(ind, biomes, 4096);
}
inline bool Chunk::setBiome(unsigned int ind, unsigned short bio) {
return RIE::write(ind, bio, biomes, 4096);
}
inline unsigned short Chunk::getBiome(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 getBiome(Space::Block::index(pos));
}
inline bool Chunk::setBiome(const glm::ivec3& pos, unsigned short bio) {
if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false;
return setBiome(Space::Block::index(pos), bio);
}
inline glm::ivec4 Chunk::getLight(unsigned int ind) {
return { blockLight[ind].r, blockLight[ind].g, blockLight[ind].b, getSunlight(ind) };
}
inline void Chunk::setLight(unsigned int ind, glm::ivec4 l) {
blockLight[ind].r = l.x;
blockLight[ind].g = l.y;
blockLight[ind].b = l.z;
setSunlight(ind, l.w);
}
inline unsigned char Chunk::getLight(unsigned int ind, unsigned char channel) {
return channel == 0 ? blockLight[ind].r :
channel == 1 ? blockLight[ind].g :
channel == 2 ? blockLight[ind].b :
getSunlight(ind);
}
inline void Chunk::setLight(unsigned int ind, unsigned char channel, unsigned char l) {
channel == 0 ? blockLight[ind].r = l :
channel == 1 ? blockLight[ind].g = l :
channel == 2 ? blockLight[ind].b = l :
(setSunlight(ind,l), 0);
}
inline unsigned char Chunk::getSunlight(unsigned int ind) {
if (ind % 2 == 0) return sunLight[ind / 2].a;
else return sunLight[ind / 2].b;
}
inline void Chunk::setSunlight(unsigned int ind, unsigned char val) {
if (ind % 2 == 0) sunLight[ind / 2].a = val;
else sunLight[ind / 2].b = val;
}
#include "Chunk.inl"

128
src/world/chunk/Chunk.inl Normal file
View File

@ -0,0 +1,128 @@
glm::ivec3 Chunk::getPos() const {
auto l = getReadLock();
return pos;
}
void Chunk::setPos(glm::ivec3 pos) {
auto l = getWriteLock();
this->pos = pos;
}
bool Chunk::isDirty() const {
auto l = getReadLock();
return dirty;
}
void Chunk::setDirty(bool dirty) {
auto l = getWriteLock();
this->dirty = dirty;
}
bool Chunk::chunkShouldRender() const {
auto l = getReadLock();
return shouldRender;
}
void Chunk::setShouldRender(bool shouldRender) {
auto l = getWriteLock();
this->shouldRender = shouldRender;
}
bool Chunk::isPartial() const {
auto l = getReadLock();
return partial;
}
void Chunk::setPartial(bool partial) {
auto l = getWriteLock();
this->partial = partial;
};
bool Chunk::isGenerated() const {
auto l = getReadLock();
return generated;
}
void Chunk::setGenerated(bool generated) {
auto l = getWriteLock();
this->generated = generated;
}
inline unsigned int Chunk::getBlock(unsigned int ind) const {
auto l = getReadLock();
if (ind >= 4096) return 0; // Invalid
return RIE::read<unsigned int>(ind, blocks, 4096);
}
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));
}
inline bool Chunk::setBlock(const glm::ivec3& pos, unsigned int blk) {
if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false;
return setBlock(Space::Block::index(pos), blk);
}
inline unsigned short Chunk::getBiome(unsigned int ind) const {
auto l = getReadLock();
if (ind >= 4096) return 0; // Invalid
return RIE::read<unsigned short>(ind, biomes, 4096);
}
inline unsigned short Chunk::getBiome(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 getBiome(Space::Block::index(pos));
}
inline bool Chunk::setBiome(unsigned int ind, unsigned short bio) {
auto l = getWriteLock();
return RIE::write(ind, bio, biomes, 4096);
}
inline bool Chunk::setBiome(const glm::ivec3& pos, unsigned short bio) {
if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false;
return setBiome(Space::Block::index(pos), bio);
}
inline glm::ivec4 Chunk::getLight(unsigned int ind) {
auto l = getReadLock();
return { blockLight[ind].r, blockLight[ind].g, blockLight[ind].b, getSunlight(ind) };
}
inline void Chunk::setLight(unsigned int ind, glm::ivec4 light) {
auto l = getWriteLock();
blockLight[ind].r = light.x;
blockLight[ind].g = light.y;
blockLight[ind].b = light.z;
l.unlock();
setSunlight(ind, light.w);
}
inline unsigned char Chunk::getLight(unsigned int ind, unsigned char channel) {
auto l = getReadLock();
return channel == 0 ? blockLight[ind].r :
channel == 1 ? blockLight[ind].g :
channel == 2 ? blockLight[ind].b :
(l.unlock(), getSunlight(ind));
}
inline void Chunk::setLight(unsigned int ind, unsigned char channel, unsigned char light) {
auto l = getWriteLock();
channel == 0 ? blockLight[ind].r = light :
channel == 1 ? blockLight[ind].g = light :
channel == 2 ? blockLight[ind].b = light :
(l.unlock(), setSunlight(ind,light), 0);
}
inline unsigned char Chunk::getSunlight(unsigned int ind) {
auto l = getReadLock();
if (ind % 2 == 0) return sunLight[ind / 2].a;
else return sunLight[ind / 2].b;
}
inline void Chunk::setSunlight(unsigned int ind, unsigned char val) {
auto l = getWriteLock();
if (ind % 2 == 0) sunLight[ind / 2].a = val;
else sunLight[ind / 2].b = val;
}

View File

@ -19,16 +19,19 @@ MapBlock::MapBlock(glm::ivec3 pos) :
for(unsigned short i = 0; i < 64; i++) chunks[i] = nullptr;
}
std::shared_ptr<Chunk> MapBlock::operator[](unsigned short index) {
std::shared_ptr<Chunk> MapBlock::get(unsigned short index) const {
auto l = getReadLock();
return chunks[index];
}
void MapBlock::set(unsigned short index, std::shared_ptr<Chunk> chunk) {
auto l = getWriteLock();
if (chunks[index] == nullptr) count++;
chunks[index] = chunk;
}
void MapBlock::remove(unsigned short index) {
auto l = getWriteLock();
if (chunks[index] != nullptr) count--;
chunks[index] = nullptr;
}

View File

@ -10,14 +10,16 @@
#include <vector>
#include <glm/vec3.hpp>
#include "../../util/Lockable.h"
class Chunk;
class Deserializer;
class MapBlock {
class MapBlock : Lockable {
public:
MapBlock(glm::ivec3 pos);
std::shared_ptr<Chunk> operator[](unsigned short index);
std::shared_ptr<Chunk> get(unsigned short index) const;
void set(unsigned short index, std::shared_ptr<Chunk> chunk);
void remove(unsigned short index);

View File

@ -11,16 +11,19 @@ Region::Region(glm::ivec3 pos) :
for(unsigned short i = 0; i < 64; i++) mapBlocks[i] = nullptr;
}
std::shared_ptr<MapBlock> Region::operator[](unsigned short index) {
std::shared_ptr<MapBlock> Region::get(unsigned short index) const {
auto l = getReadLock();
return mapBlocks[index];
}
void Region::set(unsigned short index, std::shared_ptr<MapBlock> block) {
auto l = getWriteLock();
if (mapBlocks[index] == nullptr) count++;
mapBlocks[index] = block;
}
void Region::remove(unsigned short index) {
auto l = getWriteLock();
if (mapBlocks[index] != nullptr) count--;
mapBlocks[index] = nullptr;
}

View File

@ -9,13 +9,15 @@
#include <memory>
#include <glm/vec3.hpp>
#include "../../util/Lockable.h"
class MapBlock;
class Region {
class Region : Lockable {
public:
Region(glm::ivec3 pos);
std::shared_ptr<MapBlock> operator[](unsigned short index);
std::shared_ptr<MapBlock> get(unsigned short index) const;
void set(unsigned short index, std::shared_ptr<MapBlock> block);
void remove(unsigned short index);

View File

@ -25,8 +25,8 @@ FileManipulator::FileManipulator(const std::string &worldPath) :
}
void FileManipulator::commitChunk(Chunk &chunk) {
glm::ivec3 reg = Space::Region::world::fromChunk(chunk.pos);
unsigned int chunkInd = Space::Chunk::index(chunk.pos);
glm::ivec3 reg = Space::Region::world::fromChunk(chunk.getPos());
unsigned int chunkInd = Space::Chunk::index(chunk.getPos());
std::string fileName = std::to_string(reg.x) + "_" + std::to_string(reg.y) + "_" + std::to_string(reg.z);
std::string filePath = path + "/" + fileName;

View File

@ -1,7 +1,7 @@
zepha.register_entity("zeus:default:bee", {
display = "model",
display_object = "zeus:default:bee",
display_texture = "zeus:default:bee",
display_texture = "zeus:default:bee_shiny",
on_create = function(self)
self.object.scale = 1/12
@ -21,7 +21,5 @@ zepha.register_entity("zeus:default:bee", {
zepha.register_keybind("zeus:default:spawn_bee", {
description = "Spawn Bee",
default = zepha.keys.b,
on_press = function()
zepha.add_entity("zeus:default:bee", vector.add(zepha.player.pos, V(0, 1.7, 0)))
end
on_press = function() zepha.player.dim:add_entity(zepha.player.pos + V(0, 1.7, 0), "zeus:default:bee") end
})

View File

@ -57,9 +57,7 @@ zepha.register_entity("zeus:default:rabbit", {
zepha.register_keybind("zeus:default:spawn_rabbit", {
description = "Spawn Rabbit",
default = zepha.keys.y,
on_press = function()
zepha.add_entity(zepha.player.pos, "zeus:default:rabbit")
end
on_press = function() zepha.player.dim:add_entity(zepha.player.pos, "zeus:default:rabbit") end
})
zepha.register_keybind("zeus:default:change_rabbit_behavior", {

View File

@ -43,6 +43,6 @@ zepha.register_keybind("zeus:default:spawn_raven", {
description = "Spawn Raven",
default = zepha.keys.z,
on_press = function()
zepha.add_entity("zeus:default:raven", vector.add(zepha.player.pos, V{0, 1.7, 0}))
zepha.player.dim:add_entity(zepha.player.pos + V(0, 1.7, 0), "zeus:default:raven")
end
})

View File

@ -8,12 +8,12 @@ zepha.register_entity("zeus:default:test", {
walk = {0, 300}
})
self.object.anims:set_anim("walk"):play()
self.object.scale = 1/4
-- self.object.scale = 1/4
end,
on_update = function(self, delta)
self.object.pos = self.object.pos +
V(0.6 * math.sin(math.rad(self.object.yaw)), 0, 0.6 * math.cos(math.rad(self.object.yaw))) * delta
self.object.yaw = self.object.yaw + 50 * delta
-- self.object.pos = self.object.pos +
-- V(0.6 * math.sin(math.rad(self.object.yaw)), 0, 0.6 * math.cos(math.rad(self.object.yaw))) * delta
-- self.object.yaw = self.object.yaw + 50 * delta
end
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 856 B

After

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 975 B

After

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB