diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
new file mode 100644
index 00000000..371e1ac1
--- /dev/null
+++ b/.github/workflows/macos.yml
@@ -0,0 +1,51 @@
+name: Macos Build
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build-dmg:
+ runs-on: macos-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: 'true'
+
+ - name: Install dependencies from brew
+ run: |
+ brew install glfw3 glew libpng openal-soft luajit libvorbis
+
+ - name: Install specific version of GLM
+ run: |
+ curl -O https://raw.githubusercontent.com/Homebrew/homebrew-core/5c7655a866646aa4b857c002b8ae5465b9d26f65/Formula/g/glm.rb
+ brew install --formula glm.rb
+
+ - name: Configure
+ run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_APPDIR=1
+
+ - name: Build
+ run: cmake --build build -t install
+
+ - name: Make fix_dylibs.sh executable
+ run: chmod +x fix_dylibs.sh
+
+ - name: Fix dylibs
+ run: ./fix_dylibs.sh VoxelEngine Release build
+
+ - name: Create DMG
+ run: |
+ mkdir VoxelEngineDmgContent
+ cp -r build/res VoxelEngineDmgContent/
+ cp -r build/VoxelEngine VoxelEngineDmgContent/
+ cp -r build/libs VoxelEngineDmgContent/libs
+ hdiutil create VoxelEngineMacApp.dmg -volname "VoxelEngine" -srcfolder VoxelEngineDmgContent -ov -format UDZO
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: VoxelEngineMacOs
+ path: VoxelEngineMacApp.dmg
\ No newline at end of file
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
new file mode 100644
index 00000000..46fe7122
--- /dev/null
+++ b/.github/workflows/windows.yml
@@ -0,0 +1,48 @@
+name: Windows Build
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build-windows:
+
+ strategy:
+ matrix:
+ include:
+ - os: windows-latest
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: 'true'
+
+ - name: Set up vcpkg
+ run: |
+ git clone https://github.com/microsoft/vcpkg.git
+ cd vcpkg
+ .\bootstrap-vcpkg.bat
+ .\vcpkg integrate install
+ cd ..
+ - name: Configure and build project with CMake and vcpkg
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_WINDOWS_VCPKG=ON ..
+ Remove-Item -Path CMakeFiles -Recurse -Force
+ cmake -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_WINDOWS_VCPKG=ON ..
+ cmake --build . --config Release
+ - name: Package for Windows
+ run: |
+ mkdir packaged
+ cp -r build/* packaged/
+ working-directory: ${{ github.workspace }}
+
+ - uses: actions/upload-artifact@v2
+ with:
+ name: Windows-Build
+ path: 'packaged/Release/*'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6b4e4bfd..2ec2faab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,9 @@ else()
-Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wundef
-Wwrite-strings -Wno-unused-parameter)
+ if (CMAKE_BUILD_TYPE MATCHES "Debug")
+ target_compile_options(${PROJECT_NAME} PRIVATE -Og)
+ endif()
endif()
if(VOXELENGINE_BUILD_WINDOWS_VCPKG AND WIN32)
@@ -98,6 +101,18 @@ if (WIN32)
set(VORBISLIB vorbis vorbisfile) # not tested
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/glfw)
endif()
+elseif(APPLE)
+ find_package(PkgConfig)
+ pkg_check_modules(LUAJIT REQUIRED luajit)
+ pkg_check_modules(VORBIS REQUIRED vorbis vorbisfile)
+ set(LUA_INCLUDE_DIR "/opt/homebrew/include/luajit-2.1")
+ set(LUA_LIBRARIES "/opt/homebrew/lib/libluajit-5.1.a")
+ message(STATUS "LUA Libraries: ${LUA_LIBRARIES}")
+ message(STATUS "LUA Include Dir: ${LUA_INCLUDE_DIR}")
+ find_package(PNG REQUIRED)
+ set(PNGLIB PNG::PNG)
+ set(VORBISLIB ${VORBIS_LDFLAGS})
+ message(STATUS "Vorbis Lib: ${VORBIS_LDFLAGS}")
else()
find_package(PkgConfig)
pkg_check_modules(LUAJIT REQUIRED luajit)
diff --git a/doc/en/8.Scripting.md b/doc/en/8.Scripting.md
index e18ab0ad..5aa1f8cb 100644
--- a/doc/en/8.Scripting.md
+++ b/doc/en/8.Scripting.md
@@ -52,10 +52,10 @@ player.set_pos(playerid: int, x: number, y: number, z: number)
Set player position
```python
-player.get_rot(playerid: int) -> number, number
+player.get_rot(playerid: int) -> number, number, number
```
-Returns x, y of camera rotation (radians)
+Returns x, y, z of camera rotation (radians)
```python
player.set_rot(playerid: int, x: number, y: number, z: number)
@@ -69,6 +69,20 @@ player.get_inventory(playerid: int) -> int, int
Returns player inventory ID and selected slot index (0-9)
+```python
+player.is_flight() -> bool
+player.set_flight(bool)
+```
+
+Getter and setter for player flight mode
+
+```python
+player.is_noclip() -> bool
+player.set_noclip(bool)
+```
+
+Getter and setter for player noclip mode (collisions disabled)
+
## *world* library
```python
diff --git a/doc/ru/5.XML-разметка-интерфейса.md b/doc/ru/5.XML-разметка-интерфейса.md
index 17f4e701..93c23c93 100644
--- a/doc/ru/5.XML-разметка-интерфейса.md
+++ b/doc/ru/5.XML-разметка-интерфейса.md
@@ -26,14 +26,31 @@
# Общие атрибуты элементов
+- `enabled` - при значении false блокирует элемент, в отличие от interactive, обозначая это состояние визуально.
- `id` - идентификатор элемента. Тип: строка.
- `pos` - позиция элемента. Тип: 2D вектор.
- `size` - размер элемента. Тип: 2D вектор.
+- `context` - указывает контекст перевода для `@`-строк.
- `color` - цвет элемента. Тип: RGBA цвет.
+- `hover-color` - цвет элемента при наведении курсора. Тип: RGBA цвет.
+- `pressed-color` - цвет элемента при нажатии на элемент. Тип: RGBA цвет.
- `margin` - внешний отступ элемента. Тип: 4D вектор.
Порядок: `"left,top,right,bottom"`
- `visible` - видимость элемента. Тип: логический ("true"/"false").
- `position-func` - поставщик позиции элемента (два числа), вызываемый при изменении размера контейнера, в котором находится элемент, либо при добавлении элемента в контейнер. Может быть вызван до вызова on_hud_open.
+- `size-func` - поставщик размера элемента (два числа), вызываемый при изменении размера контейнера, в котором находится элемент, либо при добавлении элемента в контейнер. Может быть вызван до вызова on_hud_open.
+- `onclick` - lua функция вызываемая при нажатии на элемент.
+- `ondoubleclick` - lua функция вызываемая при двойном нажатии на элемент.
+- `tooltip` - текст всплывающей подсказки
+- `tooltip-delay` - задержка появления всплывающей подсказки
+- `gravity` - автоматическое позиционирование элемента в контейнере. (Не работает в автоматических контейнерах, как panel). Значения: *top-left, top-center, top-right, center-left, center-center, center-right, bottom-left, bottom-center, bottom-right*.
+- `z-index` - определяет порядок элементов, при большем значении будет перекрывать элементы с меньшим.
+- `interactive` - при значении false наведение на элемент и все под-элементы будет игнорироваться.
+
+# Атрибуты шаблонов
+
+- `if` при значениях ('', 'false', 'nil') элемент будет проигнорирован, включая под-элементы.
+- `ifnot` то же, что и `if`, но с обратным условием.
# Общие атрибуты контейнеров
@@ -46,47 +63,69 @@
В число панелей также входят кнопки.
- `max-length` - максимальная длина, на которую растягивается панель до начала скроллинга (если scrollable = true). Тип: число
+- `orientation` - ориентация панели: horizontal/vertical.
# Основные элементы
-## Кнопка `button`
+## Кнопка - *button*
Внутренний текст - текст кнопки.
- `text-align` - выравнивание текста ("left", "center" или "right"). Тип: строка.
-- `onclick` - lua функция вызываемая при нажатии на кнопку.
-## Изображение `image`
+## Флажок - *checkbox*
+
+- `checked` - определяет состояние отметки.
+- `supplier` - поставщик состояния отметки (вызывается каждый кадр)
+- `consumer` - lua функция-приемник состояния отметки. Вызывается только при завершении ввода
+## Метка - *label*
+
+- `valign` - вертикальное выравнивание текста: top/center/bottom
+- `supplier` - поставщик текста (вызывается каждый кадр)
+- `autoresize` - автоматическое изменение размера элемента (по-умолчанию - false). Не влияет на размер шрифта.
+- `multiline` - разрешает отображение многострочного текста.
+- `text-wrap` - разрешает автоматический перенос текста (работает только при multiline: "true")
+
+## Изображение - *image*
- `src` - имя изображения в папке textures без указания расширения. Тип: строка. Например `gui/error`
-# Текстовое поле `textbox`
+## Текстовое поле - *textbox*
Внутренний текст - изначально введенный текст
- `placeholder` - текст подстановки (используется текстовое поле пусто)
+- `supplier` - поставщик текста (вызывается каждый кадр)
- `consumer` - lua функция-приемник введенного текста. Вызывается только при завершении ввода
-
-## Ползунок `trackbar`
+- `autoresize` - автоматическое изменение размера элемента (по-умолчанию - false). Не влияет на размер шрифта.
+- `multiline` - разрешает отображение многострочного текста.
+- `text-wrap` - разрешает автоматический перенос текста (работает только при multiline: "true")
+- `editable`- определяет возможность редактирования текста.
+- `error-color` - цвет при вводе некорректных данных (текст не проходит проверку валидатора). Тип: RGBA цвет.
+- `validator` - lua функция, проверяющая текст на корректность. Принимает на вход строку, возвращает true если текст корректен.
+- `onup` - lua функция вызываемая при нажатии стрелки вверх.
+- `ondown` - lua функция вызываемая при нажатии стрелки вниз.
+## Ползунок - *trackbar*
- `min` - минимальное значение. Тип: число. По-умолчанию: 0
- `max` - максимальное значение. Тип: число. По-умолчанию: 1
- `value` - изначальное значение. Тип: число. По-умолчанию: 0
- `step` - размер деления ползунка. Тип: число. По-умолчанию: 1
-- `track-width` - ширина указателя (в делениях). Тип: число. По-умолчанию: 1
+- `track-width` - ширина указателя (в пикселях). Тип: число. По-умолчанию: 12
+- `track-color` - цвет указателя при наведении курсора. Тип: RGBA цвет.
- `consumer` - lua функция-приемник установленного значения
- `supplier` - lua функция-поставщик значения
# Элементы инвентаря
-## Инвентарь `inventory`
+## Инвентарь - *inventory*
Элемент является контейнером. На данный момент не имеет специфических атрибутов.
> [!WARNING]
> Расположение инвентарей управляется движком и не может быть изменено свойствами pos, margin и т.д.
-## Одиночный слот `slot`
+## Одиночный слот - *slot*
Элемент должен находиться внутри `inventory` элемента, без посредников.
- `index` - индекс слота инвентаря. (Нумерация с 0)
@@ -95,7 +134,7 @@
- `updatefunc` - lua событие вызываемое при изменении содержимого слота
- `onrightclick` - lua событие вызываемое при использовании ПКМ. Передается id инвентаря и индекс слота
-## Решетка слотов `slots-grid`
+## Сетка слотов - *slots-grid*
Элемент должен находиться внутри `inventory` элемента, без посредников.
- `start-index` - индекс первого слота
diff --git a/doc/ru/8.Скриптинг.md b/doc/ru/8.Скриптинг.md
index 82f27159..f5ba82c2 100644
--- a/doc/ru/8.Скриптинг.md
+++ b/doc/ru/8.Скриптинг.md
@@ -2,11 +2,7 @@
В качестве языка сценариев используется LuaJIT
-## Функции, доступные в скриптах
-
```lua
-load_script("контентпак:scripts/имя_скрипта.lua") -- загружает скрипт, если ещё не загружен
-load_script("контентпак:scripts/имя_скрипта.lua", true) -- перезагружает скрипт
require "контентпак:имя_модуля" -- загружает lua модуль из папки modules (расширение не указывается)
```
@@ -46,10 +42,10 @@ player.set_pos(playerid: int, x: number, y: number, z: number)
Устанавливает x, y, z координаты игрока
```python
-player.get_rot(playerid: int) -> number, number
+player.get_rot(playerid: int) -> number, number, number
```
-Возвращает x, y вращения камеры (в радианах)
+Возвращает x, y, z вращения камеры (в радианах)
```python
player.set_rot(playerid: int, x: number, y: number, z: number)
@@ -63,8 +59,37 @@ player.get_inventory(playerid: int) -> int, int
Возвращает id инвентаря игрока и индекс выбранного слота (от 0 до 9)
+```python
+player.is_flight() -> bool
+player.set_flight(bool)
+```
+
+Геттер и сеттер режима полета
+
+```python
+player.is_noclip() -> bool
+player.set_noclip(bool)
+```
+
+Геттер и сеттер noclip режима (выключенная коллизия игрока)
+
+```python
+player.get_selected_block(playerid: int) -> x,y,z
+```
+
+Возвращает координаты выделенного блока, либо nil
+
## Библиотека world
+```python
+world.get_list() -> массив таблиц {
+ name: str,
+ icon: str
+}
+```
+
+Возвращает информацию о мирах: название и предпросмотр (автоматически загружаемая текстура).
+
```python
world.get_day_time() -> number
```
@@ -89,6 +114,12 @@ world.get_seed() -> int
Возвращает зерно мира.
+```python
+world.exists() -> bool
+```
+
+Проверяет существование мира по имени.
+
## Библиотека pack
```python
@@ -109,6 +140,38 @@ pack.get_installed() -> массив строк
Возращает id всех установленных в мире контент-паков
+```python
+pack.get_available() -> массив строк
+```
+
+Возвращает id всех доступных, но не установленных в мире контент-паков
+
+```python
+pack.get_base_packs() -> массив строк
+```
+
+Возвращает id всех базовых паков (неудаляемых)
+
+```python
+pack.get_info(packid: str) -> {
+ id: str,
+ title: str,
+ creator: str,
+ description: str,
+ version: str,
+ icon: str,
+ dependencies: опциональный массив строк
+}
+```
+
+Возвращает информацию о паке (не обязательно установленном).
+- icon - название текстуры предпросмотра (загружается автоматически)
+- dependencies - строки в формате `{lvl}{id}`, где lvl:
+ - `!` - required
+ - `?` - optional
+ - `~` - weak
+ например `!teal`
+
## Библиотека gui
Библиотека содержит функции для доступа к свойствам UI элементов. Вместо gui следует использовать объектную обертку, предоставляющую доступ к свойствам через мета-методы __index, __newindex:
@@ -120,6 +183,33 @@ indentory_doc.some_button.text = "new text"
В скрипте макета `layouts/файл_макета.xml` - `layouts/файл_макета.xml.lua` уже доступна переменная **document** содержащая объект класса Document
+```python
+gui.str(text: str, context: str) -> str
+```
+
+Возращает переведенный текст.
+
+```python
+gui.get_viewport() -> {int, int}
+```
+
+Возвращает размер главного контейнера (окна).
+
+```python
+gui.get_env(document: str) -> table
+```
+
+Возвращает окружение (таблица глобальных переменных) указанного документа.
+
+```python
+get_locales_info() -> таблица таблиц где
+ ключ - id локали в формате isolangcode_ISOCOUNTRYCODE
+ значение - таблица {
+ name: str # название локали на её языке
+ }
+```
+
+Возвращает информацию о всех загруженных локалях (res/texts/\*).
## Библиотека inventory
Библиотека функций для работы с инвентарем.
@@ -197,6 +287,18 @@ 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
```
@@ -359,206 +461,27 @@ hud.close(layoutid: str)
hud.get_block_inventory() -> int
```
-Получить ID инвентаря открытого блока или 0
-
-## События блоков
-
-```lua
-function on_placed(x, y, z, playerid)
-```
-
-Вызывается после установки блока игроком
-
-```lua
-function on_broken(x, y, z, playerid)
-```
-
-Вызывается после разрушения блока игроком
-
-```lua
-function on_interact(x, y, z, playerid) -> bool
-```
-
-Вызывается при нажатии на блок ПКМ. Предотвращает установку блоков, если возвращает `true`
-
-```lua
-function on_update(x, y, z)
-```
-
-Вызывается при обновлении блока (если изменился соседний блок)
-
-```lua
-function on_random_update(x, y, z)
-```
-
-Вызывается в случайные моменты времени (рост травы на блоках земли)
-
-```lua
-function on_blocks_tick(tps: int)
-```
-
-Вызывается tps (20) раз в секунду
-
-## События предметов
-
-```lua
-function on_use(playerid: int)
-```
-
-Вызывается при нажатии ПКМ не на блок.
-
-```lua
-function on_use_on_block(x: int, y: int, z: int, playerid: int)
-```
-
-Вызывается при нажатии ПКМ на блок. Предотвращает установку блока, прописанного в `placing-block` если возвращает `true`
-
-```lua
-function on_block_break_by(x: int, y: int, z: int, playerid: int)
-```
-
-Вызывается при нажатии ЛКМ на блок (в т.ч неразрушимый). Предотвращает разрушение блока, если возвращает `true`
-
-## События мира
-
-События мира для контент-пака прописываются в `scripts/world.lua`
-
-```lua
-function on_world_open()
-```
-
-Вызывается при загрузке мира
-
-```lua
-function on_world_save()
-```
-
-Вызывается перед сохранением мира
-
-```lua
-function on_world_tick()
-```
-
-Вызывается 20 раз в секунду
-
-```lua
-function on_world_quit()
-```
-
-Вызывается при выходе из мира (после сохранения)
-
-## События макета
-
-События прописываются в файле `layouts/имя_макета.xml.lua`.
-
-```lua
-function on_open(invid: int, x: int, y: int, z: int)
-```
-
-Вызывается при добавлении элемента на экран.
-При отсутствии привязки к инвентарю invid будет равен 0.
-При отсутствии привязки к блоку x, y, z так же будут равны 0.
-
-```lua
-function on_close(invid: int)
-```
-
-Вызывается при удалении элемента с экрана.
-
-## События HUD
-
-События связанные с игровым интерфейсом прописываются в файле `scripts/hud.lua`
-
-```lua
-function on_hud_open(playerid: int)
-```
-
-Вызывается после входа в мир, когда становится доступна библиотека hud. Здесь на экран добавляются постоянные элементы.
-
-```lua
-function on_hud_close(playerid: int)
-```
-
-Вызывается при выходе из мира, перед его сохранением.
-
-## Библиотеки движка
-
-### file
-
-Библиотека функций для работы с файлами
+Дает ID инвентаря открытого блока или 0
```python
-file.resolve(путь: str) -> str
+hud.get_player() -> int
```
-Функция приводит запись `точка_входа:путь` (например `user:worlds/house1`) к обычному пути. (например `C://Users/user/.voxeng/worlds/house1`)
-
-> [!NOTE]
-> Функцию не нужно использовать в сочетании с другими функциями из библиотеки, так как они делают это автоматически
-
-Возвращаемый путь не является каноническим и может быть как абсолютным, так и относительным.
+Дает ID игрока, к которому привязан пользовательский интерфейс
```python
-file.read(путь: str) -> str
+hud.pause()
```
-Читает весь текстовый файл и возвращает в виде строки
+Открывает меню паузы
```python
-file.read_bytes(путь: str) -> array of integers
+hud.resume()
```
-Читает файл в массив байт.
+Закрывает меню паузы.
-```python
-file.write(путь: str, текст: str) -> nil
-```
-
-Записывает текст в файл (с перезаписью)
-
-```python
-file.write_bytes(путь: str, data: array of integers)
-```
-
-Записывает массив байт в файл (с перезаписью)
-
-```python
-file.length(путь: str) -> int
-```
-
-Возвращает размер файла в байтах, либо -1, если файл не найден
-
-```python
-file.exists(путь: str) -> bool
-```
-
-Проверяет, существует ли по данному пути файл или директория
-
-```python
-file.isfile(путь: str) -> bool
-```
-
-Проверяет, существует ли по данному пути файл
-
-```python
-file.isdir(путь: str) -> bool
-```
-
-Проверяет, существует ли по данному пути директория
-
-```python
-file.mkdir(путь: str) -> bool
-```
-
-Создает директорию. Возвращает true если была создана новая директория
-
-```python
-file.mkdirs(путь: str) -> bool
-```
-
-Создает всю цепочку директорий. Возвращает true если были созданы директории.
-
-### time
+## Библиотека time
```python
time.uptime() -> float
@@ -566,24 +489,8 @@ time.uptime() -> float
Возвращает время с момента запуска движка в секундах
-## Доступные модули
-
-### TOML сериализация/десериализация
-
-```lua
-local toml = require "core:toml"
-
-local t = {a=53, b=42, s="test", sub={x=1, y=6}}
-local s = toml.serialize(t)
-print(s)
-local t2 = toml.deserialize(s)
-```
-вывод:
-```toml
-b = 42
-s = "test"
-a = 53
-[sub]
-y = 6
-x = 1
+```python
+time.delta() -> float
```
+
+Возвращает дельту времени (время прошедшее с предыдущего кадра)
diff --git a/doc/ru/Консоль.md b/doc/ru/Консоль.md
new file mode 100644
index 00000000..a279be61
--- /dev/null
+++ b/doc/ru/Консоль.md
@@ -0,0 +1,109 @@
+# Консоль
+
+Для работы с командным интерпретатором предоставляется библиотека **console**
+
+## Создание команд
+
+Для создания команды консоли используется следующая функция:
+
+```python
+console.add_command(схема: str, исполнитель: function)
+```
+
+Схема имеет следующий синтаксис:
+
+```
+название позиционные параметры {именованные параметры}
+```
+
+Название может содержать:
+- латинницу
+- цифры (кроме первого символа)
+- `.`, `_`, `-`
+
+Позиционные параметры разделяются пробелами и имеют следующий синтаксис:
+
+```
+название:тип (вариант 1)
+название:тип=по-умолчанию (вариант 2)
+название:тип~центральное-значение (вариант 3)
+название:тип=по-умолчанию~центральное-значение (вариант 4)
+```
+
+Доступные типы:
+- **int** - целое число
+- **num** - дробное число
+- **str** - строка
+- **sel** - селектор (id объекта представленный целым числом)
+- **enum** - перечисление
+
+На вариантах 3 и 4 показан оператор `~` позволяющий использовать относительные значения. *Центральное значение* - значение, относительно которого будет указываться пользовательское. Например позиция игрока.
+
+Относительный оператор работает только с числами (num или int)
+
+В качестве центральных значений могут указываться переменные, назначаемые через **console.set**.
+
+Пример:
+
+```python
+x:num~pos.x
+```
+
+Переменные можно указывать и в качестве значений по-умолчанию, при использовании префикса `$`:
+
+```python
+t:int=$time
+```
+
+Перечисления указывазываются в формате:
+
+```python
+mode:[replace|destruct|none]
+```
+
+Либо через переменную:
+
+```python
+mode:enum $modes
+```
+
+Селекторы указываются с префиксом `@`. На данный момент являются заглушкой, по причине отсутствия объектной модели. Следует делать опциональными и использовать переменные:
+
+```python
+obj:sel=$obj.id # obj.id - id игрока
+```
+
+Именованные аргументы указываются в специальном блоке, ограниченном фигурными скобками `{ }` по той же схеме.
+
+Пример:
+
+```python
+eval name:str="World" {greeting:str='Hello'}
+```
+
+## Примеры схем команд
+
+Схемы существующих команд можно найти в файле `res/script/stdcmd.lua`.
+
+Пример - команда **tp**:
+
+```python
+tp obj:sel=$obj.id x:num~pos.x y:num~pos.y z:num~pos.z
+```
+
+Полный lua код создания команды:
+
+```lua
+console.add_command(
+ "tp obj:sel=$obj.id x:num~pos.x y:num~pos.y z:num~pos.z",
+ "Teleport object",
+ function (args, kwargs)
+ player.set_pos(unpack(args))
+ end
+)
+```
+
+- В args передаются готовые значения позиционных аргументов.
+- В kwargs передается таблица значений именованных аргументов.
+
+Проверку и приведение типов интерпретатор команд производит автоматически.
diff --git a/doc/ru/Пользовательский-ввод.md b/doc/ru/Пользовательский-ввод.md
new file mode 100644
index 00000000..e113b3b1
--- /dev/null
+++ b/doc/ru/Пользовательский-ввод.md
@@ -0,0 +1,59 @@
+# Пользовательский ввод
+
+Обработка нажатий клавиш и кнопок мыши обрабатываются через привязки (bindings), которые назначаются в паке, в файле `config/bindings.toml` в формате:
+
+```toml
+packid.binding.name="inputtype:codename"
+```
+
+- packid - опционально, но желательно
+- inputtype - key или mouse
+- codename - имя клавиши или кнопки мыши (left/right/middle)
+
+## Имена клавиш
+
+- space, backspace, tab, enter, caps-lock, escape
+- left-ctrl, left-shift, left-alt, left-super
+- right-ctrl, right-shift, right-alt, right-super
+- delete, home, end, insert, page-up, page-down
+- left, right, down, up
+- a..z
+- 0..9
+- f1..f25
+
+## Библиотека input
+
+```python
+input.keycode(keyname: str) -> int
+```
+
+Возвращает код клавиши по имени, либо -1
+
+```python
+input.mousecode(mousename: str) -> int
+```
+
+Возвращает код кнопки мыши по имени, либо -1
+
+```python
+input.add_callback(bindname: str, callback: function)
+```
+
+Назначает функцию, которая будет вызываться при активации привязки. Пример:
+```lua
+input.add_callback("hud.inventory", function ()
+ print("Inventory open key pressed")
+end)
+```
+
+```python
+input.get_mouse_pos() -> {int, int}
+```
+
+Возвращает позицию курсора на экране.
+
+```python
+input.get_bindings() -> массив строк
+```
+
+Возвращает названия всех доступных привязок.
diff --git a/doc/ru/События-движка.md b/doc/ru/События-движка.md
new file mode 100644
index 00000000..ecfd2db9
--- /dev/null
+++ b/doc/ru/События-движка.md
@@ -0,0 +1,126 @@
+# События движка
+
+## События блоков
+
+Функции для обработки событий, прописываемые в скрипте блока.
+
+```lua
+function on_placed(x, y, z, playerid)
+```
+
+Вызывается после установки блока игроком
+
+```lua
+function on_broken(x, y, z, playerid)
+```
+
+Вызывается после разрушения блока игроком
+
+```lua
+function on_interact(x, y, z, playerid) -> bool
+```
+
+Вызывается при нажатии на блок ПКМ. Предотвращает установку блоков, если возвращает `true`
+
+```lua
+function on_update(x, y, z)
+```
+
+Вызывается при обновлении блока (если изменился соседний блок)
+
+```lua
+function on_random_update(x, y, z)
+```
+
+Вызывается в случайные моменты времени (рост травы на блоках земли)
+
+```lua
+function on_blocks_tick(tps: int)
+```
+
+Вызывается tps (20) раз в секунду
+
+## События предметов
+
+Функции для обработки событий, прописываемые в скрипте предмета.
+
+```lua
+function on_use(playerid: int)
+```
+
+Вызывается при нажатии ПКМ не на блок.
+
+```lua
+
+function on_use_on_block(x: int, y: int, z: int, playerid: int)
+
+```
+
+Вызывается при нажатии ПКМ на блок. Предотвращает установку блока, прописанного в `placing-block` если возвращает `true`
+
+```lua
+function on_block_break_by(x: int, y: int, z: int, playerid: int)
+```
+
+Вызывается при нажатии ЛКМ на блок (в т.ч неразрушимый). Предотвращает разрушение блока, если возвращает `true`
+
+## События мира
+
+События мира для контент-пака прописываются в `scripts/world.lua`
+
+```lua
+function on_world_open()
+```
+
+Вызывается при загрузке мира
+
+```lua
+function on_world_save()
+```
+
+Вызывается перед сохранением мира
+
+```lua
+function on_world_tick()
+```
+
+Вызывается 20 раз в секунду
+
+```lua
+function on_world_quit()
+```
+
+Вызывается при выходе из мира (после сохранения)
+## События макета
+
+События прописываются в файле `layouts/имя_макета.xml.lua`.
+
+```lua
+function on_open(invid: int, x: int, y: int, z: int)
+```
+
+Вызывается при добавлении элемента на экран.
+- При отсутствии привязки к инвентарю invid будет равен 0.
+- При отсутствии привязки к блоку x, y, z так же будут равны 0.
+
+```lua
+function on_close(invid: int)
+```
+
+Вызывается при удалении элемента с экрана.
+
+## События HUD
+
+События связанные с игровым интерфейсом прописываются в файле `scripts/hud.lua`
+
+```lua
+function on_hud_open(playerid: int)
+```
+
+Вызывается после входа в мир, когда становится доступна библиотека hud. Здесь на экран добавляются постоянные элементы.
+
+```lua
+function on_hud_close(playerid: int)
+```
+
+Вызывается при выходе из мира, перед его сохранением.
diff --git a/doc/ru/Файловая-система-и-сериализация.md b/doc/ru/Файловая-система-и-сериализация.md
new file mode 100644
index 00000000..ed350048
--- /dev/null
+++ b/doc/ru/Файловая-система-и-сериализация.md
@@ -0,0 +1,137 @@
+## Библиотека *file*
+
+Библиотека функций для работы с файлами
+
+```python
+file.resolve(путь: str) -> str
+```
+
+Функция приводит запись `точка_входа:путь` (например `user:worlds/house1`) к обычному пути. (например `C://Users/user/.voxeng/worlds/house1`)
+
+> [!NOTE]
+> Функцию не нужно использовать в сочетании с другими функциями из библиотеки, так как они делают это автоматически
+
+Возвращаемый путь не является каноническим и может быть как абсолютным, так и относительным.
+
+```python
+file.read(путь: str) -> str
+```
+
+Читает весь текстовый файл и возвращает в виде строки
+
+```python
+file.read_bytes(путь: str) -> array of integers
+```
+
+Читает файл в массив байт.
+
+```python
+file.write(путь: str, текст: str) -> nil
+```
+
+Записывает текст в файл (с перезаписью)
+
+```python
+file.write_bytes(путь: str, data: array of integers)
+```
+
+Записывает массив байт в файл (с перезаписью)
+
+```python
+file.length(путь: str) -> int
+```
+
+Возвращает размер файла в байтах, либо -1, если файл не найден
+
+```python
+file.exists(путь: str) -> bool
+```
+
+Проверяет, существует ли по данному пути файл или директория
+
+```python
+file.isfile(путь: str) -> bool
+```
+
+Проверяет, существует ли по данному пути файл
+
+```python
+file.isdir(путь: str) -> bool
+```
+
+Проверяет, существует ли по данному пути директория
+
+```python
+file.mkdir(путь: str) -> bool
+```
+
+Создает директорию. Возвращает true если была создана новая директория
+
+```python
+file.mkdirs(путь: str) -> bool
+```
+
+Создает всю цепочку директорий. Возвращает true если были созданы директории.
+
+```python
+file.find(путь: str) -> str
+```
+
+Ищет файл от последнего пака до res. Путь указывается без префикса. Возвращает путь с нужным префиксом. Если файл не найден, возвращает nil.
+
+```python
+file.remove(путь: str) -> bool
+```
+
+Удаляет файл. Возращает **true** если файл существовал. Бросает исключение при нарушении доступа.
+
+```python
+file.remove_tree(путь: str) -> int
+```
+
+Рекурсивно удаляет файлы. Возвращает число удаленных файлов.
+
+## Библиотека json
+
+Библиотека содержит функции для сериализации и десериализации таблиц:
+
+```python
+json.tostring(object: table, human_readable: bool=false) -> str
+```
+
+Сериализует объект в JSON строку. При значении второго параметра **true** будет использовано многострочное форматирование, удобное для чтения человеком, а не компактное, использующееся по-умолчанию.
+
+```python
+json.parse(code: str) -> table
+```
+
+Парсит JSON строку в таблицу.
+
+## Библиотека toml
+
+Библиотека содержит функции для сериализации и десериализации таблиц:
+
+```python
+toml.tostring(object: table) -> str
+```
+
+Сериализует объект в TOML строку.
+
+```python
+toml.parse(code: str) -> table
+```
+
+Парсит TOML строку в таблицу.
+
+## Сохранение данных в мире
+
+При сохранении данных пака в мире следует использовать функцию
+```python
+pack.data_file(packid: str, filename: str) -> str
+```
+
+Функция возвращает путь к файлу данных по типу: `world:data/packid/filename`
+
+и создает недостающие директории в пути.
+
+При использовании путей не соответствующим `data/{packid}/...` возможна потеря данных при перезаписи мира.
diff --git a/fix_dylibs.sh b/fix_dylibs.sh
new file mode 100755
index 00000000..779336b3
--- /dev/null
+++ b/fix_dylibs.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+PROJECT_NAME=$1
+CONFIG=$2
+OUTPUT_DIR=$3
+LIBS_DIR="$OUTPUT_DIR/libs"
+
+mkdir -p "$LIBS_DIR"
+
+TMP_BINARY="$OUTPUT_DIR/tmp_$PROJECT_NAME"
+BINARY="$OUTPUT_DIR/$PROJECT_NAME"
+
+cp "$BINARY" "$TMP_BINARY"
+
+otool -L "$TMP_BINARY" | grep -o '/.*dylib' | while read -r dylib; do
+ if [[ "$dylib" == /usr/lib/* || "$dylib" == /System/Library/* ]]; then
+ continue
+ fi
+
+ cp "$dylib" "$LIBS_DIR"
+ install_name_tool -change "$dylib" "@executable_path/libs/$(basename "$dylib")" "$TMP_BINARY"
+done
+
+mv "$TMP_BINARY" "$BINARY"
diff --git a/res/config/bindings.toml b/res/config/bindings.toml
new file mode 100644
index 00000000..e13be068
--- /dev/null
+++ b/res/config/bindings.toml
@@ -0,0 +1,18 @@
+devtools.console="key:grave-accent"
+chunks.reload="key:f5"
+movement.forward="key:w"
+movement.back="key:s"
+movement.left="key:a"
+movement.right="key:d"
+movement.jump="key:space"
+movement.sprint="key:left-ctrl"
+movement.crouch="key:left-shift"
+movement.cheat="key:r"
+camera.zoom="key:c"
+camera.mode="key:f4"
+player.noclip="key:n"
+player.flight="key:f"
+player.attack="mouse:left"
+player.build="mouse:right"
+player.pick="mouse:middle"
+hud.inventory="key:tab"
diff --git a/res/config/builtins.list b/res/config/builtins.list
new file mode 100644
index 00000000..df967b96
--- /dev/null
+++ b/res/config/builtins.list
@@ -0,0 +1 @@
+base
diff --git a/res/content/base/scripts/grass_block.lua b/res/content/base/scripts/grass_block.lua
index d92813c4..e58597cc 100644
--- a/res/content/base/scripts/grass_block.lua
+++ b/res/content/base/scripts/grass_block.lua
@@ -1,15 +1,15 @@
function on_random_update(x, y, z)
- local dirtid = block_index('base:dirt');
- if is_solid_at(x, y+1, z) then
- set_block(x, y, z, dirtid, 0)
+ local dirtid = block.index('base:dirt');
+ if block.is_solid_at(x, y+1, z) then
+ block.set(x, y, z, dirtid, 0)
else
- local grassblockid = block_index('base:grass_block')
+ local grassblockid = block.index('base:grass_block')
for lx=-1,1 do
for ly=-1,1 do
for lz=-1,1 do
- if get_block(x + lx, y + ly, z + lz) == dirtid then
- if not is_solid_at(x + lx, y + ly + 1, z + lz) then
- set_block(x + lx, y + ly, z + lz, grassblockid, 0)
+ if block.get(x + lx, y + ly, z + lz) == dirtid then
+ if not block.is_solid_at(x + lx, y + ly + 1, z + lz) then
+ block.set(x + lx, y + ly, z + lz, grassblockid, 0)
return
end
end
diff --git a/res/layouts/console.xml.lua b/res/layouts/console.xml.lua
index 7ed29c1f..31314ca5 100644
--- a/res/layouts/console.xml.lua
+++ b/res/layouts/console.xml.lua
@@ -35,6 +35,7 @@ function submit(text)
add_to_history(text)
setup_variables()
+ document.log.caret = -1
local status, result = pcall(function() return console.execute(text) end)
if result ~= nil then
local prevtext = document.log.text
diff --git a/res/layouts/pages/languages.xml.lua b/res/layouts/pages/languages.xml.lua
index a064c68c..2e3710e9 100644
--- a/res/layouts/pages/languages.xml.lua
+++ b/res/layouts/pages/languages.xml.lua
@@ -9,10 +9,9 @@ function on_open()
table.sort(names)
local panel = document.root
- for _,k in ipairs(names) do
- panel:add(string.format(
- "",
- string.format("core.set_setting('ui.language', %q) menu:back()", invlocales[k]), k
+ for _,name in ipairs(names) do
+ panel:add(gui.template(
+ "language", {id=invlocales[name], name=name}
))
end
panel:add("")
diff --git a/res/layouts/pages/settings_controls.xml.lua b/res/layouts/pages/settings_controls.xml.lua
index a66e17e3..c7c8632c 100644
--- a/res/layouts/pages/settings_controls.xml.lua
+++ b/res/layouts/pages/settings_controls.xml.lua
@@ -16,7 +16,8 @@ function on_open()
refresh_sensitivity()
local panel = document.bindings_panel
- local bindings = core.get_bindings()
+ local bindings = input.get_bindings()
+ table.sort(bindings, function(a, b) return a > b end)
for i,name in ipairs(bindings) do
panel:add(gui.template("binding", {
id=name, name=gui.str(name)
diff --git a/res/layouts/pages/settings_graphics.xml.lua b/res/layouts/pages/settings_graphics.xml.lua
index 835b3746..179d8df8 100644
--- a/res/layouts/pages/settings_graphics.xml.lua
+++ b/res/layouts/pages/settings_graphics.xml.lua
@@ -1,6 +1,7 @@
-function create_setting(id, name, step, postfix)
+function create_setting(id, name, step, postfix, tooltip)
local info = core.get_setting_info(id)
postfix = postfix or ""
+ tooltip = tooltip or ""
document.root:add(gui.template("track_setting", {
id=id,
name=gui.str(name, "settings"),
@@ -8,7 +9,8 @@ function create_setting(id, name, step, postfix)
min=info.min,
max=info.max,
step=step,
- postfix=postfix
+ postfix=postfix,
+ tooltip=tooltip
}))
update_setting(core.get_setting(id), id, name, postfix)
end
@@ -24,10 +26,11 @@ function update_setting(x, id, name, postfix)
)
end
-function create_checkbox(id, name)
+function create_checkbox(id, name, tooltip)
+ tooltip = tooltip or ''
document.root:add(string.format(
- "%s",
- id, core.str_setting(id), gui.str(name, "settings")
+ "%s",
+ id, core.str_setting(id), gui.str(tooltip, "settings"), gui.str(name, "settings")
))
end
@@ -35,10 +38,10 @@ function on_open()
create_setting("chunks.load-distance", "Load Distance", 1)
create_setting("chunks.load-speed", "Load Speed", 1)
create_setting("graphics.fog-curve", "Fog Curve", 0.1)
- create_setting("graphics.gamma", "Gamma", 0.05)
+ create_setting("graphics.gamma", "Gamma", 0.05, "", "graphics.gamma.tooltip")
create_setting("camera.fov", "FOV", 1, "°")
create_checkbox("display.fullscreen", "Fullscreen")
create_checkbox("display.vsync", "V-Sync")
- create_checkbox("graphics.backlight", "Backlight")
+ create_checkbox("graphics.backlight", "Backlight", "graphics.backlight.tooltip")
create_checkbox("camera.shaking", "Camera Shaking")
end
diff --git a/res/layouts/templates/language.xml b/res/layouts/templates/language.xml
new file mode 100644
index 00000000..fea34b31
--- /dev/null
+++ b/res/layouts/templates/language.xml
@@ -0,0 +1,4 @@
+
diff --git a/res/layouts/templates/track_setting.xml b/res/layouts/templates/track_setting.xml
index 994e5bb3..82ee81c1 100644
--- a/res/layouts/templates/track_setting.xml
+++ b/res/layouts/templates/track_setting.xml
@@ -1,6 +1,6 @@
diff --git a/res/modules/toml.lua b/res/modules/toml.lua
index fb082e75..3b66790c 100644
--- a/res/modules/toml.lua
+++ b/res/modules/toml.lua
@@ -1,65 +1,4 @@
--- TOML serialization module
-local toml = {}
-
--- Convert table to TOML
-function toml.serialize(tb, isinner)
- local text = ""
- for k, v in pairs(tb) do
- local tp = type(v)
- if tp ~= "table" then
- text = text..k.." = "
- if tp == "string" then
- text = text..string.format("%q", v)
- else
- text = text..tostring(v)
- end
- text = text.."\n"
- end
- end
- for k, v in pairs(tb) do
- local tp = type(v)
- if tp == "table" then
- if isinner then
- error("only one level of subtables supported")
- end
- text = text.."["..k.."]\n"..toml.serialize(v).."\n"
- end
- end
- return text
-end
-
--- Parse TOML to new table
-function toml.deserialize(s)
- local output = {}
- local current = output
- local lines = {}
- for line in string.gmatch(s, "[^\r\n]+") do
- line = string.gsub(line, "%s+", "")
- table.insert(lines, line)
- end
- for i = 1,#lines do
- local s = lines[i]
- if string.sub(s, 1, 1) == "[" then
- local section = s.sub(s, 2, #s-1)
- current = {}
- output[section] = current
- else
- for k, v in string.gmatch(s, "(%w+)=(.+)" ) do
- v = string.gsub(v, "%s+", "")
- if v.sub(v, 1, 1) == "\"" then
- current[k] = v.sub(v, 2, #v-1)
- elseif v == "true" or v == "false" then
- current[k] = v == "true"
- end
-
- local num = tonumber(v)
- if num ~= nil then
- current[k] = num
- end
- end
- end
- end
- return output
-end
-
+print("WARNING: toml is replaced with built-in library, just remove 'require \"core:toml\"'")
+toml.serialize = toml.tostring
+toml.deserialize = toml.parse
return toml
diff --git a/res/scripts/stdcmd.lua b/res/scripts/stdcmd.lua
index 48741102..0db4d208 100644
--- a/res/scripts/stdcmd.lua
+++ b/res/scripts/stdcmd.lua
@@ -51,7 +51,7 @@ console.add_command(
)
console.add_command(
- "obj.tp obj:sel=$obj.id x:num~pos.x y:num~pos.y z:num~pos.z",
+ "tp obj:sel=$obj.id x:num~pos.x y:num~pos.y z:num~pos.z",
"Teleport object",
function (args, kwargs)
player.set_pos(unpack(args))
diff --git a/res/texts/be_BY.txt b/res/texts/be_BY.txt
index c208eeaf..318a95ff 100644
--- a/res/texts/be_BY.txt
+++ b/res/texts/be_BY.txt
@@ -12,47 +12,55 @@ error.pack-not-found=Не ўдалося знайсці пакет
error.dependency-not-found=Выкарыстоўваная залежнасць не знойдзена
pack.remove-confirm=Выдаліць увесь кантэнт які пастаўляецца пакам са свету (беззваротна)?
+# Подсказки
+graphics.gamma.tooltip=Крывая яркасці асвятлення
+graphics.backlight.tooltip=Падсветка, якая прадухіляе поўную цемру
+
# Меню
-menu.New World=Новы Свет
-menu.Quit=Выхад
-menu.Continue=Працягнуть
-menu.Save and Quit to Menu=Захаваць і Выйсці ў Меню
-menu.missing-content=Адсутнічае Кантэнт!
-menu.Content Error=Памылка Кантэнту
-menu.Controls=Кіраванне
-menu.Back to Main Menu=Вярнуцца ў Меню
-menu.Settings=Налады
-menu.Content=Кантэнт
+menu.Apply=Ужыць
menu.Audio=Гук
+menu.Back to Main Menu=Вярнуцца ў Меню
+menu.Content Error=Памылка Кантэнту
+menu.Content=Кантэнт
+menu.Continue=Працягнуть
+menu.Controls=Кіраванне
+menu.Graphics=Графіка
+menu.missing-content=Адсутнічае Кантэнт!
+menu.New World=Новы Свет
+menu.Page not found=Старонка не знойдзена
+menu.Quit=Выхад
+menu.Save and Quit to Menu=Захаваць і Выйсці ў Меню
+menu.Settings=Налады
+
world.Seed=Зерне
world.Name=Назва
-
world.World generator=Генератар свету
world.generators.default=Звычайны
world.generators.flat=Плоскі
-menu.Create World=Стварыць Свет
-
+world.Create World=Стварыць Свет
world.convert-request=Ёсць змены ў індэксах! Канвертаваць свет?
world.delete-confirm=Выдаліць свет незваротна?
# Настройки
+settings.Ambient=Фон
+settings.Backlight=Падсветка
+settings.Camera Shaking=Труска Камеры
+settings.Fog Curve=Крывая Туману
+settings.FOV=Поле Зроку
+settings.Fullscreen=Поўны экран
+settings.Gamma=Гама
+settings.Language=Мова
settings.Load Distance=Дыстанцыя Загрузкі
settings.Load Speed=Хуткасць Загрузкі
-settings.Fog Curve=Крывая Туману
-settings.Backlight=Падсветка
-settings.V-Sync=Вертыкальная Сінхранізацыя
-settings.Camera Shaking=Труска Камеры
settings.Master Volume=Агульная Гучнасць
+settings.Mouse Sensitivity=Адчувальнасць Мышы
+settings.Music=Музыка
settings.Regular Sounds=Звычайныя Гукі
settings.UI Sounds=Гукі Інтэрфейсу
-settings.Ambient=Фон
-settings.Music=Музыка
-
-settings.FOV=Поле Зроку
-settings.Mouse Sensitivity=Адчувальнасць Мышы
-settings.Language=Мова
+settings.V-Sync=Вертыкальная Сінхранізацыя
# Управление
+devtools.console=Кансоль
movement.forward=Уперад
movement.back=Назад
movement.left=Улева
diff --git a/res/texts/en_US.txt b/res/texts/en_US.txt
index 979c7330..4b8d5e5e 100644
--- a/res/texts/en_US.txt
+++ b/res/texts/en_US.txt
@@ -8,7 +8,12 @@ world.delete-confirm=Do you want to delete world forever?
world.generators.default=Default
world.generators.flat=Flat
+# Tooltips
+graphics.gamma.tooltip=Lighting brightness curve
+graphics.backlight.tooltip=Backlight to prevent total darkness
+
# Bindings
+chunks.reload=Reload Chunks
devtools.console=Console
movement.forward=Forward
movement.back=Back
diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt
index ec2946ef..f4cdfbc0 100644
--- a/res/texts/ru_RU.txt
+++ b/res/texts/ru_RU.txt
@@ -12,6 +12,10 @@ error.pack-not-found=Не удалось найти пакет
error.dependency-not-found=Используемая зависимость не найдена
pack.remove-confirm=Удалить весь поставляемый паком/паками контент из мира (безвозвратно)?
+# Подсказки
+graphics.gamma.tooltip=Кривая яркости освещения
+graphics.backlight.tooltip=Подсветка, предотвращающая полную темноту
+
# Меню
menu.Apply=Применить
menu.Audio=Звук
@@ -56,6 +60,7 @@ settings.UI Sounds=Звуки Интерфейса
settings.V-Sync=Вертикальная Синхронизация
# Управление
+chunks.reload=Перезагрузить Чанки
devtools.console=Консоль
movement.forward=Вперёд
movement.back=Назад
diff --git a/src/assets/Assets.cpp b/src/assets/Assets.cpp
index d1c93360..12a3db65 100644
--- a/src/assets/Assets.cpp
+++ b/src/assets/Assets.cpp
@@ -18,8 +18,8 @@ Texture* Assets::getTexture(std::string name) const {
return found->second.get();
}
-void Assets::store(Texture* texture, std::string name){
- textures.emplace(name, texture);
+void Assets::store(std::unique_ptr texture, std::string name){
+ textures.emplace(name, std::move(texture));
}
@@ -30,8 +30,8 @@ Shader* Assets::getShader(std::string name) const{
return found->second.get();
}
-void Assets::store(Shader* shader, std::string name){
- shaders.emplace(name, shader);
+void Assets::store(std::unique_ptr shader, std::string name){
+ shaders.emplace(name, std::move(shader));
}
Font* Assets::getFont(std::string name) const {
@@ -41,8 +41,8 @@ Font* Assets::getFont(std::string name) const {
return found->second.get();
}
-void Assets::store(Font* font, std::string name){
- fonts.emplace(name, font);
+void Assets::store(std::unique_ptr font, std::string name){
+ fonts.emplace(name, std::move(font));
}
Atlas* Assets::getAtlas(std::string name) const {
@@ -52,8 +52,8 @@ Atlas* Assets::getAtlas(std::string name) const {
return found->second.get();
}
-void Assets::store(Atlas* atlas, std::string name){
- atlases.emplace(name, atlas);
+void Assets::store(std::unique_ptr atlas, std::string name){
+ atlases.emplace(name, std::move(atlas));
}
audio::Sound* Assets::getSound(std::string name) const {
@@ -63,8 +63,8 @@ audio::Sound* Assets::getSound(std::string name) const {
return found->second.get();
}
-void Assets::store(audio::Sound* sound, std::string name) {
- sounds.emplace(name, sound);
+void Assets::store(std::unique_ptr sound, std::string name) {
+ sounds.emplace(name, std::move(sound));
}
const std::vector& Assets::getAnimations() {
@@ -82,6 +82,6 @@ UiDocument* Assets::getLayout(std::string name) const {
return found->second.get();
}
-void Assets::store(UiDocument* layout, std::string name) {
- layouts[name] = std::shared_ptr(layout);
+void Assets::store(std::unique_ptr layout, std::string name) {
+ layouts[name] = std::shared_ptr(std::move(layout));
}
diff --git a/src/assets/Assets.hpp b/src/assets/Assets.hpp
index a9d4b927..c06e764f 100644
--- a/src/assets/Assets.hpp
+++ b/src/assets/Assets.hpp
@@ -39,25 +39,25 @@ public:
~Assets();
Texture* getTexture(std::string name) const;
- void store(Texture* texture, std::string name);
+ void store(std::unique_ptr texture, std::string name);
Shader* getShader(std::string name) const;
- void store(Shader* shader, std::string name);
+ void store(std::unique_ptr shader, std::string name);
Font* getFont(std::string name) const;
- void store(Font* font, std::string name);
+ void store(std::unique_ptr font, std::string name);
Atlas* getAtlas(std::string name) const;
- void store(Atlas* atlas, std::string name);
+ void store(std::unique_ptr atlas, std::string name);
audio::Sound* getSound(std::string name) const;
- void store(audio::Sound* sound, std::string name);
+ void store(std::unique_ptr sound, std::string name);
const std::vector& getAnimations();
void store(const TextureAnimation& animation);
UiDocument* getLayout(std::string name) const;
- void store(UiDocument* layout, std::string name);
+ void store(std::unique_ptr layout, std::string name);
};
#endif // ASSETS_ASSETS_HPP_
diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp
index 8d9119ee..1f194c21 100644
--- a/src/assets/AssetsLoader.cpp
+++ b/src/assets/AssetsLoader.cpp
@@ -11,6 +11,7 @@
#include "../files/engine_paths.hpp"
#include "../content/Content.hpp"
#include "../content/ContentPack.hpp"
+#include "../voxels/Block.hpp"
#include "../graphics/core/Texture.hpp"
#include "../logic/scripting/scripting.hpp"
@@ -187,7 +188,7 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
loader.processPreloadConfigs(content);
for (auto& entry : content->getBlockMaterials()) {
- auto& material = entry.second;
+ auto& material = *entry.second;
loader.tryAddSound(material.stepsSound);
loader.tryAddSound(material.placeSound);
loader.tryAddSound(material.breakSound);
@@ -217,7 +218,7 @@ bool AssetsLoader::loadExternalTexture(
if (fs::exists(path)) {
try {
auto image = imageio::read(path.string());
- assets->store(Texture::from(image.get()).release(), name);
+ assets->store(Texture::from(image.get()), name);
return true;
} catch (const std::exception& err) {
logger.error() << "error while loading external "
diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp
index ea4560b5..bfe799bb 100644
--- a/src/assets/assetload_funcs.cpp
+++ b/src/assets/assetload_funcs.cpp
@@ -6,6 +6,7 @@
#include "../audio/audio.hpp"
#include "../files/files.hpp"
#include "../files/engine_paths.hpp"
+#include "../coders/commons.hpp"
#include "../coders/imageio.hpp"
#include "../coders/json.hpp"
#include "../coders/GLSLExtension.hpp"
@@ -43,7 +44,7 @@ assetload::postfunc assetload::texture(
imageio::read(paths->find(filename+".png").u8string()).release()
);
return [name, image](auto assets) {
- assets->store(Texture::from(image.get()).release(), name);
+ assets->store(Texture::from(image.get()), name);
};
}
@@ -102,7 +103,7 @@ assetload::postfunc assetload::atlas(
Atlas* atlas = builder.build(2, false).release();
return [=](auto assets) {
atlas->prepare();
- assets->store(atlas, name);
+ assets->store(std::unique_ptr(atlas), name);
for (const auto& file : names) {
animation(assets, paths, name, directory, file, atlas);
}
@@ -128,7 +129,7 @@ assetload::postfunc assetload::font(
for (auto& page : *pages) {
textures.emplace_back(Texture::from(page.get()));
}
- assets->store(new Font(std::move(textures), res, 4), name);
+ assets->store(std::make_unique(std::move(textures), res, 4), name);
};
}
@@ -142,8 +143,7 @@ assetload::postfunc assetload::layout(
return [=](auto assets) {
try {
auto cfg = std::dynamic_pointer_cast(config);
- auto document = UiDocument::read(cfg->env, name, file);
- assets->store(document.release(), name);
+ assets->store(UiDocument::read(cfg->env, name, file), name);
} catch (const parsing_error& err) {
throw std::runtime_error(
"failed to parse layout XML '"+file+"':\n"+err.errorLog()
@@ -189,7 +189,7 @@ assetload::postfunc assetload::sound(
}
auto sound = baseSound.release();
return [=](auto assets) {
- assets->store(sound, name);
+ assets->store(std::unique_ptr(sound), name);
};
}
@@ -304,7 +304,7 @@ static bool animation(
auto animation = create_animation(
srcAtlas.get(), dstAtlas, name, builder.getNames(), frameList
);
- assets->store(srcAtlas.release(), atlasName + "/" + name + "_animation");
+ assets->store(std::move(srcAtlas), atlasName + "/" + name + "_animation");
assets->store(animation);
return true;
}
diff --git a/src/audio/AL/ALAudio.cpp b/src/audio/AL/ALAudio.cpp
index bf5f7f13..939aa4ad 100644
--- a/src/audio/AL/ALAudio.cpp
+++ b/src/audio/AL/ALAudio.cpp
@@ -389,7 +389,7 @@ std::unique_ptr ALAudio::openStream(std::shared_ptr stream, b
return std::make_unique(this, stream, keepSource);
}
-ALAudio* ALAudio::create() {
+std::unique_ptr ALAudio::create() {
ALCdevice* device = alcOpenDevice(nullptr);
if (device == nullptr)
return nullptr;
@@ -400,7 +400,7 @@ ALAudio* ALAudio::create() {
}
AL_CHECK();
logger.info() << "initialized";
- return new ALAudio(device, context);
+ return std::make_unique(device, context);
}
uint ALAudio::getFreeSource(){
diff --git a/src/audio/AL/ALAudio.hpp b/src/audio/AL/ALAudio.hpp
index 294b0224..f0a22dde 100644
--- a/src/audio/AL/ALAudio.hpp
+++ b/src/audio/AL/ALAudio.hpp
@@ -136,9 +136,8 @@ namespace audio {
std::vector freebuffers;
uint maxSources = 256;
-
- ALAudio(ALCdevice* device, ALCcontext* context);
public:
+ ALAudio(ALCdevice* device, ALCcontext* context);
~ALAudio();
uint getFreeSource();
@@ -164,7 +163,7 @@ namespace audio {
return false;
}
- static ALAudio* create();
+ static std::unique_ptr create();
};
}
diff --git a/src/audio/NoAudio.cpp b/src/audio/NoAudio.cpp
index 3000b891..04dd2b77 100644
--- a/src/audio/NoAudio.cpp
+++ b/src/audio/NoAudio.cpp
@@ -17,6 +17,6 @@ std::unique_ptr NoAudio::openStream(std::shared_ptr stream, b
return std::make_unique(stream, keepSource);
}
-NoAudio* NoAudio::create() {
- return new NoAudio();
+std::unique_ptr NoAudio::create() {
+ return std::make_unique();
}
diff --git a/src/audio/NoAudio.hpp b/src/audio/NoAudio.hpp
index e24fb5c6..bc105139 100644
--- a/src/audio/NoAudio.hpp
+++ b/src/audio/NoAudio.hpp
@@ -81,7 +81,7 @@ namespace audio {
return true;
}
- static NoAudio* create();
+ static std::unique_ptr create();
};
}
diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp
index 3829c16a..9fe62de0 100644
--- a/src/audio/audio.cpp
+++ b/src/audio/audio.cpp
@@ -147,11 +147,11 @@ public:
void audio::initialize(bool enabled) {
if (enabled) {
- backend = ALAudio::create();
+ backend = ALAudio::create().release();
}
if (backend == nullptr) {
std::cerr << "could not to initialize audio" << std::endl;
- backend = NoAudio::create();
+ backend = NoAudio::create().release();
}
create_channel("master");
}
@@ -333,7 +333,7 @@ int audio::create_channel(const std::string& name) {
if (index != -1) {
return index;
}
- channels.emplace_back(new Channel(name));
+ channels.emplace_back(std::make_unique(name));
return channels.size()-1;
}
diff --git a/src/coders/binary_json.hpp b/src/coders/binary_json.hpp
index ba7531bc..c79a7d4d 100644
--- a/src/coders/binary_json.hpp
+++ b/src/coders/binary_json.hpp
@@ -11,20 +11,20 @@ namespace dynamic {
}
namespace json {
- const int BJSON_END = 0x0;
- const int BJSON_TYPE_DOCUMENT = 0x1;
- const int BJSON_TYPE_LIST = 0x2;
- const int BJSON_TYPE_BYTE = 0x3;
- const int BJSON_TYPE_INT16 = 0x4;
- const int BJSON_TYPE_INT32 = 0x5;
- const int BJSON_TYPE_INT64 = 0x6;
- const int BJSON_TYPE_NUMBER = 0x7;
- const int BJSON_TYPE_STRING = 0x8;
- const int BJSON_TYPE_BYTES = 0x9;
- const int BJSON_TYPE_FALSE = 0xA;
- const int BJSON_TYPE_TRUE = 0xB;
- const int BJSON_TYPE_NULL = 0xC;
- const int BJSON_TYPE_CDOCUMENT = 0x1F;
+ inline constexpr int BJSON_END = 0x0;
+ inline constexpr int BJSON_TYPE_DOCUMENT = 0x1;
+ inline constexpr int BJSON_TYPE_LIST = 0x2;
+ inline constexpr int BJSON_TYPE_BYTE = 0x3;
+ inline constexpr int BJSON_TYPE_INT16 = 0x4;
+ inline constexpr int BJSON_TYPE_INT32 = 0x5;
+ inline constexpr int BJSON_TYPE_INT64 = 0x6;
+ inline constexpr int BJSON_TYPE_NUMBER = 0x7;
+ inline constexpr int BJSON_TYPE_STRING = 0x8;
+ inline constexpr int BJSON_TYPE_BYTES = 0x9;
+ inline constexpr int BJSON_TYPE_FALSE = 0xA;
+ inline constexpr int BJSON_TYPE_TRUE = 0xB;
+ inline constexpr int BJSON_TYPE_NULL = 0xC;
+ inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F;
extern std::vector to_binary(const dynamic::Map* obj, bool compress=false);
extern std::shared_ptr from_binary(const ubyte* src, size_t size);
diff --git a/src/coders/json.cpp b/src/coders/json.cpp
index 89f06354..19b59726 100644
--- a/src/coders/json.cpp
+++ b/src/coders/json.cpp
@@ -1,5 +1,7 @@
#include "json.hpp"
+#include "commons.hpp"
+
#include "../data/dynamic.hpp"
#include "../util/stringutil.hpp"
@@ -240,11 +242,11 @@ Value Parser::parseValue() {
throw error("unexpected character '"+std::string({next})+"'");
}
-std::unique_ptr