feat: extended blocks rotation
This commit is contained in:
parent
65a2a3e475
commit
90ed175915
@ -11,7 +11,7 @@
|
|||||||
"light-passing": true,
|
"light-passing": true,
|
||||||
"sky-light-passing": true,
|
"sky-light-passing": true,
|
||||||
"size": [1, 2, 1],
|
"size": [1, 2, 1],
|
||||||
"rotation": "pipe",
|
"rotation": "pane",
|
||||||
"model": "aabb",
|
"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 y = lua_tointeger(L, 2);
|
||||||
lua_Integer z = lua_tointeger(L, 3);
|
lua_Integer z = lua_tointeger(L, 3);
|
||||||
lua_Integer value = lua_tointeger(L, 4);
|
lua_Integer value = lua_tointeger(L, 4);
|
||||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
scripting::level->chunks->setRotation(x, y, z, value);
|
||||||
if (vox == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
vox->state.rotation = value;
|
|
||||||
scripting::level->chunks->getChunkByVoxel(x, y, z)->setModifiedAndUnsaved();
|
|
||||||
return 0;
|
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) {
|
void Chunks::repairSegments(const Block* def, blockstate state, int x, int y, int z) {
|
||||||
const auto& rotation = def->rotations.variants[state.rotation];
|
const auto& rotation = def->rotations.variants[state.rotation];
|
||||||
const auto id = def->rt.id;
|
const auto id = def->rt.id;
|
||||||
@ -211,7 +215,7 @@ void Chunks::repairSegments(const Block* def, blockstate state, int x, int y, in
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
blockstate segState = state;
|
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);
|
glm::ivec3 pos(x, y, z);
|
||||||
pos += rotation.axisX * sx;
|
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& rotation = def->rotations.variants[state.rotation];
|
||||||
const auto size = def->size;
|
const auto size = def->size;
|
||||||
for (int sy = 0; sy < size.y; sy++) {
|
for (int sy = 0; sy < size.y; sy++) {
|
||||||
for (int sz = 0; sz < size.z; sz++) {
|
for (int sz = 0; sz < size.z; sz++) {
|
||||||
for (int sx = 0; sx < size.x; sx++) {
|
for (int sx = 0; sx < size.x; sx++) {
|
||||||
blockstate segState = state;
|
blockstate segState = state;
|
||||||
segState.segment = ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2));
|
segState.segment = segment_to_int(sx, sy, sz);
|
||||||
|
|
||||||
auto pos = origin;
|
auto pos = origin;
|
||||||
pos += rotation.axisX * sx;
|
pos += rotation.axisX * sx;
|
||||||
@ -238,7 +242,7 @@ bool Chunks::checkReplaceability(const Block* def, blockstate state, glm::ivec3
|
|||||||
pos += rotation.axisZ * sz;
|
pos += rotation.axisZ * sz;
|
||||||
if (auto vox = get(pos.x, pos.y, pos.z)) {
|
if (auto vox = get(pos.x, pos.y, pos.z)) {
|
||||||
auto target = indices->getBlockDef(vox->id);
|
auto target = indices->getBlockDef(vox->id);
|
||||||
if (!target->replaceable) {
|
if (!target->replaceable && vox->id != ignore) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -250,6 +254,82 @@ bool Chunks::checkReplaceability(const Block* def, blockstate state, glm::ivec3
|
|||||||
return true;
|
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) {
|
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;
|
||||||
|
|||||||
@ -25,6 +25,7 @@ class Chunks {
|
|||||||
|
|
||||||
void eraseSegments(const Block* def, blockstate state, int x, int y, int z);
|
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 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:
|
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,7 +41,7 @@ public:
|
|||||||
WorldFiles* worldFiles, LevelEvents* events, const Content* content);
|
WorldFiles* worldFiles, LevelEvents* events, const Content* content);
|
||||||
~Chunks() = default;
|
~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);
|
bool putChunk(const std::shared_ptr<Chunk>& chunk);
|
||||||
|
|
||||||
Chunk* getChunk(int32_t x, int32_t z);
|
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);
|
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);
|
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(
|
voxel* rayCast(
|
||||||
glm::vec3 start,
|
glm::vec3 start,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user