Merge branch 'main' into heightmaps
This commit is contained in:
commit
fcd1339e5b
@ -115,17 +115,20 @@ Set specified bits.
|
||||
## Raycast
|
||||
|
||||
```lua
|
||||
block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: table) -> {
|
||||
block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: table, [optional] filter: table) -> {
|
||||
block: int, -- block id
|
||||
endpoint: vec3, -- point of the ray hit point
|
||||
iendpoint: vec3, -- position of the block hit by the ray
|
||||
length: number, -- ray length
|
||||
normal: vec3 -- normal vector of the surface hit by the ray
|
||||
normal: vec3, -- normal vector of the surface hit by the ray
|
||||
} or nil
|
||||
```
|
||||
|
||||
Casts a ray from the start point in the direction of *dir*. Max_distance specifies the maximum ray length.
|
||||
|
||||
Argument `filter` can be used to tell ray what blocks can be skipped(passed through) during ray-casting.
|
||||
To use filter `dest` argument must be filled with some value(can be nil), it's done for backwards compatability
|
||||
|
||||
The function returns a table with the results or nil if the ray does not hit any block.
|
||||
|
||||
The result will use the destination table instead of creating a new one if the optional argument specified.
|
||||
|
||||
@ -51,7 +51,7 @@ entities.get_all_in_radius(center: vec3, radius: number) -> array<int>
|
||||
|
||||
```lua
|
||||
entities.raycast(start: vec3, dir: vec3, max_distance: number,
|
||||
ignore: int, [optional] destination: table) -> table or nil
|
||||
ignore: int, [optional] destination: table, [optional] filter: table) -> table or nil
|
||||
```
|
||||
|
||||
The function is an extended version of [block.raycast](libblock.md#raycast). Returns a table with the results if the ray touches a block or entity.
|
||||
|
||||
@ -60,17 +60,20 @@ block.get_picking_item(id: int) -> int
|
||||
### Raycast
|
||||
|
||||
```lua
|
||||
block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table) -> {
|
||||
block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table, [опционально] filter: table) -> {
|
||||
block: int, -- id блока
|
||||
endpoint: vec3, -- точка касания луча
|
||||
iendpoint: vec3, -- позиция блока, которого касается луч
|
||||
length: number, -- длина луча
|
||||
normal: vec3 -- вектор нормали поверхности, которой касается луч
|
||||
normal: vec3, -- вектор нормали поверхности, которой касается луч
|
||||
} или nil
|
||||
```
|
||||
|
||||
Бросает луч из точки start в направлении dir. Max_distance указывает максимальную длину луча.
|
||||
|
||||
Аргумент `filter` позволяет указать какие блоки являются "прозрачными" для луча, прим.: {"base:glass","base:water"}.
|
||||
Для использования агрумент `dest` нужно чем-то заполнить(можно nil), это сделано для обратной совместимости
|
||||
|
||||
Функция возвращает таблицу с результатами или nil, если луч не касается блока.
|
||||
|
||||
Для результата будет использоваться целевая (dest) таблица вместо создания новой, если указан опциональный аргумент.
|
||||
|
||||
@ -51,7 +51,7 @@ entities.get_all_in_radius(center: vec3, radius: number) -> array<int>
|
||||
|
||||
```lua
|
||||
entities.raycast(start: vec3, dir: vec3, max_distance: number,
|
||||
ignore: int, [optional] destination: table) -> table или nil
|
||||
ignore: int, [optional] destination: table, [optional] filter: table) -> table или nil
|
||||
```
|
||||
|
||||
Функция является расширенным вариантом [block.raycast](libblock.md#raycast). Возвращает таблицу с результатами если луч касается блока, либо сущности.
|
||||
|
||||
@ -353,13 +353,30 @@ static int l_raycast(lua::State* L) {
|
||||
auto start = lua::tovec<3>(L, 1);
|
||||
auto dir = lua::tovec<3>(L, 2);
|
||||
auto maxDistance = lua::tonumber(L, 3);
|
||||
std::set<blockid_t> filteredBlocks {};
|
||||
if (lua::gettop(L) >= 5) {
|
||||
if (lua::istable(L, 5)) {
|
||||
int addLen = lua::objlen(L, 5);
|
||||
for (int i = 0; i < addLen; i++) {
|
||||
lua::rawgeti(L, i + 1, 5);
|
||||
auto blockName = std::string(lua::tostring(L, -1));
|
||||
Block* block = content->blocks.find(blockName);
|
||||
if (block != nullptr) {
|
||||
filteredBlocks.insert(block->rt.id);
|
||||
}
|
||||
lua::pop(L);
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("table expected for filter");
|
||||
}
|
||||
}
|
||||
glm::vec3 end;
|
||||
glm::ivec3 normal;
|
||||
glm::ivec3 iend;
|
||||
if (auto voxel = level->chunks->rayCast(
|
||||
start, dir, maxDistance, end, normal, iend
|
||||
start, dir, maxDistance, end, normal, iend, filteredBlocks
|
||||
)) {
|
||||
if (lua::gettop(L) >= 4) {
|
||||
if (lua::gettop(L) >= 4 && !lua::isnil(L, 4)) {
|
||||
lua::pushvalue(L, 4);
|
||||
} else {
|
||||
lua::createtable(L, 0, 5);
|
||||
@ -452,4 +469,5 @@ const luaL_Reg blocklib[] = {
|
||||
{"raycast", lua::wrap<l_raycast>},
|
||||
{"compose_state", lua::wrap<l_compose_state>},
|
||||
{"decompose_state", lua::wrap<l_decompose_state>},
|
||||
{NULL, NULL}};
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "objects/rigging.hpp"
|
||||
#include "physics/Hitbox.hpp"
|
||||
#include "voxels/Chunks.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
|
||||
using namespace scripting;
|
||||
@ -118,7 +119,25 @@ static int l_raycast(lua::State* L) {
|
||||
auto start = lua::tovec<3>(L, 1);
|
||||
auto dir = lua::tovec<3>(L, 2);
|
||||
auto maxDistance = lua::tonumber(L, 3);
|
||||
auto ignore = lua::tointeger(L, 4);
|
||||
auto ignoreEntityId = lua::tointeger(L, 4);
|
||||
std::set<blockid_t> filteredBlocks {};
|
||||
if (lua::gettop(L) >= 6) {
|
||||
if (lua::istable(L, 6)) {
|
||||
int addLen = lua::objlen(L, 6);
|
||||
for (int i = 0; i < addLen; i++) {
|
||||
lua::rawgeti(L, i + 1, 6);
|
||||
auto blockName = std::string(lua::tostring(L, -1));
|
||||
Block* block = content->blocks.find(blockName);
|
||||
if (block != nullptr) {
|
||||
filteredBlocks.insert(block->rt.id);
|
||||
}
|
||||
lua::pop(L);
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("table expected for filter");
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 end;
|
||||
glm::ivec3 normal;
|
||||
glm::ivec3 iend;
|
||||
@ -126,13 +145,14 @@ static int l_raycast(lua::State* L) {
|
||||
blockid_t block = BLOCK_VOID;
|
||||
|
||||
if (auto voxel = level->chunks->rayCast(
|
||||
start, dir, maxDistance, end, normal, iend
|
||||
start, dir, maxDistance, end, normal, iend, filteredBlocks
|
||||
)) {
|
||||
maxDistance = glm::distance(start, end);
|
||||
block = voxel->id;
|
||||
}
|
||||
if (auto ray = level->entities->rayCast(start, dir, maxDistance, ignore)) {
|
||||
if (lua::gettop(L) >= 5) {
|
||||
if (auto ray =
|
||||
level->entities->rayCast(start, dir, maxDistance, ignoreEntityId)) {
|
||||
if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) {
|
||||
lua::pushvalue(L, 5);
|
||||
} else {
|
||||
lua::createtable(L, 0, 6);
|
||||
@ -157,7 +177,7 @@ static int l_raycast(lua::State* L) {
|
||||
lua::setfield(L, "entity");
|
||||
return 1;
|
||||
} else if (block != BLOCK_VOID) {
|
||||
if (lua::gettop(L) >= 5) {
|
||||
if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) {
|
||||
lua::pushvalue(L, 5);
|
||||
} else {
|
||||
lua::createtable(L, 0, 5);
|
||||
@ -194,4 +214,5 @@ const luaL_Reg entitylib[] = {
|
||||
{"get_all_in_box", lua::wrap<l_get_all_in_box>},
|
||||
{"get_all_in_radius", lua::wrap<l_get_all_in_radius>},
|
||||
{"raycast", lua::wrap<l_raycast>},
|
||||
{NULL, NULL}};
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "debug/Logger.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#include "api_lua.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
|
||||
static debug::Logger logger("lua-debug");
|
||||
|
||||
@ -21,6 +23,128 @@ static int l_debug_log(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int MAX_DEPTH = 10;
|
||||
|
||||
int l_debug_print(lua::State* L) {
|
||||
auto addIndentation = [](int depth) {
|
||||
for (int i = 0; i < depth; ++i) std::cout << " ";
|
||||
};
|
||||
|
||||
auto printHexData = [](const void* ptr, size_t size) {
|
||||
const auto* bytePtr = reinterpret_cast<const uint8_t*>(ptr);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
std::cout << std::hex << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<int>(bytePtr[i])
|
||||
<< ((i + 1) % 8 == 0 && i + 1 < size ? "\n" : " ");
|
||||
}
|
||||
};
|
||||
|
||||
auto printEscapedString = [](const char* str) {
|
||||
while (*str) {
|
||||
switch (*str) {
|
||||
case '\\': std::cout << "\\\\"; break;
|
||||
case '\"': std::cout << "\\\""; break;
|
||||
case '\n': std::cout << "\\n"; break;
|
||||
case '\t': std::cout << "\\t"; break;
|
||||
case '\r': std::cout << "\\r"; break;
|
||||
case '\b': std::cout << "\\b"; break;
|
||||
case '\f': std::cout << "\\f"; break;
|
||||
default:
|
||||
if (iscntrl(static_cast<unsigned char>(*str))) {
|
||||
// Print other control characters in \xHH format
|
||||
std::cout << "\\x" << std::hex << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<int>(static_cast<unsigned char>(*str)) << std::dec;
|
||||
} else {
|
||||
std::cout << *str;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
};
|
||||
|
||||
std::function<void(int, int, bool)> debugPrint = [&](int index,
|
||||
int depth,
|
||||
bool is_key) {
|
||||
if (depth > MAX_DEPTH) {
|
||||
std::cout << "{...}";
|
||||
return;
|
||||
}
|
||||
switch (lua::type(L, index)) {
|
||||
case LUA_TSTRING:
|
||||
if (is_key){
|
||||
std::cout << lua::tostring(L, index);
|
||||
}else{
|
||||
std::cout << "\"";
|
||||
printEscapedString(lua::tostring(L, index));
|
||||
std::cout << "\"";
|
||||
}
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
std::cout << (lua::toboolean(L, index) ? "true" : "false");
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
std::cout << lua::tonumber(L, index);
|
||||
break;
|
||||
case LUA_TTABLE: {
|
||||
bool is_list = lua::objlen(L, index) > 0, hadItems = false;
|
||||
int absTableIndex =
|
||||
index > 0 ? index : lua::gettop(L) + index + 1;
|
||||
std::cout << "{";
|
||||
lua::pushnil(L);
|
||||
while (lua::next(L, absTableIndex) != 0) {
|
||||
if (hadItems)
|
||||
std::cout << "," << '\n';
|
||||
else
|
||||
std::cout << '\n';
|
||||
|
||||
addIndentation(depth + 1);
|
||||
if (!is_list) {
|
||||
debugPrint(-2, depth, true);
|
||||
std::cout << " = ";
|
||||
}
|
||||
debugPrint(-1, depth + 1, false);
|
||||
lua::pop(L, 1);
|
||||
hadItems = true;
|
||||
}
|
||||
if (hadItems) std::cout << '\n';
|
||||
addIndentation(depth);
|
||||
std::cout << "}";
|
||||
break;
|
||||
}
|
||||
case LUA_TFUNCTION:
|
||||
std::cout << "function(0x" << std::hex
|
||||
<< lua::topointer(L, index) << std::dec << ")";
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
std::cout << "userdata:\n";
|
||||
printHexData(lua::topointer(L, index), lua::objlen(L, index));
|
||||
break;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
std::cout << "lightuserdata:\n";
|
||||
printHexData(lua::topointer(L, index), sizeof(void*));
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
std::cout << "nil";
|
||||
break;
|
||||
default:
|
||||
std::cout << lua::type_name(L, lua::type(L, index));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
int n = lua::gettop(L);
|
||||
std::cout << "debug.print(" << '\n';
|
||||
for (int i = 1; i <= n; ++i) {
|
||||
addIndentation(1);
|
||||
debugPrint(i, 1, false);
|
||||
if (i < n) std::cout << "," << '\n';
|
||||
}
|
||||
std::cout << '\n' << ")" << std::endl;
|
||||
lua::pop(L, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initialize_libs_extends(lua::State* L) {
|
||||
if (lua::getglobal(L, "debug")) {
|
||||
lua::pushcfunction(L, lua::wrap<l_debug_error>);
|
||||
@ -32,6 +156,9 @@ void initialize_libs_extends(lua::State* L) {
|
||||
lua::pushcfunction(L, lua::wrap<l_debug_log>);
|
||||
lua::setfield(L, "log");
|
||||
|
||||
lua::pushcfunction(L, lua::wrap<l_debug_print>);
|
||||
lua::setfield(L, "print");
|
||||
|
||||
lua::pop(L);
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,7 +413,8 @@ voxel* Chunks::rayCast(
|
||||
float maxDist,
|
||||
glm::vec3& end,
|
||||
glm::ivec3& norm,
|
||||
glm::ivec3& iend
|
||||
glm::ivec3& iend,
|
||||
std::set<blockid_t> filter
|
||||
) {
|
||||
float px = start.x;
|
||||
float py = start.y;
|
||||
@ -453,8 +454,10 @@ voxel* Chunks::rayCast(
|
||||
if (voxel == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& def = indices->blocks.require(voxel->id);
|
||||
if (def.selectable) {
|
||||
if ((filter.empty() && def.selectable) ||
|
||||
(!filter.empty() && filter.find(def.rt.id) == filter.end())) {
|
||||
end.x = px + t * dx;
|
||||
end.y = py + t * dy;
|
||||
end.z = pz + t * dz;
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
@ -93,7 +94,8 @@ public:
|
||||
float maxLength,
|
||||
glm::vec3& end,
|
||||
glm::ivec3& norm,
|
||||
glm::ivec3& iend
|
||||
glm::ivec3& iend,
|
||||
std::set<blockid_t> filter = {}
|
||||
);
|
||||
|
||||
glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user