Исходник Информация Multi-Config system

movebx

Известный
Автор темы
72
191
Всем хай, здрасьте, привет и здарова. Если вам нужна была возможность реализовать несколько конфиг-файлов в вашейм пасте скрипте, то вы попали по адресу.

Вкратце, че делает эта вся шняга:
1. Умеем читать файлы ( files.read( "paste.txt" ) )
2. Умеем записывать файлы ( files.write( "paste.txt", "FYPSASAL" ) )
3. Умеем удалять файлы ( files.delete( "paste.txt" ) )
4. Шифрование Base64 ( base64.encode( "FYPSASAL" ) )
5. Дешифрование Base64 ( base64.decode( "RllQU0FTQUw=" ) )
6. Получение всех файлов с определенным расширением из папки ( files.get_files( "SUPERIOR_PASTE1337\\configs" ) )

И так, как это юзать именно для конфигов?:
1. Для начала можем заюзать любую JSON любу для того, чтобы удобно конвертить луа таблицы в JSON и наоборот.
2. Создаем какую-то таблицу с переменными, которые будут являться настройкой нашей пастули.
3. На кнопку делаем сохранение нашего конфига, записывая какие-то значения в таблицу.
4. С помощью JSON конвертируем таблицу в JSON формат
5. Кодируем строку JSON формата в base64
6. Сохраняем наш закодированный конфиг в файл

Для загрузки конфига можем делать следующее:
1. Читаем файлы с расширением нашего конфига из определенной директории
2. Предлагаем выбрать конфиг, который хочет загрузить юзер
3. Декодируем base64 конфиг в JSON формат
4. Конвертируем JSON формат в таблицу Lua
5. Выставляем наши значения переменных.

Code:
Lua:
local base64 = { } do
    local alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    base64.encode = function(data)
        return ((data:gsub('.', function(x)
            local r,alphabet='',x:byte()
            for i=8,1,-1 do r=r..(alphabet%2^i-alphabet%2^(i-1)>0 and '1' or '0') end
            return r;
        end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
            if (#x < 6) then return '' end
            local c=0
            for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
            return alphabet:sub(c+1,c+1)
        end)..({ '', '==', '=' })[#data%3+1])
    end

    base64.decode = function(data)
        data = string.gsub(data, '[^'..alphabet..'=]', '')
        return (data:gsub('.', function(x)
            if (x == '=') then return '' end
            local r,f='',(alphabet:find(x)-1)
            for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
            return r;
        end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
            if (#x ~= 8) then return '' end
            local c=0
            for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
            return string.char(c)
        end))
    end
end

local files = { } do
    files.read = function( filename )
        local result = ""

        local file = assert( io.open( filename ) )
        for line in file:lines( ) do
            result = result..line
        end
        file:close( )

        return result
    end

    files.write = function( filename, data )
        local file = assert( io.open( filename, "w" ) )
        file:write( data )
        file:close( )
    end

    ffi.cdef( [[
        typedef struct {
            unsigned long dwLowDateTime;
            unsigned long dwHighDateTime;
        } FILETIME;
        
        typedef struct {
            unsigned long dwFileAttributes;
            FILETIME ftCreationTime;
            FILETIME ftLastAccessTime;
            FILETIME ftLastWriteTime;
            unsigned long nFileSizeHigh;
            unsigned long nFileSizeLow;
            unsigned long dwReserved0;
            unsigned long dwReserved1;
            char cFileName[260];
            char cAlternateFileName[14];
        } WIN32_FIND_DATA_A;
        
        void* FindFirstFileA(const char* lpFileName, WIN32_FIND_DATA_A* lpFindFileData);
        int FindNextFileA(void* hFile, WIN32_FIND_DATA_A* lpFindFileData);
        bool FindClose(void* hFindFile);
        bool DeleteFileA(const char* lpFileName);
    ]] )

    files.delete = function( filename )
        return ffi.C.DeleteFileA( filename )
    end

    files.get_files = function( path, extension )
        local path = path.."\\*"

        local files = { }

        local invalid_handle = ffi.cast( "void*", -1 )
        local win32_find_data = ffi.new( "WIN32_FIND_DATA_A[1]" )

        local data = ffi.FindFirstFileA(  )
        if data ~= invalid_handle then
            repeat
                local name = ffi.string( win32_find_data[0].cFileName )
                if name:find( "."..extension ) then
                    if bit.band( win32_find_data[ 0 ].dwFileAttributes, 0x2 ) == 0 then
                        if bit.band( win32_find_data[ 0 ].dwFileAttributes, 0x10 ) ~= 0x10 then
                            name = name:sub( 1, #name - ( #extension + 1 ) )
                            table.insert( files, name )
                        end
                    end
                end
            until ffi.C.FindNextFileA( data, win32_find_data ) == 0
        end
        ffi.FindClose( data )

        return files
    end
end

Пример как юзать:
Lua:
local configs = { } do
    configs.update_list = function( )
        configs_list = files.get_files( "samp\\configs", "mcfg" )
        some_combobox:update( configs_list ) --some_combobox можете заменить аналогом ImGui/MimGui, обновляя значение при нажатии соответствующей кнопки
    end

    configs.load = function( )
        local selected_config = some_combobox:get( )
        local encoded = base64.decode( files.read( string.format( "samp\\configs\\%s.mcfg", selected_config ) ) )
        local values = json.parse( encoded )

        for i in ipairs( values ) do
            --Выставляете значения в своем конфиге
        end
    end

    configs.save = function( )
        local json_fmt = json.stringify( some_table_with_variables ) --some_table_with_variables - таблица, где хранятся все значения для каких-то элементов
        local encoded = base64.encode( json_fmt )
        files.write( string.format( "samp\\configs\\%s.mcfg", some_combobox:get( ) ) ) --Напомню, что в some_combobox хранится таблица со всеми конфигами в определенной директории
    end
end

И вот то, как я это реализовал, используя API одного очень известного чита на каесгоу:

1696756893896.png

1696756943526.png