Исходник Гайд XCONF Module — современный конфигуратор

Frankstosh

Участник
Автор темы
13
15
blue_edupictrocketship_1484335252-1.png

XCONF Module v.1.0.1
Contributors: Frankstosh & Pakulichev
Многие разработчики сталкиваются с проблемой организации системы конфигурации в своих скриптах. XCONF Module позволяет в полной мере забыть о том, что такое сложности при разработке скриптов с необходимостью реализации системы сохранения настроек.

XCONF Module работает на основе JSON Parser и позволяет хранить ваши данные в формате JSON. Это очень удобно и, в отличие от INI, JSON позволяет хранить большие объемы данных. Например, вы можете сохранить таблицу с целой горой вложенных таблиц внутри. Сделать то же самое при помощи INI, к сожалению, не представляется возможным — приходится жертвовать функциональностью.

Помимо всего прочего, XCONF Module обладает всеми прелестями другой библиотеки — inicfg. Вы можете задавать шаблон-конфигуратор, в котором будут хранится все необходимые данные, поэтому, даже если пользователь удалит файл конфигурации или как-либо его повредит, ваш скрипт восполнит все необходимые данные. Это также позволяет распространять скрипт без файла конфигурации.

Установка XCONF Module
Скачайте файл, находящийся во вложениях, и просто переместите его по следующему пути: {GTA_FOLDER}/moonloader/lib. Для того, чтобы использовать модуль внутри вашего скрипта, просто подключите его таким или любым другим способом: xconf = require("xconf")

Использование XCONF Module

Библиотека предоставляет доступ к некотором функциям и методам, использование которых — залог правильного пользования модулем. В нижеприведённом скрипте вы можете лицезреть пример использования XCONF Module в боевых условиях:
Lua:
local xconf = require("xconf")

local conf = xconf.new("moonloader/new_config.json")
if conf then
    conf:set_template({
        main_settings = {
            username = "Pakulichev",
            email = "paveltalking@gmail.com",
            password = {
                hash = "XXXXXXXXXXXXXXX",
                encoder = "SHA256"
            },
            level = 15
        },
        is_enabled = true
    })
    local result = conf:get()
    if type(result) == 'table' then
        print(result.main_settings.username)
        print(result.main_settings.password.hash)
        print(result.main_settings.password.encoder)
        print(result.is_enabled)
    end
    conf:set({
        main_settings = {
            username = "Pavel",
            password = {
                hash = "RRRRRRRRRRRRRRR"
            }
        }
    })
    conf:close()
end
Теперь немного об отдельных функциях и методах:
Lua:
XCONF Handle conf = xconf.new(string filename) -- открытие сессии работы с конфигуратором. Необходимо открывать сессию перед началом работы с файлом конфигурации и закрывать по окончанию работы с файлом конфигуратора.
conf:set_template(table template) -- установить шаблон конфигуратора, используется в работе модуля.
conf:set(table data) -- произвести запись в файл конфигурации, первым аргументом передать таблицу.
boolean/table data = conf:get() -- прочитать записи из файла конфигурации: метод может вернуть FALSE, необходимо делать проверку перед тем, как использовать значения из переменной "data". Будьте осторожны с этим методом!
conf:close() -- закрытие сессии работы с конфигуратором, необходимо делать в конце работы с файлом конфигурации.

Спасибо за ваше внимание!
 

Вложения

  • xconf.lua
    2.4 KB · Просмотры: 52
Последнее редактирование:

AnWu

Известный
Всефорумный модератор
4,777
5,400
Зачем это усложнение с сет темплейт и тп? почему не юзать лоад и сейв как ини, но с возможностью юзать вложенность.
Вот еще идея, создаешь функцию table.loadcfg(table), дальше можно использовать как table:loadcfg() 😉
 

ImPasha

Software Developer & System Administrator
Друг
1,788
2,142
Зачем это усложнение с сет темплейт и тп? почему не юзать лоад и сейв как ини, но с возможностью юзать вложенность.
Вот еще идея, создаешь функцию table.loadcfg(table), дальше можно использовать как table:loadcfg() 😉
Модуль работает немного иначе, нежели тот же inicfg, и это скорее связано больше с тем, что была попытка добиться максимальной оптимизации в вопросе работы с файловой системой. Библиотека по сути единожды открывает файл с конфигурацией и дальше работает с ним до тех пор, пока сессия не будет закрыта. Не будем считать повторное открытие с флагом "w+" для полной очистки файла, потому что способа сделать лучше я не нашёл. SET_TEMPLATE нужен для того, чтобы раз и на всё время жизни сессии установить шаблон и не указывать его дополнительным аргументом в методе CONFIG:GET. Мне показалось это удобным: опять же, можно было вынести это в переменную, но тогда бы происходила смерть при передачи неверного типа, была попытка создать newbie-friendly модуля. Насчет предложения про table.loadcfg непонятно, попробуй объяснить как-нибудь иначе, перефразировать.
 
  • Влюблен
Реакции: Frankstosh

ImPasha

Software Developer & System Administrator
Друг
1,788
2,142
UPDATE: XCONF Module v.1.0.1
Что нового:

  • Изменен метод GET, теперь передавать результат можно двумя способами: стандартным присваиванием и передачей необходимой таблицы первым аргументом. В случае, если таблица передается первым аргументом, метод вернет значение boolean. Это не отменяет того, что может вернутся false.
  • Изменен метод SET: теперь, в случае если раньше по коду вы использовали метод GET и не передали в метод ни одного аргумента, будет использоваться та таблица, куда в последний раз записались данные, т.е. вы можете свободно изменять полученную таблицу с последующим вызовом SET.
Пример использования:
Lua:
local my_table = {}
local result = config:get(my_table) -- эквивалентно my_table = config:get()
if result then -- если вернется TRUE, будем обрабатывать
  -- желательно ещё проверить тип my_table, там может быть FALSE!
  my_table.anyKey = false
  config:set() -- будут записаны данные из my_table, так как ранее мы записали
  -- туда данные из этого же конфига; используется последняя таблица из GET!
end
 

Вложения

  • xconf.lua
    2.4 KB · Просмотры: 13
  • Нравится
  • Влюблен
Реакции: serhiyrubin и Frankstosh
У

Удалённый пользователь 341712

Гость
прикольная идея, с таблицами легче работать будет
 

Cosmo

Известный
Друг
656
2,744
Что не так делаю? config:get() возвращает FALSE
Lua:
local xconf = require("xconf")
local config = xconf.new("moonloader/Test/testConfig.json")

if config then
    config:set_template({
        main = {
            nickname = "Cosmo",
            organisation = {
                name = 'Банк',
                rank = 'Охранник',
                ordinal = 1
            }
        }
    })
    cfg = config:get()
end

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(80) end
        
        sampRegisterChatCommand('xread', function()
            if cfg then
                sampAddChatMessage(string.format('Никнейм: {33AA33}%s', cfg.main.nickname), -1)
                sampAddChatMessage(string.format('Работа: {33AA33}%s', cfg.main.organisation.name), -1)
                sampAddChatMessage(string.format('Должность: {33AA33}%s (%s)', cfg.main.organisation.rank, cfg.main.organisation.ordinal), -1)
            else
                sampAddChatMessage('Не удалось прочитать таблицу', -1)
            end
        end)

        sampRegisterChatCommand('xset', function(arg)
            if #arg > 0 and cfg then
                local k, v = arg:match('(.+) (.+)')
                if k == 'nick' then cfg.main.nickname = tostring(v) end
                if k == 'org' then cfg.main.organisation.name = tostring(v) end
                if k == 'rank' then cfg.main.organisation.rank = tonumber(v) end
                if k == 'ordinal' then cfg.main.organisation.ordinal = tostring(v) end
                config:set()
            end
        end)

    while true do

    wait(0)
    end
end

function onScriptTerminate(lua, bquit)
    if lua == thisScript() then
        conf:close()
    end
end
 

ImPasha

Software Developer & System Administrator
Друг
1,788
2,142
Что не так делаю? config:get() возвращает FALSE
Lua:
local xconf = require("xconf")
local config = xconf.new("moonloader/Test/testConfig.json")

if config then
    config:set_template({
        main = {
            nickname = "Cosmo",
            organisation = {
                name = 'Банк',
                rank = 'Охранник',
                ordinal = 1
            }
        }
    })
    cfg = config:get()
end

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(80) end
       
        sampRegisterChatCommand('xread', function()
            if cfg then
                sampAddChatMessage(string.format('Никнейм: {33AA33}%s', cfg.main.nickname), -1)
                sampAddChatMessage(string.format('Работа: {33AA33}%s', cfg.main.organisation.name), -1)
                sampAddChatMessage(string.format('Должность: {33AA33}%s (%s)', cfg.main.organisation.rank, cfg.main.organisation.ordinal), -1)
            else
                sampAddChatMessage('Не удалось прочитать таблицу', -1)
            end
        end)

        sampRegisterChatCommand('xset', function(arg)
            if #arg > 0 and cfg then
                local k, v = arg:match('(.+) (.+)')
                if k == 'nick' then cfg.main.nickname = tostring(v) end
                if k == 'org' then cfg.main.organisation.name = tostring(v) end
                if k == 'rank' then cfg.main.organisation.rank = tonumber(v) end
                if k == 'ordinal' then cfg.main.organisation.ordinal = tostring(v) end
                config:set()
            end
        end)

    while true do

    wait(0)
    end
end

function onScriptTerminate(lua, bquit)
    if lua == thisScript() then
        conf:close()
    end
end
Сложно сказать, нужно поэтапно смотреть и искать причину. Единственное, что могу сказать по коду, что переменной conf, которая у тебя есть в конце кода, не существует, ты некорректно скопировал это из примера - в твоём случае используется переменная config. А так не знаю, завтра посмотрю, если не забуду.
 
  • Нравится
Реакции: Cosmo

Smeruxa

Известный
1,371
726
Почему не работает?
Lua:
require 'lib.moonloader'
local xconf = require("xconf")
local path = xconf.new("moonloader/config/test.json")
if path then 
    path:set_template({
        config = {
            test = 123
        }
    })
    HLcfg = path:get()
end
function main()
    while not isSampAvailable() do wait(100) end 
    sampRegisterChatCommand("test", function()
        sampAddChatMessage(HLcfg.config.test, -1)
    end)
    sampRegisterChatCommand("set", function(arg)
        HLcfg.config.test = arg
        path:set(HLcfg)
    end)
    while true do wait(0) end
end
function onScriptTerminate(lua, bquit)
    if lua == thisScript() then
        path:close()
    end
end

Код:
[ML] (system) Loading script 'D:\A_GTA\moonloader\test.lua'...
[ML] (exception) test.lua: CJSON: Expected value but found T_END at character 1
[ML] (system) test.lua: Loaded successfully.
[ML] (error) test.lua: D:\A_GTA\moonloader\test.lua:17: attempt to index global 'HLcfg' (a boolean value)
stack traceback:
    D:\A_GTA\moonloader\test.lua:17: in function <D:\A_GTA\moonloader\test.lua:16>