From 5e3373313b72e9004d5e5a00230987b137f9ccf9 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 31 Aug 2025 15:52:23 +0300 Subject: [PATCH] add pathfinding.set_avoided_tags --- doc/en/scripting/builtins/libpathfinding.md | 3 +++ doc/ru/scripting/builtins/libpathfinding.md | 3 +++ res/content/base/blocks/water.json | 2 +- res/scripts/components/pathfinding.lua | 1 + .../scripting/lua/libs/libpathfinding.cpp | 23 +++++++++++++++++++ src/voxels/Pathfinding.cpp | 20 ++++++++-------- src/voxels/Pathfinding.hpp | 6 +++-- 7 files changed, 46 insertions(+), 12 deletions(-) diff --git a/doc/en/scripting/builtins/libpathfinding.md b/doc/en/scripting/builtins/libpathfinding.md index 4d07fa75..106df755 100644 --- a/doc/en/scripting/builtins/libpathfinding.md +++ b/doc/en/scripting/builtins/libpathfinding.md @@ -54,4 +54,7 @@ pathfinding.pull_route(agent: int) --> table or nil --- Set the maximum number of visited blocks for the agent. Used to limit the amount of work of the pathfinding algorithm. pathfinding.set_max_visited(agent: int, max_visited: int) + +--- Set a list of tags defining avoided blocks +pathfinding.set_avoided_tags(agent: int, tags: table) ``` diff --git a/doc/ru/scripting/builtins/libpathfinding.md b/doc/ru/scripting/builtins/libpathfinding.md index d4f5ed7c..fc39b16f 100644 --- a/doc/ru/scripting/builtins/libpathfinding.md +++ b/doc/ru/scripting/builtins/libpathfinding.md @@ -54,4 +54,7 @@ pathfinding.pull_route(agent: int) --> table или nil --- Установка максимального количества посещенных блоков для агента. Используется для ограничения объема работы алгоритма поиска пути. pathfinding.set_max_visited(agent: int, max_visited: int) + +--- Установка перечня тегов, определяющих избегаемые блоки +pathfinding.set_avoided_tags(agent: int, tags: table) ``` diff --git a/res/content/base/blocks/water.json b/res/content/base/blocks/water.json index 0c2fa020..3bbc014b 100644 --- a/res/content/base/blocks/water.json +++ b/res/content/base/blocks/water.json @@ -8,5 +8,5 @@ "selectable": false, "replaceable": true, "translucent": true, - "tags": ["base:liquid"] + "tags": ["core:liquid"] } diff --git a/res/scripts/components/pathfinding.lua b/res/scripts/components/pathfinding.lua index 2a804a78..0296c4c7 100644 --- a/res/scripts/components/pathfinding.lua +++ b/res/scripts/components/pathfinding.lua @@ -6,6 +6,7 @@ local tsf = entity.transform agent = pathfinding.create_agent() pathfinding.set_max_visited(agent, 1e4) +pathfinding.set_avoided_tags(agent, {"core:liquid"}) function set_target(new_target) target = new_target diff --git a/src/logic/scripting/lua/libs/libpathfinding.cpp b/src/logic/scripting/lua/libs/libpathfinding.cpp index c0efe801..a52acea1 100644 --- a/src/logic/scripting/lua/libs/libpathfinding.cpp +++ b/src/logic/scripting/lua/libs/libpathfinding.cpp @@ -1,5 +1,6 @@ #include "api_lua.hpp" +#include "content/Content.hpp" #include "voxels/Pathfinding.hpp" #include "world/Level.hpp" @@ -99,6 +100,27 @@ static int l_set_jump_height(lua::State* L) { return 0; } +static int l_set_avoided_tags(lua::State* L) { + if (auto agent = get_agent(L)) { + if (!lua::istable(L, 2)) { + throw std::runtime_error("array of tags expected"); + } + agent->avoidTags.clear(); + int len = lua::objlen(L, 2); + for (int i = 1; i <= len; i++) { + lua::rawgeti(L, i); + if (lua::isstring(L, -1)) { + int index = content->getTagIndex(lua::tostring(L, -1)); + if (index != -1) { + agent->avoidTags.insert(index); + } + } + lua::pop(L); + } + } + return 0; +} + const luaL_Reg pathfindinglib[] = { {"create_agent", lua::wrap}, {"remove_agent", lua::wrap}, @@ -109,5 +131,6 @@ const luaL_Reg pathfindinglib[] = { {"pull_route", lua::wrap}, {"set_max_visited", lua::wrap}, {"set_jump_height", lua::wrap}, + {"set_avoided_tags", lua::wrap}, {NULL, NULL} }; diff --git a/src/voxels/Pathfinding.cpp b/src/voxels/Pathfinding.cpp index 125a23e6..2d7d4674 100644 --- a/src/voxels/Pathfinding.cpp +++ b/src/voxels/Pathfinding.cpp @@ -160,7 +160,7 @@ Route Pathfinding::perform(Agent& agent, int maxVisited) { auto pos = node.pos; int surface = - getSurfaceAt(pos + glm::ivec3(offset.x, 0, offset.y), 1); + getSurfaceAt(agent, pos + glm::ivec3(offset.x, 0, offset.y), 1); if (surface == -1) { continue; @@ -214,7 +214,7 @@ const std::unordered_map& Pathfinding::getAgents() const { return agents; } -int Pathfinding::checkPoint(int x, int y, int z) { +int Pathfinding::checkPoint(const Agent& agent, int x, int y, int z) { auto vox = blocks_agent::get(chunks, x, y, z); if (vox == nullptr) { return OBSTACLE; @@ -223,27 +223,29 @@ int Pathfinding::checkPoint(int x, int y, int z) { if (def.obstacle) { return OBSTACLE; } - if (def.translucent) { - return NON_PASSABLE; + for (int tagIndex : agent.avoidTags) { + if (def.rt.tags.find(tagIndex) != def.rt.tags.end()) { + return NON_PASSABLE; + } } return PASSABLE; } -int Pathfinding::getSurfaceAt(const glm::ivec3& pos, int maxDelta) { +int Pathfinding::getSurfaceAt(const Agent& agent, const glm::ivec3& pos, int maxDelta) { using namespace blocks_agent; int status; int surface = pos.y; - if (checkPoint(pos.x, surface, pos.z) <= 0) { - if (checkPoint(pos.x, surface + 1, pos.z) <= 0) + if (checkPoint(agent, pos.x, surface, pos.z) <= 0) { + if (checkPoint(agent, pos.x, surface + 1, pos.z) <= 0) return NON_PASSABLE; else return surface + 1; - } else if ((status = checkPoint(pos.x, surface - 1, pos.z)) <= 0) { + } else if ((status = checkPoint(agent, pos.x, surface - 1, pos.z)) <= 0) { if (status == NON_PASSABLE) return NON_PASSABLE; return surface; - } else if (checkPoint(pos.x, surface - 2, pos.z) == 0) { + } else if (checkPoint(agent, pos.x, surface - 2, pos.z) == 0) { return surface - 1; } return NON_PASSABLE; diff --git a/src/voxels/Pathfinding.hpp b/src/voxels/Pathfinding.hpp index a92cafab..1d073186 100644 --- a/src/voxels/Pathfinding.hpp +++ b/src/voxels/Pathfinding.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ namespace voxels { glm::ivec3 target; Route route; State state {}; + std::set avoidTags; }; class Pathfinding { @@ -84,8 +86,8 @@ namespace voxels { std::unordered_map agents; int nextAgent = 1; - int getSurfaceAt(const glm::ivec3& pos, int maxDelta); + int getSurfaceAt(const Agent& agent, const glm::ivec3& pos, int maxDelta); - int checkPoint(int x, int y, int z); + int checkPoint(const Agent& agent, int x, int y, int z); }; }