add extended blocks (block size property)
This commit is contained in:
@@ -62,6 +62,7 @@ std::unique_ptr<Content> ContentBuilder::build() {
|
|||||||
def.rt.id = blockDefsIndices.size();
|
def.rt.id = blockDefsIndices.size();
|
||||||
def.rt.emissive = *reinterpret_cast<uint32_t*>(def.emission);
|
def.rt.emissive = *reinterpret_cast<uint32_t*>(def.emission);
|
||||||
def.rt.solid = def.model == BlockModel::block;
|
def.rt.solid = def.model == BlockModel::block;
|
||||||
|
def.rt.extended = def.size.x > 1 || def.size.y > 1 || def.size.z > 1;
|
||||||
|
|
||||||
if (def.rotatable) {
|
if (def.rotatable) {
|
||||||
for (uint i = 0; i < BlockRotProfile::MAX_COUNT; i++) {
|
for (uint i = 0; i < BlockRotProfile::MAX_COUNT; i++) {
|
||||||
|
|||||||
@@ -175,29 +175,38 @@ void ContentLoader::loadBlock(Block& def, const std::string& name, const fs::pat
|
|||||||
def.hitboxes[i].b = glm::vec3(box->num(3), box->num(4), box->num(5));
|
def.hitboxes[i].b = glm::vec3(box->num(3), box->num(4), box->num(5));
|
||||||
def.hitboxes[i].b += def.hitboxes[i].a;
|
def.hitboxes[i].b += def.hitboxes[i].a;
|
||||||
}
|
}
|
||||||
|
} else if (auto boxarr = root->list("hitbox")){
|
||||||
|
AABB aabb;
|
||||||
|
aabb.a = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2));
|
||||||
|
aabb.b = glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5));
|
||||||
|
aabb.b += aabb.a;
|
||||||
|
def.hitboxes = { aabb };
|
||||||
|
} else if (!def.modelBoxes.empty()) {
|
||||||
|
def.hitboxes = def.modelBoxes;
|
||||||
} else {
|
} else {
|
||||||
boxarr = root->list("hitbox");
|
def.hitboxes = { AABB() };
|
||||||
if (boxarr) {
|
|
||||||
AABB aabb;
|
|
||||||
aabb.a = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2));
|
|
||||||
aabb.b = glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5));
|
|
||||||
aabb.b += aabb.a;
|
|
||||||
def.hitboxes = { aabb };
|
|
||||||
} else if (!def.modelBoxes.empty()) {
|
|
||||||
def.hitboxes = def.modelBoxes;
|
|
||||||
} else {
|
|
||||||
def.hitboxes = { AABB() };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// block light emission [r, g, b] where r,g,b in range [0..15]
|
// block light emission [r, g, b] where r,g,b in range [0..15]
|
||||||
auto emissionarr = root->list("emission");
|
if (auto emissionarr = root->list("emission")) {
|
||||||
if (emissionarr) {
|
|
||||||
def.emission[0] = emissionarr->num(0);
|
def.emission[0] = emissionarr->num(0);
|
||||||
def.emission[1] = emissionarr->num(1);
|
def.emission[1] = emissionarr->num(1);
|
||||||
def.emission[2] = emissionarr->num(2);
|
def.emission[2] = emissionarr->num(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// block size
|
||||||
|
if (auto sizearr = root->list("size")) {
|
||||||
|
def.size.x = sizearr->num(0);
|
||||||
|
def.size.y = sizearr->num(1);
|
||||||
|
def.size.z = sizearr->num(2);
|
||||||
|
if (def.model == BlockModel::block &&
|
||||||
|
(def.size.x != 1 || def.size.y != 1 || def.size.z != 1)) {
|
||||||
|
def.model = BlockModel::aabb;
|
||||||
|
def.hitboxes = {AABB(def.size)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// primitive properties
|
// primitive properties
|
||||||
root->flag("obstacle", def.obstacle);
|
root->flag("obstacle", def.obstacle);
|
||||||
root->flag("replaceable", def.replaceable);
|
root->flag("replaceable", def.replaceable);
|
||||||
|
|||||||
@@ -414,9 +414,11 @@ void BlocksRenderer::render(const voxel* voxels) {
|
|||||||
for (int i = begin; i < end; i++) {
|
for (int i = begin; i < end; i++) {
|
||||||
const voxel& vox = voxels[i];
|
const voxel& vox = voxels[i];
|
||||||
blockid_t id = vox.id;
|
blockid_t id = vox.id;
|
||||||
|
blockstate state = vox.state;
|
||||||
const Block& def = *blockDefsCache[id];
|
const Block& def = *blockDefsCache[id];
|
||||||
if (id == 0 || def.drawGroup != drawGroup)
|
if (id == 0 || def.drawGroup != drawGroup || state.segment) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const UVRegion texfaces[6]{ cache->getRegion(id, 0),
|
const UVRegion texfaces[6]{ cache->getRegion(id, 0),
|
||||||
cache->getRegion(id, 1),
|
cache->getRegion(id, 1),
|
||||||
cache->getRegion(id, 2),
|
cache->getRegion(id, 2),
|
||||||
|
|||||||
@@ -130,11 +130,13 @@ void BlocksController::randomTick(int tickid, int parts) {
|
|||||||
for (uint z = padding; z < d-padding; z++){
|
for (uint z = padding; z < d-padding; z++){
|
||||||
for (uint x = padding; x < w-padding; x++){
|
for (uint x = padding; x < w-padding; x++){
|
||||||
int index = z * w + x;
|
int index = z * w + x;
|
||||||
if ((index + tickid) % parts != 0)
|
if ((index + tickid) % parts != 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
auto& chunk = chunks->chunks[index];
|
auto& chunk = chunks->chunks[index];
|
||||||
if (chunk == nullptr || !chunk->flags.lighted)
|
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
for (int s = 0; s < segments; s++) {
|
for (int s = 0; s < segments; s++) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
int bx = random.rand() % CHUNK_W;
|
int bx = random.rand() % CHUNK_W;
|
||||||
@@ -146,7 +148,8 @@ void BlocksController::randomTick(int tickid, int parts) {
|
|||||||
scripting::random_update_block(
|
scripting::random_update_block(
|
||||||
block,
|
block,
|
||||||
chunk->x * CHUNK_W + bx, by,
|
chunk->x * CHUNK_W + bx, by,
|
||||||
chunk->z * CHUNK_D + bz);
|
chunk->z * CHUNK_D + bz
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -364,9 +364,15 @@ void PlayerController::updateInteraction(){
|
|||||||
end, norm, iend
|
end, norm, iend
|
||||||
);
|
);
|
||||||
if (vox != nullptr) {
|
if (vox != nullptr) {
|
||||||
|
blockstate selectedState = vox->state;
|
||||||
player->selectedVoxel = *vox;
|
player->selectedVoxel = *vox;
|
||||||
selectedBlockId = vox->id;
|
selectedBlockId = vox->id;
|
||||||
selectedBlockRotation = vox->state.rotation;
|
selectedBlockRotation = vox->state.rotation;
|
||||||
|
if (selectedState.segment) {
|
||||||
|
iend = chunks->seekOrigin(
|
||||||
|
iend, indices->getBlockDef(selectedBlockId), selectedState
|
||||||
|
);
|
||||||
|
}
|
||||||
player->selectedBlockPosition = iend;
|
player->selectedBlockPosition = iend;
|
||||||
selectedPointPosition = end;
|
selectedPointPosition = end;
|
||||||
selectedBlockNormal = norm;
|
selectedBlockNormal = norm;
|
||||||
@@ -379,8 +385,9 @@ void PlayerController::updateInteraction(){
|
|||||||
state.rotation = determine_rotation(def, norm, camera->dir);
|
state.rotation = determine_rotation(def, norm, camera->dir);
|
||||||
|
|
||||||
if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) {
|
if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) {
|
||||||
if (scripting::on_item_break_block(player.get(), item, x, y, z))
|
if (scripting::on_item_break_block(player.get(), item, x, y, z)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Block* target = indices->getBlockDef(vox->id);
|
Block* target = indices->getBlockDef(vox->id);
|
||||||
@@ -411,10 +418,8 @@ void PlayerController::updateInteraction(){
|
|||||||
x = (iend.x)+(norm.x);
|
x = (iend.x)+(norm.x);
|
||||||
y = (iend.y)+(norm.y);
|
y = (iend.y)+(norm.y);
|
||||||
z = (iend.z)+(norm.z);
|
z = (iend.z)+(norm.z);
|
||||||
} else {
|
} else if (def->rotations.name == "pipe") {
|
||||||
if (def->rotations.name == "pipe") {
|
state.rotation = BLOCK_DIR_UP;
|
||||||
state.rotation = BLOCK_DIR_UP;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vox = chunks->get(x, y, z);
|
vox = chunks->get(x, y, z);
|
||||||
blockid_t chosenBlock = def->rt.id;
|
blockid_t chosenBlock = def->rt.id;
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ struct AABB {
|
|||||||
glm::vec3 a {0.0f};
|
glm::vec3 a {0.0f};
|
||||||
glm::vec3 b {1.0f};
|
glm::vec3 b {1.0f};
|
||||||
|
|
||||||
|
AABB() {}
|
||||||
|
|
||||||
|
AABB(glm::vec3 size) : a(0.0f), b(size) {
|
||||||
|
}
|
||||||
|
|
||||||
/* Get AABB point with minimal x,y,z */
|
/* Get AABB point with minimal x,y,z */
|
||||||
inline glm::vec3 min() const {
|
inline glm::vec3 min() const {
|
||||||
return glm::min(a, b);
|
return glm::min(a, b);
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ public:
|
|||||||
/// @brief Light emission R, G, B, S (sky lights: sun, moon, radioactive clouds)
|
/// @brief Light emission R, G, B, S (sky lights: sun, moon, radioactive clouds)
|
||||||
uint8_t emission[4] {0, 0, 0, 0};
|
uint8_t emission[4] {0, 0, 0, 0};
|
||||||
|
|
||||||
|
glm::i8vec3 size {1, 1, 1};
|
||||||
|
|
||||||
/// @brief Influences visible block sides for transparent blocks
|
/// @brief Influences visible block sides for transparent blocks
|
||||||
uint8_t drawGroup = 0;
|
uint8_t drawGroup = 0;
|
||||||
|
|
||||||
@@ -176,6 +178,9 @@ public:
|
|||||||
/// @brief does the block emit any lights
|
/// @brief does the block emit any lights
|
||||||
bool emissive = false;
|
bool emissive = false;
|
||||||
|
|
||||||
|
// @brief block size is greather than 1x1x1
|
||||||
|
bool extended = false;
|
||||||
|
|
||||||
/// @brief set of hitboxes sets with all coord-systems precalculated
|
/// @brief set of hitboxes sets with all coord-systems precalculated
|
||||||
std::vector<AABB> hitboxes[BlockRotProfile::MAX_COUNT];
|
std::vector<AABB> hitboxes[BlockRotProfile::MAX_COUNT];
|
||||||
|
|
||||||
|
|||||||
+82
-6
@@ -33,7 +33,7 @@ Chunks::Chunks(
|
|||||||
chunksCount = 0;
|
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;
|
x -= ox * CHUNK_W;
|
||||||
z -= oz * CHUNK_D;
|
z -= oz * CHUNK_D;
|
||||||
int cx = floordiv(x, CHUNK_W);
|
int cx = floordiv(x, CHUNK_W);
|
||||||
@@ -158,28 +158,104 @@ Chunk* Chunks::getChunk(int x, int z){
|
|||||||
return chunks[z * w + x].get();
|
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) {
|
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;
|
return;
|
||||||
|
}
|
||||||
|
int32_t gx = x;
|
||||||
|
int32_t gz = z;
|
||||||
x -= ox * CHUNK_W;
|
x -= ox * CHUNK_W;
|
||||||
z -= oz * CHUNK_D;
|
z -= oz * CHUNK_D;
|
||||||
int cx = floordiv(x, CHUNK_W);
|
int cx = floordiv(x, CHUNK_W);
|
||||||
int cz = floordiv(z, CHUNK_D);
|
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;
|
return;
|
||||||
|
}
|
||||||
Chunk* chunk = chunks[cz * w + cx].get();
|
Chunk* chunk = chunks[cz * w + cx].get();
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
int lx = x - cx * CHUNK_W;
|
int lx = x - cx * CHUNK_W;
|
||||||
int lz = z - cz * CHUNK_D;
|
int lz = z - cz * CHUNK_D;
|
||||||
|
|
||||||
|
// block finalization
|
||||||
voxel& vox = chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
voxel& vox = chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||||
auto def = contentIds->getBlockDef(vox.id);
|
auto prevdef = contentIds->getBlockDef(vox.id);
|
||||||
if (def->inventorySize == 0)
|
if (prevdef->inventorySize == 0) {
|
||||||
chunk->removeBlockInventory(lx, y, lz);
|
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.id = id;
|
||||||
vox.state = state;
|
vox.state = state;
|
||||||
chunk->setModifiedAndUnsaved();
|
chunk->setModifiedAndUnsaved();
|
||||||
|
if (!state.segment && newdef->rt.extended) {
|
||||||
|
repairSegments(newdef, state, gx, y, gz);
|
||||||
|
}
|
||||||
|
|
||||||
if (y < chunk->bottom) chunk->bottom = y;
|
if (y < chunk->bottom) chunk->bottom = y;
|
||||||
else if (y + 1 > chunk->top) chunk->top = y + 1;
|
else if (y + 1 > chunk->top) chunk->top = y + 1;
|
||||||
|
|||||||
+11
-1
@@ -17,10 +17,14 @@ class ContentIndices;
|
|||||||
class Chunk;
|
class Chunk;
|
||||||
class WorldFiles;
|
class WorldFiles;
|
||||||
class LevelEvents;
|
class LevelEvents;
|
||||||
|
class Block;
|
||||||
|
|
||||||
/* Player-centred chunks matrix */
|
/* Player-centred chunks matrix */
|
||||||
class Chunks {
|
class Chunks {
|
||||||
const ContentIndices* const contentIds;
|
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:
|
public:
|
||||||
std::vector<std::shared_ptr<Chunk>> chunks;
|
std::vector<std::shared_ptr<Chunk>> chunks;
|
||||||
std::vector<std::shared_ptr<Chunk>> chunksSecond;
|
std::vector<std::shared_ptr<Chunk>> chunksSecond;
|
||||||
@@ -40,10 +44,16 @@ public:
|
|||||||
|
|
||||||
Chunk* getChunk(int32_t x, int32_t z);
|
Chunk* getChunk(int32_t x, int32_t z);
|
||||||
Chunk* getChunkByVoxel(int32_t x, int32_t y, 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);
|
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);
|
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);
|
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(
|
voxel* rayCast(
|
||||||
glm::vec3 start,
|
glm::vec3 start,
|
||||||
|
|||||||
Reference in New Issue
Block a user