Исходник Софт Upacker | Упаковка/распаковка .lua, .dll. exe. asi и любые др. Обновление: Автозапуск файлов БЕЗ распаковки. 16.02.2025 21:30

UBP

Известный
Автор темы
368
242

1739637635216.png



UPacker -
это Lua библиотека, предназначенная для упаковки, сжатия и управления файлами, скриптами и любыми другими ресурсами.
Она предоставляет функционал для создания автономных пакетов с автоматическим разрешением зависимостей, сжатием скриптов и возможностями безопасного автоматического выполнения.

* - Неполноценный

Поддерживаемые типы файлов:
  • Lua скрипты (.lua)
  • Исполняемые файлы (.exe)
  • Пакетные файлы (.bat, .cmd)
  • Конфигурационные файлы (.txt, .json, .cfg, .ini)
  • Изображения и другие ресурсы
  • dll и asi модули
Для чего использовать:
Можно использовать для создания пакета модификации, который включает все необходимые скрипты, зависимости и метаданные. Пакет можно легко распространять среди игроков, и он будет содержать все необходимое для установки и запуска мода.​
  1. Вы можете указать, какие файлы или скрипты автоматически запустятся сразу после распаковки, к примеру init.lua который запустит всё остальное.​
  2. Вы так-же можете указать любой путь для распаковки, не ограничиваясь папкой moonloader. К примеру, вы распаковали архив с файлом luajit.exe на диске D, он запустится автоматически, если был указан флаг autorun = true.​
Установка:
Скачайте библиотеки: upacker.lua, upacker_native.dll и переместите в moonloader/lib

Зависимости:
Скачайте Json Builder Plus и переместите в moonloader/lib

Важное обновление 16.02.2025:
Теперь для распаковки пакета вам необходимо указать ключ шифрования, который был создан после создания пакета.
Ключ шифрования автоматически генерируется после создания пакета, он будет выведет в консоль:​
Код:
[ML] (script) marsZip.lua: Package created successfully!
[ML] (script) marsZip.lua: Package XOR key (required for extraction): 0x81 -- save this key
[ML] (script) marsZip.lua: Please save this key - it will be required to extract the package

Часть 2:
Теперь можно запускать луа скрипты(Со всеми их зависимостями) без распаковки файла. Для этого была добавлена функция:
Код:
local scriptCache = packer:executePackage("moonloader/output/luajit.upac", 0x8B1C68E3)
--0x8B1C68E3 - Ключ шифрования
moonloader/output/luajit.upac -- путь до сжатого файла
Запуск exe и dll, их тоже можно запустить через эту функцию. Они будут распакованы в tempDir и запущены, подтягивая нужные зависимости.
Наглядный пример:
У вас есть проект:

1739702758278.png

После запаковки получаем:
1739702797078.png

Пользователю отправляем только сам упакованный файл, библиотеку и файл для запуска:​
Lua:
-- Создаем экземпляр упаковщика
local ScriptPacker = require("upacker") -- подключаем библиотеку
local packer = ScriptPacker:new() -- создаем экземпляр упаковщика

-- Распаковываем файлы
local metadata, dependencies = packer:extractPackage(
    "moonloader/output/package.upac", -- путь к пакету
    "D:/moonloader/output", -- путь к выходной директории
    key
)

-- Можно просмотреть содержимое пакета без распаковки
local scripts = packer:listScripts("moonloader/output/package.upac") -- список скриптов в пакете
for _, script in ipairs(scripts) do
    print(string.format("Script: %s, Version: %s autorun: %s", script.name, script.version, script.autorun)) -- выводим информацию о скрипте
end
и весь проект будет распакован в указанную директорию, а файлы или скрипты с автозапуском будут сразу запущены.
Пример создания проекта и упаковки:​
Lua:
-- Создаем экземпляр упаковщика
local ScriptPacker = require("upacker") -- подключаем библиотеку
local packer = ScriptPacker:new() -- создаем экземпляр упаковщика
-- Добавляем скрипты с их зависимостями
packer:addScripts({
    main = {
        path = "moonloader/project/javatest.lua", -- путь к скрипту
        version = "1.0.0", -- версия скрипта
        dependencies = {"JavaCore", "JSConsole", "JSInterpreter", "JSValidator", "photo1"}, -- зависимости
        autorun = true -- true - автозапуск, false - нет
    },
    JavaCore = {
        path = "moonloader/project/libs/JavaCore.lua",
        version = "1.0.0",
        dependencies = {},
        autorun = false
    },
    JSConsole = {
        path = "moonloader/project/libs/JSConsole.lua",
        version = "1.0.0",
        dependencies = {},
        autorun = false
    },
    JSInterpreter = {
        path = "moonloader/project/libs/JSInterpreter.lua",
        version = "1.0.0",
        dependencies = {},
        autorun = false
    },
    JSValidator = {
        path = "moonloader/project/libs/JSValidator.lua",
        version = "1.0.0",
        dependencies = {},
        autorun = false
    },
    photo1 = {
        path = "moonloader/project/src/photo2.jpg",
        version = "1.0.0",
        dependencies = {},
        autorun = false
    }
})
-- Создаем пакет
packer:createPackage("moonloader/output/package.upac") -- создаем пакет
Lua:
-- Создаем экземпляр упаковщика
local ScriptPacker = require("upacker") -- подключаем библиотеку
local packer = ScriptPacker:new() -- создаем экземпляр упаковщика

-- Распаковываем файлы
local metadata, dependencies = packer:extractPackage(
    "moonloader/output/package.upac", -- путь к пакету
    "D:/moonloader/output", -- путь к выходной директории
    key
)

-- Можно просмотреть содержимое пакета без распаковки
local scripts = packer:listScripts("moonloader/output/package.upac") -- список скриптов в пакете
for _, script in ipairs(scripts) do
    print(string.format("Script: %s, Version: %s autorun: %s", script.name, script.version, script.autorun)) -- выводим информацию о скрипте
end
ScriptPacker:new(): Создает новый экземпляр ScriptPacker.

ScriptPacker:addScript(name, path, version, dependencies, autorun) Добавляет скрипт в пакет

ScriptPacker:addScripts(scriptsTable): Добавляет несколько скриптов из таблицы.

ScriptPacker:removeScript(name): Удаляет скрипт из пакета по имени.

ScriptPacker:createPackage(outputPath): Создает пакет и сохраняет его по указанному пути.

ScriptPacker:extractPackage(inputPath, outputDir) Распаковывает пакет и сохраняет скрипты в указанную директорию.

ScriptPacker:listScripts(packagePath): Возвращает список скриптов в пакете.

ScriptPacker:executeFile(path): Выполняет файл по указанному пути.

Lua:
local ScriptPacker = require("upacker")
local dlstatus = require('moonloader').download_status
local vk = require 'vkeys'

local packer = ScriptPacker:new()
local download_id = nil
local stop_downloading = false

function download_handler(id, status, p1, p2)
    if stop_downloading then
        stop_downloading = false
        download_id = nil
        print('Загрузка пакета отменена.')
        return false
    end
    if status == dlstatus.STATUS_DOWNLOADINGDATA then
        print(string.format('Загружено %d из %d байт.', p1, p2))
    elseif status == dlstatus.STATUS_ENDDOWNLOADDATA then
        print('Загрузка пакета завершена.')
        -- Распаковываем скачанный пакет
        local metadata, dependencies = packer:extractPackage(
            getWorkingDirectory() .. '/downloads/package.upac',
            getWorkingDirectory() .. '/output'
        )
        -- Выводим информацию о скриптах в пакете
        local scripts = packer:listScripts(getWorkingDirectory() .. '/downloads/package.upac')
        for _, script in ipairs(scripts) do
            print(string.format("Script: %s, Version: %s autorun: %s", script.name, script.version, script.autorun))
        end
    end
end

function main()
    print('Нажмите F1, чтобы загрузить и распаковать пакет.')
    while true do
        wait(0)
        if wasKeyPressed(vk.VK_F1) and not download_id then
            local url = 'http://example.com/package.upac' -- замените на реальный URL пакета
            local file_path = getWorkingDirectory() .. '/downloads/package.upac'
            download_id = downloadUrlToFile(url, file_path, download_handler)
            print('Загрузка пакета начата. Нажмите F2, чтобы отменить.')
        elseif wasKeyPressed(vk.VK_F2) and download_id then
            stop_downloading = true
        end
    end
end
Lua:
-- Создаем экземпляр упаковщика
local ScriptPacker = require("ubplibs.upacker")
local packer = ScriptPacker:new()

-- Добавляем скрипты с их зависимостями
packer:addScripts({
    main = {
        path = "moonloader/luajit.exe",
        version = "1.0.0",
        dependencies = {"lua51"},
        autorun = true
    },
    lua51 = {
        path = "moonloader/lua51.dll",
        version = "1.0.0",
        dependencies = {},
        autorun = false
    }
})

-- Создаем пакет
packer:createPackage("moonloader/output/package.upac")
Распаковка и автозапуск:
Lua:
-- Создаем экземпляр упаковщика
local ScriptPacker = require("upacker") -- подключаем библиотеку
local packer = ScriptPacker:new() -- создаем экземпляр упаковщика

-- Распаковываем файлы
local metadata, dependencies = packer:extractPackage(
    "moonloader/output/package.upac", -- путь к пакету
    "D:/moonloader/output", -- путь к выходной директории
    key -- ключ сгенерированый после создания пакета
)

-- Можно просмотреть содержимое пакета без распаковки
local scripts = packer:listScripts("moonloader/output/package.upac") -- список скриптов в пакете
for _, script in ipairs(scripts) do
    print(string.format("Script: %s, Version: %s autorun: %s", script.name, script.version, script.autorun)) -- выводим информацию о скрипте
end

Todo:
  1. Переход на dll формат библиотеки
  2. Шифрование/Дешифрование с указанием ключа AES
  3. Exe формат пакерa

Github - скоро

Updates:
16.02.2025 0:27 > Исправлена ошибка, когда не запускались файлы при наличии moonloader пути при распаковке
16.02.2025 13:38 > Теперь после создания пакета, в консоль вам выведет ключ шифрования. Распаковать пакет можно только имея данный ключ.
16.02.2025 13:52 > 8 бит ключ шифрования заменен на 32 бит.
16.02.2025 21:31 > Теперь можно запускать файлы луа без распаковки. Можно запустить полностью весь запакованный проект, и он подтянет все зависимости без распаковки в директорию. Exe файлы и их зависимости в виде dll, будут распакованы в tempDir и запущены в отдельном потоке, не мешая основному потоку игры. Если автозапускать .dll, то будут подгружены через loadLibrary
 

Вложения

  • upacker.lua
    17.6 KB · Просмотры: 4
  • upacker_native.dll
    312.5 KB · Просмотры: 6
Последнее редактирование:

meowprd

Тот самый Котовский
Проверенный
1,302
731
Исходник .dll на github будет существовать?
Хотелось бы посмотреть
 
  • Нравится
Реакции: lpk))) и Vespan

UBP

Известный
Автор темы
368
242
Будет ли запуск файлов без распаковки?
Добавил функцию


Код:
-- Создаем экземпляр упаковщика
local ScriptPacker = require("upacker") -- подключаем библиотеку
local packer = ScriptPacker:new() -- создаем экземпляр упаковщика
local scriptCache = packer:executePackage("moonloader/output/luajit.upac", 0x8B1C68E3)
Обнови библиотеку. Теперь ты можешь запаковать весь проект и запустить его без распаковки.
exe и .dll к сожалению нельзя запускать без распаковки. При использовании этой функции они будут распакованы в tempdir и запущены в отдельном потоке.
 
  • Нравится
Реакции: cloused2