Исходник [1.2.1] moonly / MoonLoader project manager

Musaigen

ihatemyself
Автор темы
Проверенный
1,676
1,514

moonly – менеджер проектов для MoonLoader​

Что это такое?​

moonly — это менеджер проектов для разработки Lua-скриптов под MoonLoader. Он предоставляет структуру, похожую на полноценные языки программирования, позволяя писать чище, масштабнее и удобнее. В отличие от традиционного подхода, где все скрипты лежат в одной папке moonloader, moonly предлагает создавать отдельные проекты в своей собственной директории, что помогает лучше организовать код, использовать модули, работать с зависимостями и интегрироваться с редакторами.

Для кого это?​

Moonly идеально подходит для:
  • Разработчиков, создающих большие проекты (от 1000 строк и выше)
  • Тех, кто хочет избежать хаоса в папке moonloader
  • Пользователей, желающих воспользоваться возможностями IDE, такими как IntelliSense, линтингом, навигацией
  • Командных разработок и проектов, которые нужно экспортировать в сторонние репозитории (BlastHack и др.)

Как работает moonly​

Перед запуском init.lua проекта, moonly внедряет в пространство имен несколько изменений:
  • getWorkingDirectory() теперь возвращает путь к проекту
  • package.path и package.cpath дополняются путями к src/ и lib/ внутри проекта
  • ffi.load(...) адаптирована для корректной работы с библиотеками из lib/
  • Добавлены глобальные переменные:
    • MOONLY_ENVIRONMENT — указывает, что скрипт выполняется в рамках проекта moonly
    • MOONLY_VERSION — содержит текущую версию установленного moonly
    • getMoonloaderDirectory() — возвращает путь к оригинальной папке moonloader

Функционал moonly​

  1. Загрузка проектов из корневой папки игры
    По умолчанию moonly ищет проекты в %game%/moonly. Каждый проект — это отдельная папка с файлом project.json.
  2. Поддержка внешних директорий
    В moonly.json можно указывать дополнительные пути, где будут храниться проекты. Это позволяет использовать несколько рабочих зон: ноутбук, домашний компьютер, внешний диск и т.д.
  3. Hot-reloading проектов в runtime
    При изменении любого файла в src/ или lib/, проект автоматически перезагружается. Новые файлы добавляются в список сканирования.
  4. Логгинг для дебаггинга
    Поддерживается вывод подробных логов, что облегчает поиск ошибок и анализ поведения скрипта.
  5. Пользовательские модули
    Модули — это Lua-файлы, реализующие методы: initialize(), register(project), unregister(project), tick(), unload(). Они расширяют функционал moonly и должны быть указаны в moonly.json.

Пример структуры проекта​

Код:
my-moonloader-project/
├── project.json
├── src/
│   ├── init.lua
│   ├── ui.lua
│   └── utils/
│       └── helper.lua
└── lib/
    └── mylib.lua
Так выглядит типичный проект, использующий moonly. Все исходники находятся в src/, пользовательские библиотеки — в lib/, а точкой входа является init.lua.

Конфигурационные файлы​

moonly.json (на уровне пользователя):
{
  "modules": [
    {
      "name": "autoreboot",
      "core": true,
      "options": {
        "delay": 1000
      }
    }
  ],
  "runtime": {
    "path": ["C:\\Games\\GTA San Andreas\\moonly"]
  }
}
project.json (внутри каждого проекта):
{
  "name": "my-moonloader-project",
  "library": "lib",
  "source": "src",
  "distribute": {
    "output": "dist",
    "additionalDirs": [],
    "ignoredDirs": [],
     "additionalFiles": [],
     "constants": {
        "MOONLY_BUNDLED": true,
        "MOONLY_BUNDLE_TIMESTAMP": "<$date>"
     }
  }
}
Описывает конфигурацию конкретного проекта: пути к исходникам и библиотекам, настройки сборки и экспорта. Стоит отметить, что содержимое project.json может быть пустым. В таком случае, moonly использует значения по умолчанию (имя проекта = название папки, src/, lib/).

Как использовать?​

Используйте moonly как менеджера проектов для своих MoonLoader-скриптов:
  1. Создаёте новый проект: moonly init -n my-project
  2. Разрабатываете код в папке src/, используя модульную структуру
  3. Тестируете логику в MoonLoader, используя init.lua как точку входа
  4. Когда проект готов, собираете его командой: moonly bundle
  5. Полученный файл помещается в папку moonloader и используется как обычный скрипт

Установка​

  1. Перейдите на страницу GitHub Releases.
  2. Скачайте файл moonly.lua из раздела Assets.
  3. Поместите его в папку moonloader корня игры.

Инструменты​

Для управления проектами рекомендуется использовать moonly CLI:
  1. Скачайте её с официального репозитория .
  2. Добавьте её в системные переменные PATH.
  3. Используйте команду moonly --help, чтобы узнать доступные действия.

Зависимости​

  • LuaFileSystem (встроена в скрипт) — нужен для работы с файловой системой.
 
Последнее редактирование:

kyrtion

Известный
1,197
438
и как же банджлить в 1 файле? напоминает squish
то есть предлагаешь воспользоваться moonly а затем уже можно банджлить squish в этой папке проекта? или я не* понял
 
Последнее редактирование:

Musaigen

ihatemyself
Автор темы
Проверенный
1,676
1,514
и как же банджлить в 1 файле? напоминает squish
то есть предлагаешь воспользоваться moonly а затем уже можно банджлить squish в этой папке проекта? или я понял
Нет. У тебя есть src/init.lua и есть папка с модулями src/my_project. Когда отгружаешь архив на бх, init.lua переименовываешь в my_project.lua, название папки так и оставляешь и всё это добро закидываешь в архив. Я могу написать конечно тулу для автоматизации этого, на том же питоне и скомпилить в ехе и это будет работать как command line tool, но пока ещё думаю над всем этим.
 
  • Нравится
Реакции: kyrtion

kyrtion

Известный
1,197
438
Попробовал и теперь мне больше понравилось moonly чем githelper
+реп и +уважуха

а что насчет получение библиотеки которые хранились в moonloader - их придется копировать в lib? или подобрать для адекватной работы, например только samp.lua и mimgui
 
Последнее редактирование:
  • Нравится
Реакции: Musaigen

Musaigen

ihatemyself
Автор темы
Проверенный
1,676
1,514
Первая тестовая версия утилиты для упрощения разработки, написания на Python с использованием библиотеки argparse и zipfile и скомпиленная в exe`шник через auto-py-to-exe. Прописываете в PATH системы и кайфуете.

Всего две команды:
init - инициализирует дефолтный project.json
build - создаст из проекта архив (src + lib), который можно будет сразу выгружать на blasthack. (Сохраняет кодировку файла, так что не забывайте сохранять в Windows 1251)

1726226867755.png

1726226937823.png

Попробовал и теперь мне больше понравилось moonly чем githelper
+реп и +уважуха

а что насчет получение библиотеки которые хранились в moonloader - их придется копировать в lib? или подобрать для адекватной работы, например только samp.lua и mimgui
нет, require подхватит из муна все библиотеки, если они не оверрайднуты в локальных либах (иначе возьмет из локальных)
 
Последнее редактирование:
  • Нравится
Реакции: kyrtion

kyrtion

Известный
1,197
438
Lua:
-- src/init.lua
print('Script Shat version 0.0.1-release successfully loaded!')

Код:
[ML] (script) shat: Script Shat version 0.0.1-release successfully loaded!
[ML] (system) Loading script 'C:\Users\root\AppData\Local\Temp\moonly\moonly_shat.lua'...
[ML] (system) shat: Loaded successfully.
[ML] (script) shat: Script Shat version 0.0.1-release successfully loaded!
[ML] (system) shat: Script terminated. (4BD101AC)

Это так должно быть работать? Сначала убить скрипт и затем запускать. Может это не исправляется или так положено?

а еще не знаешь как создать каллбак, типа, если скрипт запуска помер, то модули их нужно завершить работу типа так.


src/init.lua, там все-все прописано, импорт модули и константы (кнш глобальные, а как же инчае),
в констант будет создано так: CONST.SCRIPT, у его включено имя скрипта, версия, тип версии и тд, а также LUA_SCRIPT.

я указал LUA_SCRIPT, тот скрипт который запускает, попробовал вставить в модулях указать:
Lua:
function onScriptTerminate(script, quit)
  if script == CONST.SCRIPT.LUA_SCRIPT then
    print('Oop\'s, this module crashed!')
  end
end
но это не пашет, есть идеи?
 
Последнее редактирование:

Musaigen

ihatemyself
Автор темы
Проверенный
1,676
1,514
Это так должно быть работать? Сначала убить скрипт и затем запускать. Может это не исправляется или так положено?
он просто выгружается дольше чем загружается новый (ну или если быть точнее, moonloader выполняет main в отдельном потоке, из-за чего и происходит разница во времени, по идее так). script:reload не давал результатов потому используется вариант с script:unload и загрузкой скрипта.

if script == CONST.SCRIPT.LUA_SCRIPT then
Нужно использовать script.this или thisScript(), как и в обычных скриптах. Все скрипты загрузчики это такие же moonloader скрипты, единственное отличие - они подменяют package.path, package.cpath и добавляют константу MOONLY_ENVIRONMENT, константу и функцию получения версии, патчат getWorkingDirectory и добавляют getMoonloaderDirectory, ну и отличаются в пути к скрипту. За счёт этого и достигается совместимость и минимальное кол-во ошибок при переносе с moonly на moonloader.
 
Последнее редактирование:
  • Нравится
Реакции: kyrtion

kyrtion

Известный
1,197
438
Lua:
-- src/core/ui/init.lua
imgui = require('mimgui')

Код:
[ML] (system) Loading script 'C:\Users\root\AppData\Local\Temp\moonly\moonly_mytools.lua'...
[ML] (system) mytools: Loaded successfully.
[ML] (error) mytools: C:\Games\gtasa\moonloader\lib\mimgui\imgui.lua:8: cannot load module 'C:\Games\gtasa\moonly\mytools\src\lib\mimgui\cimguidx9': Не найден указанный модуль.

stack traceback:
    [C]: in function 'require'
    C:\Games\gtasa\moonly\mytools\src\core\ui\init.lua:4: in function 'start'
    C:\Games\gtasa\moonly\mytools\src\core\init.lua:11: in function 'start'
    [string "script_name('mytools')..."]:10: in function <[string "script_name('mytools')..."]:6>
[ML] (error) mytools: Script died due to an error. (0B31330C)

Нужно откатить на старой версии 0.1.2? Или из-за патча все мешает
 

Musaigen

ihatemyself
Автор темы
Проверенный
1,676
1,514
Lua:
-- src/core/ui/init.lua
imgui = require('mimgui')

Код:
[ML] (system) Loading script 'C:\Users\root\AppData\Local\Temp\moonly\moonly_mytools.lua'...
[ML] (system) mytools: Loaded successfully.
[ML] (error) mytools: C:\Games\gtasa\moonloader\lib\mimgui\imgui.lua:8: cannot load module 'C:\Games\gtasa\moonly\mytools\src\lib\mimgui\cimguidx9': Не найден указанный модуль.

stack traceback:
    [C]: in function 'require'
    C:\Games\gtasa\moonly\mytools\src\core\ui\init.lua:4: in function 'start'
    C:\Games\gtasa\moonly\mytools\src\core\init.lua:11: in function 'start'
    [string "script_name('mytools')..."]:10: in function <[string "script_name('mytools')..."]:6>
[ML] (error) mytools: Script died due to an error. (0B31330C)

Нужно откатить на старой версии 0.1.2? Или из-за патча все мешает
Если судить по пути файла, ты засунул папку lib в папку src. Здесь есть пример структуры проекта.
Добавил репозиторий moonly на GitHub
UPD: Я понял в чём ошибка, сейчас всё залью.
UPD2: Залил всё на GitHub, теперь moonly можно получить только там (либо по прямой ссылке в топике).
 
Последнее редактирование:
  • Нравится
Реакции: kyrtion

kyrtion

Известный
1,197
438
запустил скрипт затем перезагрузил (ctrl + r)
после изменение скрипта в модули, 2 раза перезагрузили этого скрипта

Решение:
закомментировать файл AutoReboot.lua в MoonLoader
 
Последнее редактирование:

kyrtion

Известный
1,197
438
@Musaigen
есть один баг, что неправильно работает авто-перезагрузка
1. загружаешь игру
2. удаляешь файл и обновляешь другого скрипта, что заставляет работать авто-перезагрузки скрипта и все равно пытается хукать старые файлы. Там файлы снесены
3. также если создал новый скрипт с .lua или некоторые, после авто-ребут скрипта не хукает новые файлы и папки. поэтому приходится полностью перезагрузить скрипта через Ctrl + R
 

Musaigen

ihatemyself
Автор темы
Проверенный
1,676
1,514
@Musaigen
есть один баг, что неправильно работает авто-перезагрузка
1. загружаешь игру
2. удаляешь файл и обновляешь другого скрипта, что заставляет работать авто-перезагрузки скрипта и все равно пытается хукать старые файлы. Там файлы снесены
3. также если создал новый скрипт с .lua или некоторые, после авто-ребут скрипта не хукает новые файлы и папки. поэтому приходится полностью перезагрузить скрипта через Ctrl + R
поточнее опиши, а то ничего не понятно, что ты там удалил, с какого скрипта обновил, кого на хук натянул
ну и в принципе непонятно, какие ты там скрипты запускаешь, а какие удаляешь.
ты в папке temp системы редактируешь временные "хук" скрипты что ли?
 

kyrtion

Известный
1,197
438
поточнее опиши, а то ничего не понятно, что ты там удалил, с какого скрипта обновил, кого на хук натянул
ну и в принципе непонятно, какие ты там скрипты запускаешь, а какие удаляешь.
ты в папке temp системы редактируешь временные "хук" скрипты что ли?
вот допустим.
открываешь проект в вскод, заходишь в игру.
если скрипт загружен, дальше создаем новый файл с .lua и там пишем что-нибудь код.
теперь сохраняем в основном файле чтобы применило авто-ребут скрипт.
когда мунли применяет авто-ребут скрипта, а вот новые файлы не загрузился.

вот что предлагаю:
когда мунли собирается применять авто-ребут, нужно снова сканировать файлов в проекте мунли, это которое скрипт moonly.lua поднялся
 
  • Нравится
Реакции: Musaigen

Musaigen

ihatemyself
Автор темы
Проверенный
1,676
1,514
Патч 0.1.5:
Пропатчен ffi.load для корректной работы с mimgui и другими библиотеками, которые подгружают DLL через getWorkingDirectory

запустил скрипт затем перезагрузил (ctrl + r)
после изменение скрипта в модули, 2 раза перезагрузили этого скрипта

Решение:
закомментировать файл AutoReboot.lua в MoonLoader
То есть AutoReboot.lua и встроенный autoreboot в moonly конфликтуют между собой при изменении главного init.lua?
 

kyrtion

Известный
1,197
438
Патч 0.1.5:
Пропатчен ffi.load для корректной работы с mimgui и другими библиотеками, которые подгружают DLL через getWorkingDirectory


То есть AutoReboot.lua и встроенный autoreboot в moonly конфликтуют между собой при изменении главного init.lua?
да, после полной перезагрузки скриптов, и после авто-ребут в в проекте мунли перезапускает два раза