Merge pull request #213 from MihailRis/block_states_to_bitfield
Converting block states to a bitfield + user bits related bug fixes
This commit is contained in:
commit
e082b4f3b5
@ -374,7 +374,7 @@ void WorldRegions::put(Chunk* chunk){
|
||||
chunk->encode(), CHUNK_DATA_LEN, true);
|
||||
|
||||
// Writing lights cache
|
||||
if (doWriteLights && chunk->isLighted()) {
|
||||
if (doWriteLights && chunk->flags.lighted) {
|
||||
put(chunk->x, chunk->z, REGION_LAYER_LIGHTS,
|
||||
chunk->lightmap.encode(), LIGHTMAP_DATA_LEN, true);
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
|
||||
using namespace gui;
|
||||
|
||||
@ -73,19 +74,25 @@ std::shared_ptr<UINode> create_debug_panel(
|
||||
}));
|
||||
panel->add(create_label([=](){
|
||||
auto* indices = level->content->getIndices();
|
||||
auto def = indices->getBlockDef(player->selectedVoxel.id);
|
||||
std::wstringstream stream;
|
||||
stream << std::hex << player->selectedVoxel.states;
|
||||
if (def) {
|
||||
stream << L" (" << util::str2wstr_utf8(def->name) << L")";
|
||||
}
|
||||
stream << "r:" << player->selectedVoxel.state.rotation << " s:"
|
||||
<< player->selectedVoxel.state.segment << " u:"
|
||||
<< std::bitset<8>(player->selectedVoxel.state.userbits);
|
||||
if (player->selectedVoxel.id == BLOCK_VOID) {
|
||||
return std::wstring {L"block: none"};
|
||||
return std::wstring {L"block: -"};
|
||||
} else {
|
||||
return L"block: "+std::to_wstring(player->selectedVoxel.id)+
|
||||
L" "+stream.str();
|
||||
}
|
||||
}));
|
||||
panel->add(create_label([=](){
|
||||
auto* indices = level->content->getIndices();
|
||||
if (auto def = indices->getBlockDef(player->selectedVoxel.id)) {
|
||||
return L"name: " + util::str2wstr_utf8(def->name);
|
||||
} else {
|
||||
return std::wstring {L"name: void"};
|
||||
}
|
||||
}));
|
||||
panel->add(create_label([=](){
|
||||
return L"seed: "+std::to_wstring(level->getWorld()->getSeed());
|
||||
}));
|
||||
|
||||
@ -333,7 +333,7 @@ void Hud::openInventory(
|
||||
if (blockinv == nullptr) {
|
||||
blockinv = level->inventories->createVirtual(blockUI->getSlotsCount());
|
||||
}
|
||||
level->chunks->getChunkByVoxel(block.x, block.y, block.z)->setUnsaved(true);
|
||||
level->chunks->getChunkByVoxel(block.x, block.y, block.z)->flags.unsaved;
|
||||
blockUI->bind(blockinv, content);
|
||||
blockPos = block;
|
||||
currentblockid = level->chunks->get(block.x, block.y, block.z)->id;
|
||||
|
||||
@ -219,10 +219,13 @@ void BlocksRenderer::blockXSprite(int x, int y, int z,
|
||||
// HINT: texture faces order: {east, west, bottom, top, south, north}
|
||||
|
||||
/* AABB blocks render method */
|
||||
void BlocksRenderer::blockAABB(const ivec3& icoord,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block, ubyte rotation,
|
||||
bool lights) {
|
||||
void BlocksRenderer::blockAABB(
|
||||
const ivec3& icoord,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights
|
||||
) {
|
||||
if (block->hitboxes.empty()) {
|
||||
return;
|
||||
}
|
||||
@ -301,11 +304,13 @@ void BlocksRenderer::blockCustomModel(const ivec3& icoord,
|
||||
}
|
||||
|
||||
/* Fastest solid shaded blocks render method */
|
||||
void BlocksRenderer::blockCube(int x, int y, int z,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block,
|
||||
ubyte states,
|
||||
bool lights) {
|
||||
void BlocksRenderer::blockCube(
|
||||
int x, int y, int z,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block,
|
||||
blockstate states,
|
||||
bool lights
|
||||
) {
|
||||
ubyte group = block->drawGroup;
|
||||
|
||||
vec3 X(1, 0, 0);
|
||||
@ -314,7 +319,7 @@ void BlocksRenderer::blockCube(int x, int y, int z,
|
||||
vec3 coord(x, y, z);
|
||||
if (block->rotatable) {
|
||||
auto& rotations = block->rotations;
|
||||
auto& orient = rotations.variants[states & BLOCK_ROT_MASK];
|
||||
auto& orient = rotations.variants[states.rotation];
|
||||
X = orient.axisX;
|
||||
Y = orient.axisY;
|
||||
Z = orient.axisZ;
|
||||
@ -423,7 +428,7 @@ void BlocksRenderer::render(const voxel* voxels) {
|
||||
int z = (i / CHUNK_D) % CHUNK_W;
|
||||
switch (def.model) {
|
||||
case BlockModel::block:
|
||||
blockCube(x, y, z, texfaces, &def, vox.states, !def.rt.emissive);
|
||||
blockCube(x, y, z, texfaces, &def, vox.state, !def.rt.emissive);
|
||||
break;
|
||||
case BlockModel::xsprite: {
|
||||
blockXSprite(x, y, z, vec3(1.0f),
|
||||
@ -431,11 +436,11 @@ void BlocksRenderer::render(const voxel* voxels) {
|
||||
break;
|
||||
}
|
||||
case BlockModel::aabb: {
|
||||
blockAABB(ivec3(x,y,z), texfaces, &def, vox.rotation(), !def.rt.emissive);
|
||||
blockAABB(ivec3(x,y,z), texfaces, &def, vox.state.rotation, !def.rt.emissive);
|
||||
break;
|
||||
}
|
||||
case BlockModel::custom: {
|
||||
blockCustomModel(ivec3(x, y, z), &def, vox.rotation(), !def.rt.emissive);
|
||||
blockCustomModel(ivec3(x, y, z), &def, vox.state.rotation, !def.rt.emissive);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@ -70,16 +70,33 @@ class BlocksRenderer {
|
||||
const UVRegion& texreg,
|
||||
bool lights);
|
||||
|
||||
void blockCube(int x, int y, int z, const UVRegion(&faces)[6], const Block* block, ubyte states, bool lights);
|
||||
void blockAABB(const glm::ivec3& coord,
|
||||
const UVRegion(&faces)[6],
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights);
|
||||
void blockXSprite(int x, int y, int z, const glm::vec3& size, const UVRegion& face1, const UVRegion& face2, float spread);
|
||||
void blockCustomModel(const glm::ivec3& icoord,
|
||||
const Block* block, ubyte rotation,
|
||||
bool lights);
|
||||
void blockCube(
|
||||
int x, int y, int z,
|
||||
const UVRegion(&faces)[6],
|
||||
const Block* block,
|
||||
blockstate states,
|
||||
bool lights
|
||||
);
|
||||
void blockAABB(
|
||||
const glm::ivec3& coord,
|
||||
const UVRegion(&faces)[6],
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights
|
||||
);
|
||||
void blockXSprite(
|
||||
int x, int y, int z,
|
||||
const glm::vec3& size,
|
||||
const UVRegion& face1,
|
||||
const UVRegion& face2,
|
||||
float spread
|
||||
);
|
||||
void blockCustomModel(
|
||||
const glm::ivec3& icoord,
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights
|
||||
);
|
||||
|
||||
bool isOpenForLight(int x, int y, int z) const;
|
||||
bool isOpen(int x, int y, int z, ubyte group) const;
|
||||
|
||||
@ -56,19 +56,16 @@ ChunksRenderer::~ChunksRenderer() {
|
||||
}
|
||||
|
||||
std::shared_ptr<Mesh> ChunksRenderer::render(std::shared_ptr<Chunk> chunk, bool important) {
|
||||
chunk->setModified(false);
|
||||
|
||||
chunk->flags.modified = false;
|
||||
if (important) {
|
||||
auto mesh = renderer->render(chunk.get(), level->chunksStorage.get());
|
||||
meshes[glm::ivec2(chunk->x, chunk->z)] = mesh;
|
||||
return mesh;
|
||||
}
|
||||
|
||||
glm::ivec2 key(chunk->x, chunk->z);
|
||||
if (inwork.find(key) != inwork.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inwork[key] = true;
|
||||
threadPool.enqueueJob(chunk);
|
||||
return nullptr;
|
||||
@ -86,7 +83,7 @@ std::shared_ptr<Mesh> ChunksRenderer::getOrRender(std::shared_ptr<Chunk> chunk,
|
||||
if (found == meshes.end()) {
|
||||
return render(chunk, important);
|
||||
}
|
||||
if (chunk->isModified()) {
|
||||
if (chunk->flags.modified) {
|
||||
render(chunk, important);
|
||||
}
|
||||
return found->second;
|
||||
|
||||
@ -79,7 +79,7 @@ bool WorldRenderer::drawChunk(
|
||||
bool culling
|
||||
){
|
||||
auto chunk = level->chunks->chunks[index];
|
||||
if (!chunk->isLighted()) {
|
||||
if (!chunk->flags.lighted) {
|
||||
return false;
|
||||
}
|
||||
float distance = glm::distance(
|
||||
|
||||
@ -21,7 +21,7 @@ void LightSolver::add(int x, int y, int z, int emission) {
|
||||
addqueue.push(lightentry {x, y, z, ubyte(emission)});
|
||||
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
chunk->lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, emission);
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ void LightSolver::solve(){
|
||||
if (chunk) {
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
|
||||
ubyte light = chunk->lightmap.get(lx,y,lz, channel);
|
||||
if (light != 0 && light == entry.light-1){
|
||||
@ -96,7 +96,7 @@ void LightSolver::solve(){
|
||||
if (chunk) {
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
|
||||
ubyte light = chunk->lightmap.get(lx, y, lz, channel);
|
||||
voxel& v = chunk->voxels[vox_index(lx, y, lz)];
|
||||
|
||||
@ -71,7 +71,7 @@ void BlocksController::updateSides(int x, int y, int z) {
|
||||
}
|
||||
|
||||
void BlocksController::breakBlock(Player* player, const Block* def, int x, int y, int z) {
|
||||
chunks->set(x,y,z, 0, 0);
|
||||
chunks->set(x,y,z, 0, {});
|
||||
lighting->onBlockSet(x,y,z, 0);
|
||||
if (def->rt.funcsset.onbroken) {
|
||||
scripting::on_block_broken(player, def, x, y, z);
|
||||
@ -132,7 +132,7 @@ void BlocksController::randomTick(int tickid, int parts) {
|
||||
if ((index + tickid) % parts != 0)
|
||||
continue;
|
||||
auto& chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr || !chunk->isLighted())
|
||||
if (chunk == nullptr || !chunk->flags.lighted)
|
||||
continue;
|
||||
for (int s = 0; s < segments; s++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
||||
@ -61,7 +61,7 @@ bool ChunksController::loadVisible(){
|
||||
int index = z * w + x;
|
||||
auto& chunk = chunks->chunks[index];
|
||||
if (chunk != nullptr){
|
||||
if (chunk->isLoaded() && !chunk->isLighted()) {
|
||||
if (chunk->flags.loaded && !chunk->flags.lighted) {
|
||||
if (buildLights(chunk)) {
|
||||
return true;
|
||||
}
|
||||
@ -99,12 +99,12 @@ bool ChunksController::buildLights(std::shared_ptr<Chunk> chunk) {
|
||||
}
|
||||
}
|
||||
if (surrounding == MIN_SURROUNDING) {
|
||||
bool lightsCache = chunk->isLoadedLights();
|
||||
bool lightsCache = chunk->flags.loadedLights;
|
||||
if (!lightsCache) {
|
||||
lighting->buildSkyLight(chunk->x, chunk->z);
|
||||
}
|
||||
lighting->onChunkLoaded(chunk->x, chunk->z, !lightsCache);
|
||||
chunk->setLighted(true);
|
||||
chunk->flags.lighted = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -114,20 +114,20 @@ void ChunksController::createChunk(int x, int z) {
|
||||
auto chunk = level->chunksStorage->create(x, z);
|
||||
chunks->putChunk(chunk);
|
||||
|
||||
if (!chunk->isLoaded()) {
|
||||
if (!chunk->flags.loaded) {
|
||||
generator->generate(
|
||||
chunk->voxels, x, z,
|
||||
level->getWorld()->getSeed()
|
||||
);
|
||||
chunk->setUnsaved(true);
|
||||
chunk->flags.unsaved = true;
|
||||
}
|
||||
chunk->updateHeights();
|
||||
|
||||
if (!chunk->isLoadedLights()) {
|
||||
if (!chunk->flags.loadedLights) {
|
||||
Lighting::prebuildSkyLight(
|
||||
chunk.get(), level->content->getIndices()
|
||||
);
|
||||
}
|
||||
chunk->setLoaded(true);
|
||||
chunk->setReady(true);
|
||||
chunk->flags.loaded = true;
|
||||
chunk->flags.ready = true;
|
||||
}
|
||||
|
||||
@ -364,7 +364,7 @@ void PlayerController::updateInteraction(){
|
||||
if (vox != nullptr) {
|
||||
player->selectedVoxel = *vox;
|
||||
selectedBlockId = vox->id;
|
||||
selectedBlockRotation = vox->rotation();
|
||||
selectedBlockRotation = vox->state.rotation;
|
||||
player->selectedBlockPosition = iend;
|
||||
selectedPointPosition = end;
|
||||
selectedBlockNormal = norm;
|
||||
@ -373,7 +373,8 @@ void PlayerController::updateInteraction(){
|
||||
int z = iend.z;
|
||||
|
||||
Block* def = indices->getBlockDef(item->rt.placingBlock);
|
||||
uint8_t states = determine_rotation(def, norm, camera->dir);
|
||||
blockstate state {};
|
||||
state.rotation = determine_rotation(def, norm, camera->dir);
|
||||
|
||||
if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) {
|
||||
if (scripting::on_item_break_block(player.get(), item, x, y, z))
|
||||
@ -410,13 +411,13 @@ void PlayerController::updateInteraction(){
|
||||
z = (iend.z)+(norm.z);
|
||||
} else {
|
||||
if (def->rotations.name == "pipe") {
|
||||
states = BLOCK_DIR_UP;
|
||||
state.rotation = BLOCK_DIR_UP;
|
||||
}
|
||||
}
|
||||
vox = chunks->get(x, y, z);
|
||||
blockid_t chosenBlock = def->rt.id;
|
||||
if (vox && (target = indices->getBlockDef(vox->id))->replaceable) {
|
||||
if (!level->physics->isBlockInside(x,y,z,def,states, player->hitbox.get())
|
||||
if (!level->physics->isBlockInside(x,y,z,def,state, player->hitbox.get())
|
||||
|| !def->obstacle){
|
||||
if (def->grounded && !chunks->isSolidBlock(x, y-1, z)) {
|
||||
chosenBlock = 0;
|
||||
@ -426,7 +427,7 @@ void PlayerController::updateInteraction(){
|
||||
glm::ivec3(x, y, z), def,
|
||||
BlockInteraction::placing
|
||||
);
|
||||
chunks->set(x, y, z, chosenBlock, states);
|
||||
chunks->set(x, y, z, chosenBlock, state);
|
||||
lighting->onBlockSet(x,y,z, chosenBlock);
|
||||
if (def->rt.funcsset.onplaced) {
|
||||
scripting::on_block_placed(player.get(), def, x, y, z);
|
||||
|
||||
@ -60,7 +60,7 @@ int l_set_block(lua_State* L) {
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
lua_Integer id = lua_tointeger(L, 4);
|
||||
lua_Integer states = lua_tointeger(L, 5);
|
||||
lua_Integer state = lua_tointeger(L, 5);
|
||||
bool noupdate = lua_toboolean(L, 6);
|
||||
if (id < 0 || size_t(id) >= scripting::indices->countBlockDefs()) {
|
||||
return 0;
|
||||
@ -68,7 +68,7 @@ int l_set_block(lua_State* L) {
|
||||
if (!scripting::level->chunks->get(x, y, z)) {
|
||||
return 0;
|
||||
}
|
||||
scripting::level->chunks->set(x, y, z, id, states);
|
||||
scripting::level->chunks->set(x, y, z, id, int2blockstate(state));
|
||||
scripting::level->lighting->onBlockSet(x,y,z, id);
|
||||
if (!noupdate)
|
||||
scripting::blocks->updateSides(x, y, z);
|
||||
@ -97,7 +97,7 @@ int l_get_block_x(lua_State* L) {
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 1, 0, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
const CoordSystem& rot = def->rotations.variants[vox->state.rotation];
|
||||
return lua::pushivec3(L, rot.axisX.x, rot.axisX.y, rot.axisX.z);
|
||||
}
|
||||
}
|
||||
@ -114,7 +114,7 @@ int l_get_block_y(lua_State* L) {
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 0, 1, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
const CoordSystem& rot = def->rotations.variants[vox->state.rotation];
|
||||
return lua::pushivec3(L, rot.axisY.x, rot.axisY.y, rot.axisY.z);
|
||||
}
|
||||
}
|
||||
@ -131,7 +131,7 @@ int l_get_block_z(lua_State* L) {
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 0, 0, 1);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
const CoordSystem& rot = def->rotations.variants[vox->state.rotation];
|
||||
return lua::pushivec3(L, rot.axisZ.x, rot.axisZ.y, rot.axisZ.z);
|
||||
}
|
||||
}
|
||||
@ -141,7 +141,7 @@ int l_get_block_rotation(lua_State* L) {
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int rotation = vox == nullptr ? 0 : vox->rotation();
|
||||
int rotation = vox == nullptr ? 0 : vox->state.rotation;
|
||||
lua_pushinteger(L, rotation);
|
||||
return 1;
|
||||
}
|
||||
@ -155,8 +155,8 @@ int l_set_block_rotation(lua_State* L) {
|
||||
if (vox == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
vox->setRotation(value);
|
||||
scripting::level->chunks->getChunkByVoxel(x, y, z)->setModified(true);
|
||||
vox->state.rotation = value;
|
||||
scripting::level->chunks->getChunkByVoxel(x, y, z)->setModifiedAndUnsaved();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ int l_get_block_states(lua_State* L) {
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int states = vox == nullptr ? 0 : vox->states;
|
||||
int states = vox == nullptr ? 0 : blockstate2int(vox->state);
|
||||
lua_pushinteger(L, states);
|
||||
return 1;
|
||||
}
|
||||
@ -181,8 +181,8 @@ int l_set_block_states(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
vox->states = states;
|
||||
chunk->setModified(true);
|
||||
vox->state = int2blockstate(states);
|
||||
chunk->setModifiedAndUnsaved();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ int l_get_block_user_bits(lua_State* L) {
|
||||
return 1;
|
||||
}
|
||||
uint mask = ((1 << bits) - 1) << offset;
|
||||
uint data = (vox->states & mask) >> offset;
|
||||
uint data = (blockstate2int(vox->state) & mask) >> offset;
|
||||
lua_pushinteger(L, data);
|
||||
return 1;
|
||||
}
|
||||
@ -208,18 +208,23 @@ int l_set_block_user_bits(lua_State* L) {
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
lua_Integer offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
lua_Integer offset = lua_tointeger(L, 4);
|
||||
lua_Integer bits = lua_tointeger(L, 5);
|
||||
|
||||
size_t mask = ((1 << bits) - 1) << offset;
|
||||
lua_Integer value = (lua_tointeger(L, 6) << offset) & mask;
|
||||
|
||||
Chunk* chunk = scripting::level->chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
vox->states = (vox->states & (~mask)) | value;
|
||||
return 0;
|
||||
vox->state.userbits = (vox->state.userbits & (~mask)) | value;
|
||||
chunk->setModifiedAndUnsaved();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_is_replaceable_at(lua_State* L) {
|
||||
|
||||
@ -44,7 +44,7 @@ public:
|
||||
std::shared_ptr<Camera> currentCamera;
|
||||
std::unique_ptr<Hitbox> hitbox;
|
||||
bool debug = false;
|
||||
voxel selectedVoxel {0, 0};
|
||||
voxel selectedVoxel {0, {}};
|
||||
glm::vec3 cam {};
|
||||
glm::ivec3 selectedBlockPosition {};
|
||||
|
||||
|
||||
@ -219,13 +219,11 @@ bool PhysicsSolver::isBlockInside(int x, int y, int z, Hitbox* hitbox) {
|
||||
y >= floor(pos.y-half.y) && y <= floor(pos.y+half.y);
|
||||
}
|
||||
|
||||
bool PhysicsSolver::isBlockInside(int x, int y, int z, Block* def, blockstate_t states, Hitbox* hitbox) {
|
||||
bool PhysicsSolver::isBlockInside(int x, int y, int z, Block* def, blockstate state, Hitbox* hitbox) {
|
||||
const glm::vec3& pos = hitbox->position;
|
||||
const glm::vec3& half = hitbox->halfsize;
|
||||
voxel v {};
|
||||
v.states = states;
|
||||
const auto& boxes = def->rotatable
|
||||
? def->rt.hitboxes[v.rotation()]
|
||||
? def->rt.hitboxes[state.rotation]
|
||||
: def->hitboxes;
|
||||
for (const auto& block_hitbox : boxes) {
|
||||
glm::vec3 min = block_hitbox.min();
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define PHYSICS_PHYSICSSOLVER_HPP_
|
||||
|
||||
#include "../typedefs.hpp"
|
||||
#include "../voxels/voxel.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
@ -31,7 +32,7 @@ public:
|
||||
float stepHeight
|
||||
);
|
||||
bool isBlockInside(int x, int y, int z, Hitbox* hitbox);
|
||||
bool isBlockInside(int x, int y, int z, Block* def, blockstate_t states, Hitbox* hitbox);
|
||||
bool isBlockInside(int x, int y, int z, Block* def, blockstate state, Hitbox* hitbox);
|
||||
};
|
||||
|
||||
#endif // PHYSICS_PHYSICSSOLVER_HPP_
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include "util/platform.hpp"
|
||||
#include "util/command_line.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
@ -13,7 +12,6 @@ static debug::Logger logger("main");
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
debug::Logger::init("latest.log");
|
||||
std::cout << sizeof(PlayerInput) << std::endl;
|
||||
|
||||
EnginePaths paths;
|
||||
if (!parse_cmdline(argc, argv, paths))
|
||||
|
||||
@ -7,56 +7,52 @@
|
||||
#include "../lighting/Lightmap.hpp"
|
||||
|
||||
Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){
|
||||
bottom = 0;
|
||||
top = CHUNK_H;
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
voxels[i].id = 2;
|
||||
voxels[i].states = 0;
|
||||
}
|
||||
bottom = 0;
|
||||
top = CHUNK_H;
|
||||
}
|
||||
|
||||
bool Chunk::isEmpty(){
|
||||
int id = -1;
|
||||
for (uint i = 0; i < CHUNK_VOL; i++){
|
||||
if (voxels[i].id != id){
|
||||
if (id != -1)
|
||||
return false;
|
||||
else
|
||||
id = voxels[i].id;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
int id = -1;
|
||||
for (uint i = 0; i < CHUNK_VOL; i++){
|
||||
if (voxels[i].id != id){
|
||||
if (id != -1)
|
||||
return false;
|
||||
else
|
||||
id = voxels[i].id;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Chunk::updateHeights() {
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
if (voxels[i].id != 0) {
|
||||
bottom = i / (CHUNK_D * CHUNK_W);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = CHUNK_VOL - 1; i >= 0; i--) {
|
||||
if (voxels[i].id != 0) {
|
||||
top = i / (CHUNK_D * CHUNK_W) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
if (voxels[i].id != 0) {
|
||||
bottom = i / (CHUNK_D * CHUNK_W);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = CHUNK_VOL - 1; i >= 0; i--) {
|
||||
if (voxels[i].id != 0) {
|
||||
top = i / (CHUNK_D * CHUNK_W) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Chunk::addBlockInventory(std::shared_ptr<Inventory> inventory,
|
||||
uint x, uint y, uint z) {
|
||||
inventories[vox_index(x, y, z)] = inventory;
|
||||
setUnsaved(true);
|
||||
flags.unsaved = true;
|
||||
}
|
||||
|
||||
void Chunk::removeBlockInventory(uint x, uint y, uint z) {
|
||||
if (inventories.erase(vox_index(x, y, z))) {
|
||||
setUnsaved(true);
|
||||
}
|
||||
if (inventories.erase(vox_index(x, y, z))) {
|
||||
flags.unsaved = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Chunk::setBlockInventories(chunk_inventories_map map) {
|
||||
inventories = map;
|
||||
inventories = map;
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Chunk::getBlockInventory(uint x, uint y, uint z) const {
|
||||
@ -70,12 +66,12 @@ std::shared_ptr<Inventory> Chunk::getBlockInventory(uint x, uint y, uint z) cons
|
||||
}
|
||||
|
||||
std::unique_ptr<Chunk> Chunk::clone() const {
|
||||
auto other = std::make_unique<Chunk>(x,z);
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
other->voxels[i] = voxels[i];
|
||||
auto other = std::make_unique<Chunk>(x,z);
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
other->voxels[i] = voxels[i];
|
||||
}
|
||||
other->lightmap.set(&lightmap);
|
||||
return other;
|
||||
other->lightmap.set(&lightmap);
|
||||
return other;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,19 +89,21 @@ std::unique_ptr<Chunk> Chunk::clone() const {
|
||||
Total size: (CHUNK_VOL * 4) bytes
|
||||
*/
|
||||
std::unique_ptr<ubyte[]> Chunk::encode() const {
|
||||
auto buffer = std::make_unique<ubyte[]>(CHUNK_DATA_LEN);
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
buffer[i] = voxels[i].id >> 8;
|
||||
auto buffer = std::make_unique<ubyte[]>(CHUNK_DATA_LEN);
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
buffer[i] = voxels[i].id >> 8;
|
||||
buffer[CHUNK_VOL+i] = voxels[i].id & 0xFF;
|
||||
buffer[CHUNK_VOL*2 + i] = voxels[i].states >> 8;
|
||||
buffer[CHUNK_VOL*3 + i] = voxels[i].states & 0xFF;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
blockstate_t state = blockstate2int(voxels[i].state);
|
||||
buffer[CHUNK_VOL*2 + i] = state >> 8;
|
||||
buffer[CHUNK_VOL*3 + i] = state & 0xFF;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool Chunk::decode(const ubyte* data) {
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
voxel& vox = voxels[i];
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
voxel& vox = voxels[i];
|
||||
|
||||
ubyte bid1 = data[i];
|
||||
ubyte bid2 = data[CHUNK_VOL + i];
|
||||
@ -113,10 +111,10 @@ bool Chunk::decode(const ubyte* data) {
|
||||
ubyte bst1 = data[CHUNK_VOL*2 + i];
|
||||
ubyte bst2 = data[CHUNK_VOL*3 + i];
|
||||
|
||||
vox.id = (blockid_t(bid1) << 8) | (blockid_t(bid2));
|
||||
vox.states = (blockstate_t(bst1) << 8) | (blockstate_t(bst2));
|
||||
}
|
||||
return true;
|
||||
vox.id = (blockid_t(bid1) << 8) | (blockid_t(bid2));
|
||||
vox.state = int2blockstate((blockstate_t(bst1) << 8) | (blockstate_t(bst2)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Chunk::convert(ubyte* data, const ContentLUT* lut) {
|
||||
|
||||
@ -9,14 +9,6 @@
|
||||
#include "voxel.hpp"
|
||||
#include "../lighting/Lightmap.hpp"
|
||||
|
||||
struct ChunkFlag {
|
||||
static const int MODIFIED = 0x1;
|
||||
static const int READY = 0x2;
|
||||
static const int LOADED = 0x4;
|
||||
static const int LIGHTED = 0x8;
|
||||
static const int UNSAVED = 0x10;
|
||||
static const int LOADED_LIGHTS = 0x20;
|
||||
};
|
||||
inline constexpr int CHUNK_DATA_LEN = CHUNK_VOL*4;
|
||||
|
||||
class Lightmap;
|
||||
@ -27,72 +19,52 @@ using chunk_inventories_map = std::unordered_map<uint, std::shared_ptr<Inventory
|
||||
|
||||
class Chunk {
|
||||
public:
|
||||
int x, z;
|
||||
int bottom, top;
|
||||
voxel voxels[CHUNK_VOL];
|
||||
Lightmap lightmap;
|
||||
int flags = 0;
|
||||
int x, z;
|
||||
int bottom, top;
|
||||
voxel voxels[CHUNK_VOL] {};
|
||||
Lightmap lightmap;
|
||||
struct {
|
||||
bool modified: 1;
|
||||
bool ready: 1;
|
||||
bool loaded: 1;
|
||||
bool lighted: 1;
|
||||
bool unsaved: 1;
|
||||
bool loadedLights: 1;
|
||||
} flags {};
|
||||
|
||||
/* Block inventories map where key is index of block in voxels array */
|
||||
chunk_inventories_map inventories;
|
||||
|
||||
Chunk(int x, int z);
|
||||
Chunk(int x, int z);
|
||||
|
||||
bool isEmpty();
|
||||
bool isEmpty();
|
||||
|
||||
void updateHeights();
|
||||
void updateHeights();
|
||||
|
||||
// unused
|
||||
std::unique_ptr<Chunk> clone() const;
|
||||
|
||||
// flags getters/setters below
|
||||
inline void setFlags(int mask, bool value){
|
||||
if (value)
|
||||
flags |= mask;
|
||||
else
|
||||
flags &= ~(mask);
|
||||
}
|
||||
std::unique_ptr<Chunk> clone() const;
|
||||
|
||||
/* Creates new block inventory given size
|
||||
@return inventory id or 0 if block does not exists */
|
||||
void addBlockInventory(std::shared_ptr<Inventory> inventory,
|
||||
uint x, uint y, uint z);
|
||||
void removeBlockInventory(uint x, uint y, uint z);
|
||||
void setBlockInventories(chunk_inventories_map map);
|
||||
void removeBlockInventory(uint x, uint y, uint z);
|
||||
void setBlockInventories(chunk_inventories_map map);
|
||||
|
||||
/* @return inventory bound to the given block or nullptr */
|
||||
std::shared_ptr<Inventory> getBlockInventory(uint x, uint y, uint z) const;
|
||||
|
||||
inline bool isUnsaved() const {return flags & ChunkFlag::UNSAVED;}
|
||||
inline void setModifiedAndUnsaved() {
|
||||
flags.modified = true;
|
||||
flags.unsaved = true;
|
||||
}
|
||||
|
||||
inline bool isModified() const {return flags & ChunkFlag::MODIFIED;}
|
||||
|
||||
inline bool isLighted() const {return flags & ChunkFlag::LIGHTED;}
|
||||
|
||||
inline bool isLoaded() const {return flags & ChunkFlag::LOADED;}
|
||||
|
||||
inline bool isLoadedLights() const {return flags & ChunkFlag::LOADED_LIGHTS;}
|
||||
|
||||
inline bool isReady() const {return flags & ChunkFlag::READY;}
|
||||
|
||||
inline void setUnsaved(bool newState) {setFlags(ChunkFlag::UNSAVED, newState);}
|
||||
|
||||
inline void setModified(bool newState) {setFlags(ChunkFlag::MODIFIED, newState);}
|
||||
|
||||
inline void setLoaded(bool newState) {setFlags(ChunkFlag::LOADED, newState);}
|
||||
|
||||
inline void setLoadedLights(bool newState) {setFlags(ChunkFlag::LOADED_LIGHTS, newState);}
|
||||
|
||||
inline void setLighted(bool newState) {setFlags(ChunkFlag::LIGHTED, newState);}
|
||||
|
||||
inline void setReady(bool newState) {setFlags(ChunkFlag::READY, newState);}
|
||||
|
||||
std::unique_ptr<ubyte[]> encode() const;
|
||||
std::unique_ptr<ubyte[]> encode() const;
|
||||
|
||||
/**
|
||||
* @return true if all is fine
|
||||
**/
|
||||
bool decode(const ubyte* data);
|
||||
bool decode(const ubyte* data);
|
||||
|
||||
static void convert(ubyte* data, const ContentLUT* lut);
|
||||
};
|
||||
|
||||
@ -68,7 +68,7 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){
|
||||
const Block* def = contentIds->getBlockDef(v->id);
|
||||
if (def->obstacle) {
|
||||
const auto& boxes = def->rotatable
|
||||
? def->rt.hitboxes[v->rotation()]
|
||||
? def->rt.hitboxes[v->state.rotation]
|
||||
: def->hitboxes;
|
||||
for (const auto& hitbox : boxes) {
|
||||
if (hitbox.contains({x - ix, y - iy, z - iz})) {
|
||||
@ -158,7 +158,7 @@ Chunk* Chunks::getChunk(int x, int z){
|
||||
return chunks[z * w + x].get();
|
||||
}
|
||||
|
||||
void Chunks::set(int32_t x, int32_t y, int32_t z, uint32_t id, uint8_t states) {
|
||||
void Chunks::set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state) {
|
||||
if (y < 0 || y >= CHUNK_H)
|
||||
return;
|
||||
x -= ox * CHUNK_W;
|
||||
@ -178,24 +178,22 @@ void Chunks::set(int32_t x, int32_t y, int32_t z, uint32_t id, uint8_t states) {
|
||||
if (def->inventorySize == 0)
|
||||
chunk->removeBlockInventory(lx, y, lz);
|
||||
vox.id = id;
|
||||
vox.states = states;
|
||||
|
||||
chunk->setUnsaved(true);
|
||||
chunk->setModified(true);
|
||||
vox.state = state;
|
||||
chunk->setModifiedAndUnsaved();
|
||||
|
||||
if (y < chunk->bottom) chunk->bottom = y;
|
||||
else if (y + 1 > chunk->top) chunk->top = y + 1;
|
||||
else if (id == 0) chunk->updateHeights();
|
||||
|
||||
if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz)))
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
if (lz == 0 && (chunk = getChunk(cx+ox, cz+oz-1)))
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
|
||||
if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cz+oz)))
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cz+oz+1)))
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
|
||||
voxel* Chunks::rayCast(
|
||||
@ -255,7 +253,7 @@ voxel* Chunks::rayCast(
|
||||
|
||||
if (!def->rt.solid) {
|
||||
const std::vector<AABB>& hitboxes = def->rotatable
|
||||
? def->rt.hitboxes[voxel->rotation()]
|
||||
? def->rt.hitboxes[voxel->state.rotation]
|
||||
: def->hitboxes;
|
||||
|
||||
scalar_t distance = maxDist;
|
||||
@ -365,7 +363,7 @@ glm::vec3 Chunks::rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDis
|
||||
if (def->obstacle) {
|
||||
if (!def->rt.solid) {
|
||||
const std::vector<AABB>& hitboxes = def->rotatable
|
||||
? def->rt.hitboxes[voxel->rotation()]
|
||||
? def->rt.hitboxes[voxel->state.rotation]
|
||||
: def->modelBoxes;
|
||||
|
||||
scalar_t distance;
|
||||
@ -499,12 +497,12 @@ void Chunks::saveAndClear(){
|
||||
for (size_t i = 0; i < volume; i++){
|
||||
Chunk* chunk = chunks[i].get();
|
||||
chunks[i] = nullptr;
|
||||
if (chunk == nullptr || !chunk->isLighted())
|
||||
if (chunk == nullptr || !chunk->flags.lighted)
|
||||
continue;
|
||||
|
||||
bool lightsUnsaved = !chunk->isLoadedLights() &&
|
||||
bool lightsUnsaved = !chunk->flags.loadedLights &&
|
||||
worldFiles->doesWriteLights();
|
||||
if (!chunk->isUnsaved() && !lightsUnsaved)
|
||||
if (!chunk->flags.unsaved && !lightsUnsaved)
|
||||
continue;
|
||||
regions.put(chunk);
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "voxel.hpp"
|
||||
#include "../typedefs.hpp"
|
||||
|
||||
class VoxelRenderer;
|
||||
@ -13,7 +15,6 @@ struct AABB;
|
||||
class Content;
|
||||
class ContentIndices;
|
||||
class Chunk;
|
||||
struct voxel;
|
||||
class WorldFiles;
|
||||
class LevelEvents;
|
||||
|
||||
@ -42,7 +43,7 @@ public:
|
||||
voxel* get(int32_t x, int32_t y, int32_t z);
|
||||
light_t getLight(int32_t x, int32_t y, int32_t z);
|
||||
ubyte getLight(int32_t x, int32_t y, int32_t z, int channel);
|
||||
void set(int32_t x, int32_t y, int32_t z, uint32_t id, uint8_t states);
|
||||
void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state);
|
||||
|
||||
voxel* rayCast(
|
||||
glm::vec3 start,
|
||||
|
||||
@ -61,7 +61,7 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||
chunk->decode(data.get());
|
||||
auto invs = regions.fetchInventories(chunk->x, chunk->z);
|
||||
chunk->setBlockInventories(std::move(invs));
|
||||
chunk->setLoaded(true);
|
||||
chunk->flags.loaded = true;
|
||||
for(auto& entry : chunk->inventories) {
|
||||
level->inventories->store(entry.second);
|
||||
}
|
||||
@ -71,7 +71,7 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||
auto lights = regions.getLights(chunk->x, chunk->z);
|
||||
if (lights) {
|
||||
chunk->lightmap.set(lights.get());
|
||||
chunk->setLoadedLights(true);
|
||||
chunk->flags.loadedLights = true;
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ void DefaultWorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){
|
||||
for (int cur_y = 0; cur_y < CHUNK_H; cur_y++){
|
||||
// int cur_y = y;
|
||||
int id = cur_y < SEA_LEVEL ? idWater : BLOCK_AIR;
|
||||
int states = 0;
|
||||
blockstate state {};
|
||||
if ((cur_y == (int)height) && (SEA_LEVEL-2 < cur_y)) {
|
||||
id = idGrassBlock;
|
||||
} else if (cur_y < (height - 6)){
|
||||
@ -177,7 +177,7 @@ void DefaultWorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){
|
||||
treesTile, idWood, idLeaves);
|
||||
if (tree) {
|
||||
id = tree;
|
||||
states = BLOCK_DIR_UP;
|
||||
state.rotation = BLOCK_DIR_UP;
|
||||
}
|
||||
}
|
||||
float sand = fmax(heights.get(MAPS::SAND, cur_x, cur_z), heights.get(MAPS::CLIFF, cur_x, cur_z));
|
||||
@ -198,10 +198,10 @@ void DefaultWorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){
|
||||
}
|
||||
if ((height > SEA_LEVEL+1) && ((int)(height + 1) == cur_y) && ((unsigned short)randomgrass.rand() > 65533)){
|
||||
id = idWood;
|
||||
states = BLOCK_DIR_UP;
|
||||
state.rotation = BLOCK_DIR_UP;
|
||||
}
|
||||
voxels[(cur_y * CHUNK_D + z) * CHUNK_W + x].id = id;
|
||||
voxels[(cur_y * CHUNK_D + z) * CHUNK_W + x].states = states;
|
||||
voxels[(cur_y * CHUNK_D + z) * CHUNK_W + x].state = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ void FlatWorldGenerator::generate(voxel* voxels, int cx, int cz, int seed) {
|
||||
for (int x = 0; x < CHUNK_W; x++) {
|
||||
for (int cur_y = 0; cur_y < CHUNK_H; cur_y++){
|
||||
int id = BLOCK_AIR;
|
||||
int states = 0;
|
||||
blockstate state {};
|
||||
|
||||
if(cur_y == 2) {
|
||||
id = idBazalt;
|
||||
@ -21,7 +21,7 @@ void FlatWorldGenerator::generate(voxel* voxels, int cx, int cz, int seed) {
|
||||
}
|
||||
|
||||
voxels[(cur_y * CHUNK_D + z) * CHUNK_W + x].id = id;
|
||||
voxels[(cur_y * CHUNK_D + z) * CHUNK_W + x].states = states;
|
||||
voxels[(cur_y * CHUNK_D + z) * CHUNK_W + x].state = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,22 +10,34 @@ inline constexpr int BLOCK_DIR_EAST = 0x3;
|
||||
inline constexpr int BLOCK_DIR_UP = 0x4;
|
||||
inline constexpr int BLOCK_DIR_DOWN = 0x5;
|
||||
|
||||
// limited to 8 block orientations
|
||||
inline constexpr int BLOCK_ROT_MASK = 0b0000'0111;
|
||||
// reserved bits
|
||||
inline constexpr int BLOCK_RESERVED_MASK = 0b1111'1000;
|
||||
struct blockstate {
|
||||
uint8_t rotation : 3;
|
||||
uint8_t segment : 2; // planned to 0.22
|
||||
uint8_t reserved : 3;
|
||||
uint8_t userbits : 8;
|
||||
};
|
||||
static_assert (sizeof(blockstate) == 2);
|
||||
|
||||
inline constexpr blockstate_t blockstate2int(blockstate b) {
|
||||
return static_cast<blockstate_t>(b.rotation) |
|
||||
static_cast<blockstate_t>(b.segment) << 3 |
|
||||
static_cast<blockstate_t>(b.reserved) << 5 |
|
||||
static_cast<blockstate_t>(b.userbits) << 8;
|
||||
}
|
||||
|
||||
inline constexpr blockstate int2blockstate(blockstate_t i) {
|
||||
return {
|
||||
static_cast<uint8_t>(i & 0b111),
|
||||
static_cast<uint8_t>((i >> 3) & 0b11),
|
||||
static_cast<uint8_t>((i >> 5) & 0b111),
|
||||
static_cast<uint8_t>((i >> 8) & 0xFF)
|
||||
};
|
||||
}
|
||||
|
||||
struct voxel {
|
||||
blockid_t id;
|
||||
blockstate_t states;
|
||||
|
||||
inline uint8_t rotation() const {
|
||||
return states & BLOCK_ROT_MASK;
|
||||
}
|
||||
|
||||
inline void setRotation(uint8_t rotation) {
|
||||
states = (states & (~BLOCK_ROT_MASK)) | (rotation & BLOCK_ROT_MASK);
|
||||
}
|
||||
blockstate state;
|
||||
};
|
||||
static_assert(sizeof(voxel) == 4);
|
||||
|
||||
#endif // VOXELS_VOXEL_HPP_
|
||||
|
||||
@ -57,11 +57,11 @@ void World::write(Level* level) {
|
||||
|
||||
for (size_t i = 0; i < chunks->volume; i++) {
|
||||
auto chunk = chunks->chunks[i];
|
||||
if (chunk == nullptr || !chunk->isLighted())
|
||||
if (chunk == nullptr || !chunk->flags.lighted)
|
||||
continue;
|
||||
bool lightsUnsaved = !chunk->isLoadedLights() &&
|
||||
bool lightsUnsaved = !chunk->flags.loadedLights &&
|
||||
settings.debug.doWriteLights.get();
|
||||
if (!chunk->isUnsaved() && !lightsUnsaved)
|
||||
if (!chunk->flags.unsaved && !lightsUnsaved)
|
||||
continue;
|
||||
regions.put(chunk.get());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user