feat: extended blocks rotation

This commit is contained in:
MihailRis 2024-06-09 19:54:34 +03:00
parent 65a2a3e475
commit 90ed175915
8 changed files with 109 additions and 13 deletions

View File

@ -11,7 +11,7 @@
"light-passing": true,
"sky-light-passing": true,
"size": [1, 2, 1],
"rotation": "pipe",
"rotation": "pane",
"model": "aabb",
"hitbox": [0.0, 0.0, 0.8, 1.0, 2.0, 0.2]
"hitbox": [0.0, 0.0, 0.0, 1.0, 2.0, 0.2]
}

View File

@ -0,0 +1,6 @@
{
"sounds": [
"blocks/door_open",
"blocks/door_close"
]
}

View File

@ -0,0 +1,13 @@
function on_interact(x, y, z)
local inc = 1
if block.get_user_bits(x, y, z, 0, 1) > 0 then
inc = 3
block.set_user_bits(x, y, z, 0, 1, 0)
audio.play_sound("blocks/door_close", x+0.5, y+1, z+0.5, 1, 1)
else
block.set_user_bits(x, y, z, 0, 1, 1)
audio.play_sound("blocks/door_open", x+0.5, y+1, z+0.5, 1, 1)
end
block.set_rotation(x, y, z, (block.get_rotation(x, y, z) + inc) % 4)
return true
end

Binary file not shown.

Binary file not shown.

View File

@ -152,12 +152,7 @@ int l_set_block_rotation(lua_State* L) {
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
lua_Integer value = lua_tointeger(L, 4);
voxel* vox = scripting::level->chunks->get(x, y, z);
if (vox == nullptr) {
return 0;
}
vox->state.rotation = value;
scripting::level->chunks->getChunkByVoxel(x, y, z)->setModifiedAndUnsaved();
scripting::level->chunks->setRotation(x, y, z, value);
return 0;
}

View File

@ -200,6 +200,10 @@ void Chunks::eraseSegments(const Block* def, blockstate state, int x, int y, int
}
}
static constexpr uint8_t segment_to_int(int sx, int sy, int sz) {
return ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2));
}
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;
@ -211,7 +215,7 @@ void Chunks::repairSegments(const Block* def, blockstate state, int x, int y, in
continue;
}
blockstate segState = state;
segState.segment = ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2));
segState.segment = segment_to_int(sx, sy, sz);
glm::ivec3 pos(x, y, z);
pos += rotation.axisX * sx;
@ -223,14 +227,14 @@ void Chunks::repairSegments(const Block* def, blockstate state, int x, int y, in
}
}
bool Chunks::checkReplaceability(const Block* def, blockstate state, glm::ivec3 origin) {
bool Chunks::checkReplaceability(const Block* def, blockstate state, glm::ivec3 origin, blockid_t ignore) {
const auto& rotation = def->rotations.variants[state.rotation];
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++) {
blockstate segState = state;
segState.segment = ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2));
segState.segment = segment_to_int(sx, sy, sz);
auto pos = origin;
pos += rotation.axisX * sx;
@ -238,7 +242,7 @@ bool Chunks::checkReplaceability(const Block* def, blockstate state, glm::ivec3
pos += rotation.axisZ * sz;
if (auto vox = get(pos.x, pos.y, pos.z)) {
auto target = indices->getBlockDef(vox->id);
if (!target->replaceable) {
if (!target->replaceable && vox->id != ignore) {
return false;
}
} else {
@ -250,6 +254,82 @@ bool Chunks::checkReplaceability(const Block* def, blockstate state, glm::ivec3
return true;
}
void Chunks::setRotationExtended(
Block* def, blockstate state, glm::ivec3 origin, uint8_t index
) {
auto newstate = state;
newstate.rotation = index;
// unable to rotate block (cause: obstacles)
if (!checkReplaceability(def, newstate, origin, def->rt.id)) {
return;
}
const auto& rotation = def->rotations.variants[index];
const auto size = def->size;
std::vector<glm::ivec3> segmentBlocks;
for (int sy = 0; sy < size.y; sy++) {
for (int sz = 0; sz < size.z; sz++) {
for (int sx = 0; sx < size.x; sx++) {
auto pos = origin;
pos += rotation.axisX * sx;
pos += rotation.axisY * sy;
pos += rotation.axisZ * sz;
blockstate segState = newstate;
segState.segment = segment_to_int(sx, sy, sz);
auto vox = get(pos);
// checked for nullptr by checkReplaceability
if (vox->id != def->rt.id) {
set(pos.x, pos.y, pos.z, def->rt.id, segState);
} else {
vox->state = segState;
auto chunk = getChunkByVoxel(pos.x, pos.y, pos.z);
chunk->setModifiedAndUnsaved();
segmentBlocks.emplace_back(pos);
}
}
}
}
const auto& prevRotation = def->rotations.variants[state.rotation];
for (int sy = 0; sy < size.y; sy++) {
for (int sz = 0; sz < size.z; sz++) {
for (int sx = 0; sx < size.x; sx++) {
auto pos = origin;
pos += prevRotation.axisX * sx;
pos += prevRotation.axisY * sy;
pos += prevRotation.axisZ * sz;
if (std::find(segmentBlocks.begin(), segmentBlocks.end(), pos) == segmentBlocks.end()) {
set(pos.x, pos.y, pos.z, 0, {});
}
}
}
}
}
void Chunks::setRotation(int32_t x, int32_t y, int32_t z, uint8_t index) {
if (index >= BlockRotProfile::MAX_COUNT) {
return;
}
auto vox = get(x, y, z);
if (vox == nullptr) {
return;
}
auto def = indices->getBlockDef(vox->id);
if (!def->rotatable || vox->state.rotation == index) {
return;
}
if (def->rt.extended) {
setRotationExtended(def, vox->state, {x, y, z}, index);
} else {
vox->state.rotation = index;
auto chunk = getChunkByVoxel(x, y, z);
chunk->setModifiedAndUnsaved();
}
}
void Chunks::set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state) {
if (y < 0 || y >= CHUNK_H) {
return;

View File

@ -25,6 +25,7 @@ class Chunks {
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);
void setRotationExtended(Block* def, blockstate state, glm::ivec3 origin, uint8_t rotation);
public:
std::vector<std::shared_ptr<Chunk>> chunks;
std::vector<std::shared_ptr<Chunk>> chunksSecond;
@ -40,7 +41,7 @@ public:
WorldFiles* worldFiles, LevelEvents* events, const Content* content);
~Chunks() = default;
bool checkReplaceability(const Block* def, blockstate state, glm::ivec3 coord);
bool checkReplaceability(const Block* def, blockstate state, glm::ivec3 coord, blockid_t ignore=0);
bool putChunk(const std::shared_ptr<Chunk>& chunk);
Chunk* getChunk(int32_t x, int32_t z);
@ -55,6 +56,7 @@ public:
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);
void setRotation(int32_t x, int32_t y, int32_t z, uint8_t rotation);
voxel* rayCast(
glm::vec3 start,