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
|
@ -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>
|
|
@ -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)
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <string>
|
||||
|
||||
struct AnimationSegment {
|
||||
std::string animationName;
|
||||
unsigned int startFrame;
|
||||
unsigned int endFrame;
|
||||
std::string name;
|
||||
glm::ivec2 range;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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());
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
})
|
|
@ -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", {
|
||||
|
|
|
@ -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
|
||||
})
|
|
@ -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
|
||||
})
|
||||
|
||||
|
|
Before Width: | Height: | Size: 856 B After Width: | Height: | Size: 849 B |
After Width: | Height: | Size: 774 B |
Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 683 B |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 975 B After Width: | Height: | Size: 759 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.1 KiB |