Merge branch 'dev' into pathfinding

This commit is contained in:
MihailRis 2025-08-24 17:32:13 +03:00
commit 98e9f5a2a9
9 changed files with 73 additions and 24 deletions

View File

@ -28,3 +28,9 @@ assert(#arr == arr:get_capacity())
arr = Bytearray({0, 2, 7, 1, 16, 75, 25}) arr = Bytearray({0, 2, 7, 1, 16, 75, 25})
assert(arr[6] == 75) assert(arr[6] == 75)
arr:insert(2, {5, 6})
assert(arr[#arr] == 25)
assert(arr[2] == 5)
assert(arr[3] == 6)

View File

@ -1,6 +1,11 @@
function on_block_broken(id, x, y, z, playerid) function on_block_broken(id, x, y, z, playerid)
if gfx then if gfx then
gfx.particles.emit({x+0.5, y+0.5, z+0.5}, 64, { local size = {block.get_size(id)}
gfx.particles.emit({
x + size[1] * 0.5,
y + size[1] * 0.5,
z + size[1] * 0.5
}, 64, {
lifetime=1.0, lifetime=1.0,
spawn_interval=0.0001, spawn_interval=0.0001,
explosion={4, 4, 4}, explosion={4, 4, 4},
@ -8,7 +13,7 @@ function on_block_broken(id, x, y, z, playerid)
random_sub_uv=0.1, random_sub_uv=0.1,
size={0.1, 0.1, 0.1}, size={0.1, 0.1, 0.1},
spawn_shape="box", spawn_shape="box",
spawn_spread={0.4, 0.4, 0.4} spawn_spread=vec3.mul(size, 0.4)
}) })
end end

View File

@ -71,7 +71,7 @@ local function insert(self, index, b)
if self.size + elems > self.capacity then if self.size + elems > self.capacity then
grow_buffer(self, elems) grow_buffer(self, elems)
end end
for i=self.size, index - 1, -1 do for i = self.size - 1, index - 1, -1 do
self.bytes[i + elems] = self.bytes[i] self.bytes[i + elems] = self.bytes[i]
end end
if _type(b) == "number" then if _type(b) == "number" then

View File

@ -6,6 +6,7 @@
#include "voxels/Block.hpp" #include "voxels/Block.hpp"
#include "content/Content.hpp" #include "content/Content.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "core_defs.hpp"
static debug::Logger logger("models-generator"); static debug::Logger logger("models-generator");
@ -67,11 +68,18 @@ void ModelsGenerator::prepareModel(
} else { } else {
auto srcModel = assets.get<model::Model>(blockModel.name); auto srcModel = assets.get<model::Model>(blockModel.name);
if (srcModel) { if (srcModel) {
bool defaultAssigned = variant.textureFaces[0] != TEXTURE_NOTFOUND;
auto model = std::make_unique<model::Model>(*srcModel); auto model = std::make_unique<model::Model>(*srcModel);
for (auto& mesh : model->meshes) { for (auto& mesh : model->meshes) {
if (mesh.texture.length() && mesh.texture[0] == '$') { if (mesh.texture.length() && mesh.texture[0] == '$') {
int index = std::stoll(mesh.texture.substr(1)); int index = std::stoll(mesh.texture.substr(1));
mesh.texture = "blocks:" + variant.textureFaces[index]; mesh.texture = "blocks:" + variant.textureFaces[index];
} else if (!defaultAssigned && !mesh.texture.empty()) {
size_t sepPos = mesh.texture.find(':');
if (sepPos == std::string::npos)
continue;
variant.textureFaces[0] = mesh.texture.substr(sepPos + 1);
defaultAssigned = true;
} }
} }
blockModel.name = modelName; blockModel.name = modelName;

View File

@ -16,7 +16,7 @@ using namespace scripting;
static int l_save_fragment(lua::State* L) { static int l_save_fragment(lua::State* L) {
auto fragment = lua::touserdata<lua::LuaVoxelFragment>(L, 1); auto fragment = lua::touserdata<lua::LuaVoxelFragment>(L, 1);
auto file = lua::require_string(L, 2); auto file = lua::require_string(L, 2);
auto map = fragment->getFragment()->serialize(); auto map = fragment->getFragment(0)->serialize();
auto bytes = json::to_binary(map, true); auto bytes = json::to_binary(map, true);
io::write_bytes(file, bytes.data(), bytes.size()); io::write_bytes(file, bytes.data(), bytes.size());
return 0; return 0;
@ -30,22 +30,45 @@ static int l_create_fragment(lua::State* L) {
auto fragment = auto fragment =
VoxelFragment::create(*level, pointA, pointB, crop, saveEntities); VoxelFragment::create(*level, pointA, pointB, crop, saveEntities);
fragment->prepare(*content);
std::array<std::shared_ptr<VoxelFragment>, 4> fragmentVariants {
std::move(fragment)
};
for (size_t i = 1; i < 4; i++) {
fragmentVariants[i] = fragmentVariants[i - 1]->rotated(*content);
}
return lua::newuserdata<lua::LuaVoxelFragment>( return lua::newuserdata<lua::LuaVoxelFragment>(
L, std::shared_ptr<VoxelFragment>(std::move(fragment)) L, std::move(fragmentVariants)
); );
} }
static int l_load_fragment(lua::State* L) { static int l_load_fragment(lua::State* L) {
dv::value map;
if (!lua::isstring(L, 1)) {
io::path path = lua::require_string(L, 1); io::path path = lua::require_string(L, 1);
if (!io::exists(path)) { if (!io::exists(path)) {
throw std::runtime_error("file "+path.string()+" does not exist"); throw std::runtime_error("file "+path.string()+" does not exist");
} }
auto map = io::read_binary_json(path); map = io::read_binary_json(path);
} else {
auto bytearray = lua::bytearray_as_string(L, 1);
map = json::from_binary(
reinterpret_cast<const ubyte*>(bytearray.data()), bytearray.size()
);
}
auto fragment = std::make_shared<VoxelFragment>(); auto fragment = std::make_shared<VoxelFragment>();
fragment->deserialize(map); fragment->deserialize(map);
fragment->prepare(*content); fragment->prepare(*content);
return lua::newuserdata<lua::LuaVoxelFragment>(L, std::move(fragment)); std::array<std::shared_ptr<VoxelFragment>, 4> fragmentVariants {
std::move(fragment)
};
for (size_t i = 1; i < 4; i++) {
fragmentVariants[i] = fragmentVariants[i - 1]->rotated(*content);
}
return lua::newuserdata<lua::LuaVoxelFragment>(
L, std::move(fragmentVariants)
);
} }
/// @brief Get a list of all world generators /// @brief Get a list of all world generators

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <array>
#include "lua_commons.hpp" #include "lua_commons.hpp"
@ -55,14 +56,16 @@ namespace lua {
static_assert(!std::is_abstract<LuaHeightmap>()); static_assert(!std::is_abstract<LuaHeightmap>());
class LuaVoxelFragment : public Userdata { class LuaVoxelFragment : public Userdata {
std::shared_ptr<VoxelFragment> fragment; std::array<std::shared_ptr<VoxelFragment>, 4> fragmentVariants;
public: public:
LuaVoxelFragment(std::shared_ptr<VoxelFragment> fragment); LuaVoxelFragment(
std::array<std::shared_ptr<VoxelFragment>, 4> fragmentVariants
);
virtual ~LuaVoxelFragment(); virtual ~LuaVoxelFragment();
std::shared_ptr<VoxelFragment> getFragment() const { std::shared_ptr<VoxelFragment> getFragment(size_t rotation) const {
return fragment; return fragmentVariants.at(rotation & 0b11);
} }
const std::string& getTypeName() const override { const std::string& getTypeName() const override {

View File

@ -8,15 +8,20 @@
using namespace lua; using namespace lua;
LuaVoxelFragment::LuaVoxelFragment(std::shared_ptr<VoxelFragment> fragment) LuaVoxelFragment::LuaVoxelFragment(
: fragment(std::move(fragment)) {} std::array<std::shared_ptr<VoxelFragment>, 4> fragmentVariants
)
: fragmentVariants(std::move(fragmentVariants)) {
}
LuaVoxelFragment::~LuaVoxelFragment() { LuaVoxelFragment::~LuaVoxelFragment() {
} }
static int l_crop(lua::State* L) { static int l_crop(lua::State* L) {
if (auto fragment = touserdata<LuaVoxelFragment>(L, 1)) { if (auto fragment = touserdata<LuaVoxelFragment>(L, 1)) {
fragment->getFragment()->crop(); for (size_t i = 0; i < 4; i++) {
fragment->getFragment(i)->crop();
}
} }
return 0; return 0;
} }
@ -24,9 +29,9 @@ static int l_crop(lua::State* L) {
static int l_place(lua::State* L) { static int l_place(lua::State* L) {
if (auto fragment = touserdata<LuaVoxelFragment>(L, 1)) { if (auto fragment = touserdata<LuaVoxelFragment>(L, 1)) {
auto offset = tovec3(L, 2); auto offset = tovec3(L, 2);
int rotation = tointeger(L, 3) & 0b11; int rotation = tointeger(L, 3);
fragment->getFragment()->place( fragment->getFragment(rotation)->place(
*scripting::level->chunks, offset, rotation *scripting::level->chunks, offset
); );
} }
return 0; return 0;
@ -50,7 +55,7 @@ static int l_meta_index(lua::State* L) {
if (isstring(L, 2)) { if (isstring(L, 2)) {
auto fieldname = tostring(L, 2); auto fieldname = tostring(L, 2);
if (!std::strcmp(fieldname, "size")) { if (!std::strcmp(fieldname, "size")) {
return pushivec(L, fragment->getFragment()->getSize()); return pushivec(L, fragment->getFragment(0)->getSize());
} else { } else {
auto found = methods.find(tostring(L, 2)); auto found = methods.find(tostring(L, 2));
if (found != methods.end()) { if (found != methods.end()) {

View File

@ -171,7 +171,7 @@ void VoxelFragment::prepare(const Content& content) {
} }
void VoxelFragment::place( void VoxelFragment::place(
GlobalChunks& chunks, const glm::ivec3& offset, ubyte rotation GlobalChunks& chunks, const glm::ivec3& offset
) { ) {
auto& structVoxels = getRuntimeVoxels(); auto& structVoxels = getRuntimeVoxels();
for (int y = 0; y < size.y; y++) { for (int y = 0; y < size.y; y++) {

View File

@ -45,8 +45,7 @@ public:
/// @brief Place fragment to the world /// @brief Place fragment to the world
/// @param offset target location /// @param offset target location
/// @param rotation rotation index void place(GlobalChunks& chunks, const glm::ivec3& offset);
void place(GlobalChunks& chunks, const glm::ivec3& offset, ubyte rotation);
/// @brief Create structure copy rotated 90 deg. clockwise /// @brief Create structure copy rotated 90 deg. clockwise
std::unique_ptr<VoxelFragment> rotated(const Content& content) const; std::unique_ptr<VoxelFragment> rotated(const Content& content) const;