add extended blocks (block size property)
This commit is contained in:
@@ -110,6 +110,8 @@ public:
|
||||
/// @brief Light emission R, G, B, S (sky lights: sun, moon, radioactive clouds)
|
||||
uint8_t emission[4] {0, 0, 0, 0};
|
||||
|
||||
glm::i8vec3 size {1, 1, 1};
|
||||
|
||||
/// @brief Influences visible block sides for transparent blocks
|
||||
uint8_t drawGroup = 0;
|
||||
|
||||
@@ -175,6 +177,9 @@ public:
|
||||
|
||||
/// @brief does the block emit any lights
|
||||
bool emissive = false;
|
||||
|
||||
// @brief block size is greather than 1x1x1
|
||||
bool extended = false;
|
||||
|
||||
/// @brief set of hitboxes sets with all coord-systems precalculated
|
||||
std::vector<AABB> hitboxes[BlockRotProfile::MAX_COUNT];
|
||||
|
||||
+82
-6
@@ -33,7 +33,7 @@ Chunks::Chunks(
|
||||
chunksCount = 0;
|
||||
}
|
||||
|
||||
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) {
|
||||
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
||||
x -= ox * CHUNK_W;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = floordiv(x, CHUNK_W);
|
||||
@@ -158,28 +158,104 @@ Chunk* Chunks::getChunk(int x, int z){
|
||||
return chunks[z * w + x].get();
|
||||
}
|
||||
|
||||
glm::ivec3 Chunks::seekOrigin(glm::ivec3 pos, const Block* def, blockstate state) {
|
||||
const auto& rotation = def->rotations.variants[state.rotation];
|
||||
auto segment = state.segment;
|
||||
while (true) {
|
||||
if (!segment) {
|
||||
return pos;
|
||||
}
|
||||
if (segment & 1) pos -= rotation.axisX;
|
||||
if (segment & 2) pos -= rotation.axisY;
|
||||
if (segment & 4) pos -= rotation.axisZ;
|
||||
|
||||
if (auto* voxel = get(pos.x, pos.y, pos.z)) {
|
||||
segment = voxel->state.segment;
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Chunks::eraseSegments(const Block* def, blockstate state, int x, int y, int z) {
|
||||
const auto& rotation = def->rotations.variants[state.rotation];
|
||||
for (int sy = 0; sy < def->size.y; sy++) {
|
||||
for (int sz = 0; sz < def->size.z; sz++) {
|
||||
for (int sx = 0; sx < def->size.x; sx++) {
|
||||
if ((sx | sy | sz) == 0) {
|
||||
continue;
|
||||
}
|
||||
glm::ivec3 pos(x, y, z);
|
||||
pos += rotation.axisX * sx;
|
||||
pos += rotation.axisY * sy;
|
||||
pos += rotation.axisZ * sz;
|
||||
set(pos.x, pos.y, pos.z, 0, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Chunks::repairSegments(const Block* def, blockstate state, int x, int y, int z) {
|
||||
const auto& rotation = def->rotations.variants[state.rotation];
|
||||
const auto id = def->rt.id;
|
||||
const auto size = def->size;
|
||||
for (int sy = 0; sy < size.y; sy++) {
|
||||
for (int sz = 0; sz < size.z; sz++) {
|
||||
for (int sx = 0; sx < size.x; sx++) {
|
||||
if ((sx | sy | sz) == 0) {
|
||||
continue;
|
||||
}
|
||||
blockstate segState = state;
|
||||
segState.segment = ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2));
|
||||
|
||||
glm::ivec3 pos(x, y, z);
|
||||
pos += rotation.axisX * sx;
|
||||
pos += rotation.axisY * sy;
|
||||
pos += rotation.axisZ * sz;
|
||||
set(pos.x, pos.y, pos.z, id, segState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Chunks::set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state) {
|
||||
if (y < 0 || y >= CHUNK_H)
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
return;
|
||||
}
|
||||
int32_t gx = x;
|
||||
int32_t gz = z;
|
||||
x -= ox * CHUNK_W;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = floordiv(x, CHUNK_W);
|
||||
int cz = floordiv(z, CHUNK_D);
|
||||
if (cx < 0 || cz < 0 || cx >= int(w) || cz >= int(d))
|
||||
if (cx < 0 || cz < 0 || cx >= static_cast<int>(w) || cz >= static_cast<int>(d)) {
|
||||
return;
|
||||
}
|
||||
Chunk* chunk = chunks[cz * w + cx].get();
|
||||
if (chunk == nullptr)
|
||||
if (chunk == nullptr) {
|
||||
return;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int lz = z - cz * CHUNK_D;
|
||||
|
||||
// block finalization
|
||||
voxel& vox = chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||
auto def = contentIds->getBlockDef(vox.id);
|
||||
if (def->inventorySize == 0)
|
||||
auto prevdef = contentIds->getBlockDef(vox.id);
|
||||
if (prevdef->inventorySize == 0) {
|
||||
chunk->removeBlockInventory(lx, y, lz);
|
||||
}
|
||||
if (prevdef->rt.extended && !vox.state.segment) {
|
||||
eraseSegments(prevdef, vox.state, gx, y, gz);
|
||||
}
|
||||
|
||||
// block initialization
|
||||
auto newdef = contentIds->getBlockDef(id);
|
||||
vox.id = id;
|
||||
vox.state = state;
|
||||
chunk->setModifiedAndUnsaved();
|
||||
if (!state.segment && newdef->rt.extended) {
|
||||
repairSegments(newdef, state, gx, y, gz);
|
||||
}
|
||||
|
||||
if (y < chunk->bottom) chunk->bottom = y;
|
||||
else if (y + 1 > chunk->top) chunk->top = y + 1;
|
||||
|
||||
+11
-1
@@ -17,10 +17,14 @@ class ContentIndices;
|
||||
class Chunk;
|
||||
class WorldFiles;
|
||||
class LevelEvents;
|
||||
class Block;
|
||||
|
||||
/* Player-centred chunks matrix */
|
||||
class Chunks {
|
||||
const ContentIndices* const contentIds;
|
||||
|
||||
void eraseSegments(const Block* def, blockstate state, int x, int y, int z);
|
||||
void repairSegments(const Block* def, blockstate state, int x, int y, int z);
|
||||
public:
|
||||
std::vector<std::shared_ptr<Chunk>> chunks;
|
||||
std::vector<std::shared_ptr<Chunk>> chunksSecond;
|
||||
@@ -40,10 +44,16 @@ public:
|
||||
|
||||
Chunk* getChunk(int32_t x, int32_t z);
|
||||
Chunk* getChunkByVoxel(int32_t x, int32_t y, int32_t z);
|
||||
voxel* get(int32_t x, int32_t y, int32_t z);
|
||||
voxel* get(int32_t x, int32_t y, int32_t z) const;
|
||||
|
||||
inline voxel* get(glm::ivec3 pos) {
|
||||
return get(pos.x, pos.y, pos.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, blockstate state);
|
||||
glm::ivec3 seekOrigin(glm::ivec3 pos, const Block* def, blockstate state);
|
||||
|
||||
voxel* rayCast(
|
||||
glm::vec3 start,
|
||||
|
||||
Reference in New Issue
Block a user