From 9cdf3e29cc448ba910c52b753d6d7d1ab6087166 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 15 Jul 2024 05:42:09 +0300 Subject: [PATCH] add entities.raycast & update docs structure --- doc/en/block-properties.md | 6 +- doc/en/scripting.md | 163 +------------------- doc/en/scripting/builtins/libblock.md | 115 ++++++++++++++ doc/en/scripting/builtins/libentities.md | 26 ++++ doc/ru/block-properties.md | 8 +- doc/ru/scripting.md | 183 +---------------------- doc/ru/scripting/builtins/libblock.md | 143 ++++++++++++++++++ doc/ru/scripting/builtins/libentities.md | 26 ++++ src/logic/scripting/lua/libentity.cpp | 67 +++++++++ 9 files changed, 389 insertions(+), 348 deletions(-) create mode 100644 doc/en/scripting/builtins/libblock.md create mode 100644 doc/en/scripting/builtins/libentities.md create mode 100644 doc/ru/scripting/builtins/libblock.md create mode 100644 doc/ru/scripting/builtins/libentities.md diff --git a/doc/en/block-properties.md b/doc/en/block-properties.md index 602df3eb..19cd01d1 100644 --- a/doc/en/block-properties.md +++ b/doc/en/block-properties.md @@ -82,12 +82,12 @@ Block is not a physical obstacle if **false** An array of 6 numbers describing an offset an size of a block hitbox. Array *\[0.25, 0.0, 0.5, 0.75, 0.4, 0.3\]* describes hitbox width: -- 0.75m width (from east to west) -- 0.4m height -- 0.3m length (from south to north) - offset 0.25m east - offset 0.0m up - offset 0.5m north +- 0.75m width (from east to west) +- 0.4m height +- 0.3m length (from south to north) ### *grounded* diff --git a/doc/en/scripting.md b/doc/en/scripting.md index 1fd1260f..3b0c6bc7 100644 --- a/doc/en/scripting.md +++ b/doc/en/scripting.md @@ -9,6 +9,8 @@ Subsections: - [UI properties and methods](scripting/ui.md) - [Entities and components](scripting/ecs.md) - [Libraries](#) + - [block](scripting/builtins/libblock.md) + - [entities](scripting/builtins/libentities.md) - [mat4](scripting/builtins/libmat4.md) - [Module core:bit_converter](scripting/modules/core_bit_converter.md) - [Module core:data_buffer](scripting/modules/core_data_buffer.md) @@ -337,167 +339,6 @@ inventory.move(invA: int, slotA: int, invB: int, slotB: int) Move item from slotA of invA to slotB of invB. invA may be the same as invB. If slotB will be chosen automaticly if argument is not specified. -## *block* library - -```python -block.name(blockid: int) -> str -``` - -Returns block string ID (name) by index. - -```python -block.index(name: str) -> int -``` - -Returns block integer ID (index) by name. - -```python -block.material(blockid: int) -> str -``` - -Returns the id of the block material. - -```python -block.caption(blockid: int) -> str -``` - -Returns the block name displayed in the interface. - -```python -block.get(x: int, y: int, z: int) -> int -``` - -Returns integer ID by block position - -```python -block.get_states(x: int, y: int, z: int) -> int -``` - -Returns block state (rotation + additional information) as an integer. - -```python -block.set(x: int, y: int, z: int, id: int, states: int) -``` - -Set block with specified integer ID and state (default - 0) at specified position. - -> [!WARNING] -> `block.set` does not trigger on_placed. - -```python -block.is_solid_at(x: int, y: int, z: int) -> bool -``` - -Check if block at the specified position is solid. - -```python -block.is_replaceable_at(x: int, y: int, z: int) -> bool -``` -Check if block may be placed at specified position. (Examples: air, water, grass, flower) - -```python -block.defs_count() -> int -``` - -Returns count of available block IDs. - -Following three functions return direction vectors based on block rotation. - - -```python -block.get_X(x: int, y: int, z: int) -> int, int, int -``` - -Returns X: integer direction vector of the block at specified coordinates. -Example: no rotation: 1, 0, 0 - -```python -block.get_Y(x: int, y: int, z: int) -> int, int, int -``` - -Returns Y: integer direction vector of the block at specified coordinates. -Example: no rotation: 0, 1, 0 - -```python -block.get_Z(x: int, y: int, z: int) -> int, int, int -``` - -Returns Z: integer direction vector of the block at specified coordinates. -Example: no rotation: 0, 0, 1 - - -```python -block.get_rotation(x: int, y: int, z: int) -> int -``` - -Returns block rotation index based on used profile. - -```python -block.set_rotation(x: int, y: int, z: int, rotation: int) -``` - -Set block rotation by index. - -### Extended blocks - -Extended blocks are blocks with size greather than 1x1x1 - -```python -block.is_extended(id: int) -> bool -``` - -Checks whether the block is extended. - -```python -block.get_size(id: int) -> int, int, int -``` - -Returns the block size. - -```python -block.is_segment(x: int, y: int, z: int) -> bool -``` - -Checks whether the block is a non-origin segment of an extended block. - -```python -block.seek_origin(x: int, y: int, z: int) -> int, int, int -``` - -Returns the position of the main segment of an extended block or the original position, -if the block is not extended. - -### User bits - -Part of a voxel data used for scripting. Size: 8 bit. - -```python -block.get_user_bits(x: int, y: int, z: int, offset: int, bits: int) -> int -``` - -Get specified bits as an unsigned integer. - -```python -block.set_user_bits(x: int, y: int, z: int, offset: int, bits: int, value: int) -> int -``` -Set specified bits. - -```lua -block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: 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 -} or nil -``` - -Casts a ray from the start point in the direction of *dir*. Max_distance specifies the maximum ray length. - -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. - ## *item* library ```python diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md new file mode 100644 index 00000000..1b095afc --- /dev/null +++ b/doc/en/scripting/builtins/libblock.md @@ -0,0 +1,115 @@ +# *block* library + +```lua +-- Returns block string ID (name) by index. +block.name(blockid: int) -> str + +-- Returns block integer ID (index) by name. +block.index(name: str) -> int + +-- Returns the id of the block material. +block.material(blockid: int) -> str + +-- Returns the block name displayed in the UI. +block.caption(blockid: int) -> str + +-- Returns integer ID by block position +block.get(x: int, y: int, z: int) -> int + +-- Returns block state (rotation + additional information) as an integer. +-- Used to save complete block information. +block.get_states(x: int, y: int, z: int) -> int + +-- Set block with specified integer ID and state (default - 0) at specified position. +block.set(x: int, y: int, z: int, id: int, states: int) +``` + +> [!WARNING] +> `block.set` does not trigger on_placed. + +```lua +-- Check if block at the specified position is solid. +block.is_solid_at(x: int, y: int, z: int) -> bool + +-- Check if block may be placed at specified position. +-- (Examples: air, water, grass, flower) +block.is_replaceable_at(x: int, y: int, z: int) -> bool + +-- Returns count of available block IDs. +block.defs_count() -> int +``` + +## Rotation + +Following three functions return direction vectors based on block rotation. + + +```lua +-- Returns X: integer direction vector of the block at specified coordinates. +-- Example: no rotation: 1, 0, 0. +block.get_X(x: int, y: int, z: int) -> int, int, int + +-- Same for axis Y. Default: 0, 1, 0. +block.get_Y(x: int, y: int, z: int) -> int, int, int + +-- Same for axis Z. Default: 0, 0, 1. +block.get_Z(x: int, y: int, z: int) -> int, int, int + +-- Returns block rotation index based on used profile. +block.get_rotation(x: int, y: int, z: int) -> int + +-- Set block rotation by index. +block.set_rotation(x: int, y: int, z: int, rotation: int) +``` + +## Extended blocks + +Extended blocks are blocks with size greather than 1x1x1 + +```lua +-- Checks whether the block is extended. +block.is_extended(id: int) -> bool + +-- Returns the block size. +block.get_size(id: int) -> int, int, int + +-- Checks whether the block is a non-origin segment of an extended block. +block.is_segment(x: int, y: int, z: int) -> bool + +-- Returns the position of the main segment of an extended block +-- or the original position, if the block is not extended. +block.seek_origin(x: int, y: int, z: int) -> int, int, int +``` + +## User bits + +Part of a voxel data used for scripting. Size: 8 bit. + +```python +block.get_user_bits(x: int, y: int, z: int, offset: int, bits: int) -> int +``` + +Get specified bits as an unsigned integer. + +```python +block.set_user_bits(x: int, y: int, z: int, offset: int, bits: int, value: int) -> int +``` +Set specified bits. + +## Raycast + +```lua +block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: 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 +} or nil +``` + +Casts a ray from the start point in the direction of *dir*. Max_distance specifies the maximum ray length. + +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. diff --git a/doc/en/scripting/builtins/libentities.md b/doc/en/scripting/builtins/libentities.md new file mode 100644 index 00000000..c25f7301 --- /dev/null +++ b/doc/en/scripting/builtins/libentities.md @@ -0,0 +1,26 @@ +# Library *entities* + +The library is designed to work with a registry of entities. + +```lua +-- Returns an entity by unique identifier +-- The table returned is the same one available in the entity components. +entities.get(uid: int) -> table + +-- Creates the specified entity. +-- args - table of component parameter tables (ARGS variable) +-- args is optional +entities.spawn(name: str, pos: vec3, [optional] args: table) + +-- Checks the existence of an entity by a unique identifier. +entities.exists(uid: int) -> bool +``` + +```lua +entities.raycast(start: vec3, dir: vec3, max_distance: number, + ignore: int, [optional] destination: 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. + +Accordingly, this will affect the presence of the *entity* and *block* fields. diff --git a/doc/ru/block-properties.md b/doc/ru/block-properties.md index 1c9c92ed..495fd8ca 100644 --- a/doc/ru/block-properties.md +++ b/doc/ru/block-properties.md @@ -86,13 +86,13 @@ Числа указываются в диапазоне [0.0, 1.0] - т.е в пределах блока. -Массив `[0.25, 0.0, 0.5, 0.75, 0.4, 0.3]` описывает хитбокс: -- шириной (с востока на запад) 0.75 м -- высотой 0.4 м -- длиной (с юга на север) 0.3 м +Массив `[0.25, 0.0, 0.5, 0.75, 0.4, 0.3]` описывает хитбокс: - смещен на 0.25 м на запад - смещен на 0.0 м вверх - смещен на 0.5 м на север +- шириной (с востока на запад) 0.75 м +- высотой 0.4 м +- длиной (с юга на север) 0.3 м ### Приземленность - *grounded* diff --git a/doc/ru/scripting.md b/doc/ru/scripting.md index 0ed31ba7..fdc55f22 100644 --- a/doc/ru/scripting.md +++ b/doc/ru/scripting.md @@ -9,7 +9,10 @@ - [Свойства и методы UI элементов](scripting/ui.md) - [Сущности и компоненты](scripting/ecs.md) - [Библиотеки](#) + - [block](scripting/builtins/libblock.md) + - [entities](scripting/builtins/libentities.md) - [mat4](scripting/builtins/libmat4.md) + - [vec2, vec3, vec4](scripting/builtins/libvecn.md) - [Модуль core:bit_converter](scripting/modules/core_bit_converter.md) - [Модуль core:data_buffer](scripting/modules/core_data_buffer.md) - [Модули core:vector2, core:vector3](scripting/modules/core_vector2_vector3.md) @@ -332,186 +335,6 @@ inventory.move(invA: int, slotA: int, invB: int, slotB: int) invA и invB могут указывать на один инвентарь. slotB будет выбран автоматически, если не указывать явно. -## Библиотека *block* - -```python -block.name(blockid: int) -> str -``` - -Возвращает строковый id блока по его числовому id. - -```python -block.index(name: str) -> int -``` - -Возвращает числовой id блока, принимая в качестве агрумента строковый. - -```python -block.material(blockid: int) -> str -``` - -Возвращает id материала блока. - -```python -block.caption(blockid: int) -> str -``` - -Возвращает название блока, отображаемое в интерфейсе. - -```python -block.get(x: int, y: int, z: int) -> int -``` - -Возвращает числовой id блока на указанных координатах. Если чанк на указанных координатах не загружен, возвращает -1. - -```python -block.get_states(x: int, y: int, z: int) -> int -``` - -Возвращает состояние (поворот + доп. информация) в виде целого числа - -```python -block.set(x: int, y: int, z: int, id: int, states: int) -``` - -Устанавливает блок с заданным числовым id и состоянием (0 - по-умолчанию) на заданных координатах. - -> [!WARNING] -> `block.set` не вызывает событие on_placed. - -```python -block.is_solid_at(x: int, y: int, z: int) -> bool -``` - -Проверяет, является ли блок на указанных координатах полным - -```python -block.is_replaceable_at(x: int, y: int, z: int) -> bool -``` -Проверяет, можно ли на заданных координатах поставить блок (примеры: воздух, трава, цветы, вода) - -```python -block.defs_count() -> int -``` - -Возвращает количество id доступных в движке блоков - -```python -block.get_picking_item(id: int) -> int -``` - -Возвращает числовой id предмета, указанного в свойстве *picking-item*. - -```lua -block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table) -> { - block: int, -- id блока - endpoint: vec3, -- точка касания луча - iendpoint: vec3, -- позиция блока, которого касается луч - length: number, -- длина луча - normal: vec3 -- вектор нормали поверхности, которой касается луч -} или nil -``` - -Бросает луч из точки start в направлении dir. Max_distance указывает максимальную длину луча. - -Функция возвращает таблицу с результатами или nil, если луч не касается блока. - -Для результата будет использоваться целевая (dest) таблица вместо создания новой, если указан опциональный аргумент. - -### Вращение - -Следующие функции используется для учёта вращения блока при обращении к соседним блокам или других целей, где направление блока имеет решающее значение. - - -```lua --- Возвращает целочисленный единичный вектор X блока на указанных координатах с учётом его вращения (три целых числа). --- Если поворот отсутствует, возвращает 1, 0, 0 -block.get_X(x: int, y: int, z: int) -> int, int, int - --- То же, но для оси Y (по-умолчанию 0, 1, 0) -block.get_Y(x: int, y: int, z: int) -> int, int, int - --- То же, но для оси Z (по-умолчанию 0, 0, 1) -block.get_Z(x: int, y: int, z: int) -> int, int, int - --- Возвращает индекс поворота блока в его профиле вращения (не превышает 7). -block.get_rotation(x: int, y: int, z: int) -> int - --- Устанавливает вращение блока по индексу в его профиле вращения. -block.set_rotation(x: int, y: int, z: int, rotation: int) - --- Возвращает имя профиля вращения (none/pane/pipe) -block.get_rotation_profile(id: int) -> str -``` - -### Расширенные блоки - -Расширенные блоки - те, размер которых превышает 1x1x1 - -```python -block.is_extended(id: int) -> bool -``` - -Проверяет, является ли блок расширенным. - -```python -block.get_size(id: int) -> int, int, int -``` - -Возвращает размер блока. - -```python -block.is_segment(x: int, y: int, z: int) -> bool -``` - -Проверяет является ли блок сегментом расширенного блока, не являющимся главным. - -```python -block.seek_origin(x: int, y: int, z: int) -> int, int, int -``` - -Возвращает позицию главного сегмента расширенного блока или исходную позицию, -если блок не являющийся расширенным. - -### Пользовательские биты - -Выделенная под использования в скриптах часть поля `voxel.states` хранящего доп-информацию о вокселе, такую как вращение блока. На данный момент выделенная часть составляет 8 бит. - -```python -block.get_user_bits(x: int, y: int, z: int, offset: int, bits: int) -> int -``` - -Возвращает выбранное число бит с указанного смещения в виде целого беззнакового числа - -```python -block.set_user_bits(x: int, y: int, z: int, offset: int, bits: int, value: int) -> int -``` -Записывает указанное число бит значения value в user bits по выбранному смещению - -### Физика - -Информация свойствах блока, используемых физическим движком. - -```lua --- Возвращает массив из двух векторов (массивов из 3 чисел): --- 1. Минимальная точка хитбокса --- 2. Размер хитбокса --- rotation_index - индекс поворота блока -block.get_hitbox(id: int, rotation_index: int) -> {vec3, vec3} -``` - -### Модель - -Информация о модели блока. - -```lua --- возвращает тип модели блока (block/aabb/custom/...) -block.get_model(id: int) -> str - --- возвращает массив из 6 текстур, назначенных на стороны блока -block.get_textures(id: int) -> таблица строк -``` - ## Библиотека item ```python diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md new file mode 100644 index 00000000..8e3926d8 --- /dev/null +++ b/doc/ru/scripting/builtins/libblock.md @@ -0,0 +1,143 @@ +# Библиотека *block* + +```lua +-- Возвращает строковый id блока по его числовому id. +block.name(blockid: int) -> str + +-- Возвращает числовой id блока, принимая в качестве агрумента строковый +block.index(name: str) -> int + +-- Возвращает id материала блока. +block.material(blockid: int) -> str + +-- Возвращает название блока, отображаемое в интерфейсе. +block.caption(blockid: int) -> str + +-- Возвращает числовой id блока на указанных координатах. +-- Если чанк на указанных координатах не загружен, возвращает -1. +block.get(x: int, y: int, z: int) -> int + +-- Возвращает состояние (поворот + доп. информация) в виде целого числа +block.get_states(x: int, y: int, z: int) -> int + +-- Устанавливает блок с заданным числовым id и состоянием (0 - по-умолчанию) на заданных координатах. +block.set(x: int, y: int, z: int, id: int, states: int) +``` + +> [!WARNING] +> `block.set` не вызывает событие on_placed. + +```lua +-- Проверяет, является ли блок на указанных координатах полным +block.is_solid_at(x: int, y: int, z: int) -> bool + +-- Проверяет, можно ли на заданных координатах поставить блок +-- (примеры: воздух, трава, цветы, вода) +block.is_replaceable_at(x: int, y: int, z: int) -> bool + +-- Возвращает количество id доступных в загруженном контенте блоков +block.defs_count() -> int + +-- Возвращает числовой id предмета, указанного в свойстве *picking-item*. +block.get_picking_item(id: int) -> int +``` + +### Raycast + +```lua +block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table) -> { + block: int, -- id блока + endpoint: vec3, -- точка касания луча + iendpoint: vec3, -- позиция блока, которого касается луч + length: number, -- длина луча + normal: vec3 -- вектор нормали поверхности, которой касается луч +} или nil +``` + +Бросает луч из точки start в направлении dir. Max_distance указывает максимальную длину луча. + +Функция возвращает таблицу с результатами или nil, если луч не касается блока. + +Для результата будет использоваться целевая (dest) таблица вместо создания новой, если указан опциональный аргумент. + +## Вращение + +Следующие функции используется для учёта вращения блока при обращении к соседним блокам или других целей, где направление блока имеет решающее значение. + + +```lua +-- Возвращает целочисленный единичный вектор X блока на указанных координатах с учётом его вращения (три целых числа). +-- Если поворот отсутствует, возвращает 1, 0, 0 +block.get_X(x: int, y: int, z: int) -> int, int, int + +-- То же, но для оси Y (по-умолчанию 0, 1, 0) +block.get_Y(x: int, y: int, z: int) -> int, int, int + +-- То же, но для оси Z (по-умолчанию 0, 0, 1) +block.get_Z(x: int, y: int, z: int) -> int, int, int + +-- Возвращает индекс поворота блока в его профиле вращения (не превышает 7). +block.get_rotation(x: int, y: int, z: int) -> int + +-- Устанавливает вращение блока по индексу в его профиле вращения. +block.set_rotation(x: int, y: int, z: int, rotation: int) + +-- Возвращает имя профиля вращения (none/pane/pipe) +block.get_rotation_profile(id: int) -> str +``` + +## Расширенные блоки + +Расширенные блоки - те, размер которых превышает 1x1x1 + +```lua +-- Проверяет, является ли блок расширенным. +block.is_extended(id: int) -> bool + +-- Возвращает размер блока. +block.get_size(id: int) -> int, int, int + +-- Проверяет является ли блок сегментом расширенного блока, не являющимся главным. +block.is_segment(x: int, y: int, z: int) -> bool + +-- Возвращает позицию главного сегмента расширенного блока или исходную позицию, +-- если блок не является расширенным. +block.seek_origin(x: int, y: int, z: int) -> int, int, int +``` + +## Пользовательские биты + +Выделенная под использования в скриптах часть поля `voxel.states` хранящего доп-информацию о вокселе, такую как вращение блока. На данный момент выделенная часть составляет 8 бит. + +```lua +-- Возвращает выбранное число бит с указанного смещения в виде целого беззнакового числа +block.get_user_bits(x: int, y: int, z: int, offset: int, bits: int) -> int + +-- Записывает указанное число бит значения value в user bits по выбранному смещению +block.set_user_bits(x: int, y: int, z: int, offset: int, bits: int, value: int) -> int +``` + + +## Физика + +Информация свойствах блока, используемых физическим движком. + +```lua +-- Возвращает массив из двух векторов (массивов из 3 чисел): +-- 1. Минимальная точка хитбокса +-- 2. Размер хитбокса +-- rotation_index - индекс поворота блока +block.get_hitbox(id: int, rotation_index: int) -> {vec3, vec3} +``` + +## Модель + +Информация о модели блока. + +```lua +-- возвращает тип модели блока (block/aabb/custom/...) +block.get_model(id: int) -> str + +-- возвращает массив из 6 текстур, назначенных на стороны блока +block.get_textures(id: int) -> таблица строк +``` diff --git a/doc/ru/scripting/builtins/libentities.md b/doc/ru/scripting/builtins/libentities.md new file mode 100644 index 00000000..4a3e96a0 --- /dev/null +++ b/doc/ru/scripting/builtins/libentities.md @@ -0,0 +1,26 @@ +# Библиотека *entities* + +Библиотека предназначена для работы с реестром сущностей. + +```lua +-- Возвращает сущность по уникальному идентификатору +-- Возвращаемая таблица - та же, что доступна в компонентах сущности. +entities.get(uid: int) -> table + +-- Создает указанную сущность. +-- args - таблица таблиц параметров компонентов (переменная ARGS) +-- args не является обязательным +entities.spawn(name: str, pos: vec3, [optional] args: table) + +-- Проверяет наличие сущности по уникальному идентификатору. +entities.exists(uid: int) -> bool +``` + +```lua +entities.raycast(start: vec3, dir: vec3, max_distance: number, + ignore: int, [optional] destination: table) -> table или nil +``` + +Функция является расширенным вариантом [block.raycast](libblock.md#raycast). Возвращает таблицу с результатами если луч касается блока, либо сущности. + +Соответственно это повлияет на наличие полей *entity* и *block*. diff --git a/src/logic/scripting/lua/libentity.cpp b/src/logic/scripting/lua/libentity.cpp index 9cff1e6b..e6621658 100644 --- a/src/logic/scripting/lua/libentity.cpp +++ b/src/logic/scripting/lua/libentity.cpp @@ -6,6 +6,7 @@ #include "../../../physics/Hitbox.hpp" #include "../../../window/Camera.hpp" #include "../../../content/Content.hpp" +#include "../../../voxels/Chunks.hpp" #include "../../../engine.hpp" using namespace scripting; @@ -53,11 +54,77 @@ static int l_set_skeleton(lua::State* L) { return 0; } +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); + glm::vec3 end; + glm::ivec3 normal; + glm::ivec3 iend; + + blockid_t block = BLOCK_VOID; + + if (auto voxel = level->chunks->rayCast(start, dir, maxDistance, end, normal, iend)) { + maxDistance = glm::distance(start, end); + block = voxel->id; + } + if (auto ray = level->entities->rayCast(start, dir, maxDistance, ignore)) { + if (lua::gettop(L) >= 5) { + lua::pushvalue(L, 5); + } else { + lua::createtable(L, 0, 6); + } + + lua::pushvec3_arr(L, start + dir * ray->distance); + lua::setfield(L, "endpoint"); + + lua::pushvec3_arr(L, ray->normal); + lua::setfield(L, "normal"); + + lua::pushnumber(L, glm::distance(start, end)); + lua::setfield(L, "length"); + + lua::pushvec3_arr(L, iend); + lua::setfield(L, "iendpoint"); + + lua::pushinteger(L, block); + lua::setfield(L, "block"); + + lua::pushinteger(L, ray->entity); + lua::setfield(L, "entity"); + return 1; + } else if (block != BLOCK_VOID) { + if (lua::gettop(L) >= 5) { + lua::pushvalue(L, 5); + } else { + lua::createtable(L, 0, 5); + } + lua::pushvec3_arr(L, end); + lua::setfield(L, "endpoint"); + + lua::pushvec3_arr(L, normal); + lua::setfield(L, "normal"); + + lua::pushnumber(L, glm::distance(start, end)); + lua::setfield(L, "length"); + + lua::pushvec3_arr(L, iend); + lua::setfield(L, "iendpoint"); + + lua::pushinteger(L, block); + lua::setfield(L, "block"); + return 1; + } + return 0; +} + const luaL_Reg entitylib [] = { {"exists", lua::wrap}, {"spawn", lua::wrap}, {"despawn", lua::wrap}, {"get_skeleton", lua::wrap}, {"set_skeleton", lua::wrap}, + {"raycast", lua::wrap}, {NULL, NULL} };