feat: extended blocks rotation
This commit is contained in:
parent
65a2a3e475
commit
90ed175915
@ -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]
|
||||
}
|
||||
|
||||
6
res/content/base/preload.json
Normal file
6
res/content/base/preload.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"sounds": [
|
||||
"blocks/door_open",
|
||||
"blocks/door_close"
|
||||
]
|
||||
}
|
||||
13
res/content/base/scripts/door.lua
Normal file
13
res/content/base/scripts/door.lua
Normal 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
|
||||
BIN
res/content/base/sounds/blocks/door_close.ogg
Normal file
BIN
res/content/base/sounds/blocks/door_close.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/blocks/door_open.ogg
Normal file
BIN
res/content/base/sounds/blocks/door_open.ogg
Normal file
Binary file not shown.
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user