UoKit.com Форумы > Кликер > UO Pilot
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
sutra
Начал осваивать LUA, помогите пожалуйста, в справке нет многих операторов.
Сразу возник вопрос, как загрузить массив из файла (аналог load_array), наверняка ответ на форуме есть, но я не нашёл. В обычном скрипте код такой.

load_array %cfg $ConfigFile

Ну и сохранить соответственно тоже не знаю как.
Вверх
cirus
чтение/запись файла
Код
--lua
log "clear"  log "mode compact"
local f = io.open([[C:\111.txt]], "r")  -- открыть файл для чтения

if f then    -- если файл открылся
    local cfg = {}    -- объявили массив
    for v in f:lines() do       -- читаем файл 111.txt по строкам
        cfg[#cfg+1]=v           -- добавляем в массив
    end
    f:close();   -- закрыть файл
    log(table.concat(cfg, " "))    -- вывести массив в лог

    for i=1, #cfg do         -- для всех элементов массива
        cfg[i]=tostring(i) .. " " .. cfg[i]  -- вначале строки добавим номер строки
    end

    f = io.open([[C:\222.txt]], "w")  -- открыть файл для записи
    if f then
        for i=1, #cfg do         -- для всех элементов массива
            f:write(cfg[i] .. "\r\n")  -- запись в файл
        end
        f:close();   -- закрыть файл
    end
end

Вверх
DarkMaster
Поскольку lua весь на деревьях и размеры массивов могут быть различными даже в части вложенности элементов (они не прямоугольные в lua), то лучше использовать что-то более серьезное, хотя в базовом виде работать бесспроно будет.
Например есть вот такое творение:
http://lua-users.org/wiki/TablePersistence
оригинал

Код
local write, writeIndent, writers, refCount;

persistence =
{
    store = function (path, ...)
        local file, e = io.open(path, "w");
        if not file then
            return error(e);
        end
        local n = select("#", ...);
        -- Count references
        local objRefCount = {}; -- Stores reference that will be exported
        for i = 1, n do
            refCount(objRefCount, (select(i,...)));
        end;
        -- Export Objects with more than one ref and assign name
        -- First, create empty tables for each
        local objRefNames = {};
        local objRefIdx = 0;
        file:write("-- Persistent Data\n");
        file:write("local multiRefObjects = {\n");
        for obj, count in pairs(objRefCount) do
            if count > 1 then
                objRefIdx = objRefIdx + 1;
                objRefNames[obj] = objRefIdx;
                file:write("{};"); -- table objRefIdx
            end;
        end;
        file:write("\n} -- multiRefObjects\n");
        -- Then fill them (this requires all empty multiRefObjects to exist)
        for obj, idx in pairs(objRefNames) do
            for k, v in pairs(obj) do
                file:write("multiRefObjects["..idx.."][");
                write(file, k, 0, objRefNames);
                file:write("] = ");
                write(file, v, 0, objRefNames);
                file:write(";\n");
            end;
        end;
        -- Create the remaining objects
        for i = 1, n do
            file:write("local ".."obj"..i.." = ");
            write(file, (select(i,...)), 0, objRefNames);
            file:write("\n");
        end
        -- Return them
        if n > 0 then
            file:write("return obj1");
            for i = 2, n do
                file:write(" ,obj"..i);
            end;
            file:write("\n");
        else
            file:write("return\n");
        end;
        if type(path) == "string" then
            file:close();
        end;
    end;

    load = function (path)
        local f, e;
        if type(path) == "string" then
            f, e = loadfile(path);
        else
            f, e = path:read('*a')
        end
        if f then
            return f();
        else
            return nil, e;
        end;
    end;
}

-- Private methods

-- write thing (dispatcher)
write = function (file, item, level, objRefNames)
    writers[type(item)](file, item, level, objRefNames);
end;

-- write indent
writeIndent = function (file, level)
    for i = 1, level do
        file:write("\t");
    end;
end;

-- recursively count references
refCount = function (objRefCount, item)
    -- only count reference types (tables)
    if type(item) == "table" then
        -- Increase ref count
        if objRefCount[item] then
            objRefCount[item] = objRefCount[item] + 1;
        else
            objRefCount[item] = 1;
            -- If first encounter, traverse
            for k, v in pairs(item) do
                refCount(objRefCount, k);
                refCount(objRefCount, v);
            end;
        end;
    end;
end;

-- Format items for the purpose of restoring
writers = {
    ["nil"] = function (file, item)
            file:write("nil");
        end;
    ["number"] = function (file, item)
            file:write(tostring(item));
        end;
    ["string"] = function (file, item)
            file:write(string.format("%q", item));
        end;
    ["boolean"] = function (file, item)
            if item then
                file:write("true");
            else
                file:write("false");
            end
        end;
    ["table"] = function (file, item, level, objRefNames)
            local refIdx = objRefNames[item];
            if refIdx then
                -- Table with multiple references
                file:write("multiRefObjects["..refIdx.."]");
            else
                -- Single use table
                file:write("{\n");
                for k, v in pairs(item) do
                    writeIndent(file, level+1);
                    file:write("[");
                    write(file, k, level+1, objRefNames);
                    file:write("] = ");
                    write(file, v, level+1, objRefNames);
                    file:write(";\n");
                end
                writeIndent(file, level);
                file:write("}");
            end;
        end;
    ["function"] = function (file, item)
            -- Does only work for "normal" functions, not those
            -- with upvalues or c functions
            local dInfo = debug.getinfo(item, "uS");
            if dInfo.nups > 0 then
                file:write("nil --[[functions with upvalue not supported]]");
            elseif dInfo.what ~= "Lua" then
                file:write("nil --[[non-lua function not supported]]");
            else
                local r, s = pcall(string.dump,item);
                if r then
                    file:write(string.format("loadstring(%q)", s));
                else
                    file:write("nil --[[function could not be dumped]]");
                end
            end
        end;
    ["thread"] = function (file, item)
            file:write("nil --[[thread]]\n");
        end;
    ["userdata"] = function (file, item)
            file:write("nil --[[userdata]]\n");
        end;
}

Пример использования:
Код
t_original = {1, 2, ["a"] = "string", b = "test", {"subtable", [4] = 2}};
persistence.store("storage.lua", t_original);
t_restored = persistence.load("storage.lua");

Это позволит сохранят таблицы с любой структурой при этом сохраненный файл является полностью валидным lua кодом и может быть загружен через loadstring (что на самом деле и делает функция persistence.load). Вид при этом читабельный, никаких дурных проблем с зарезервированными символами и т.д.

Почему для себя я бы не стал это использовать... Сделано оно так, что должно находиться в коде скрита, а не подгружаться из отдельного файла. Это просто не удобно. К тому же мы получаем километровое название функции которое еще и правильно нужно написать. Поэтому для себя я сделал небольшие модификации.
Допиленный вариант
Код

local write, writeIndent, writers, refCount;

local persistence =
{
    save = function (path, ...)
        local file, e = io.open(path, "w");
        if not file then
            return error(e);
        end
        local n = select("#", ...);
        -- Count references
        local objRefCount = {}; -- Stores reference that will be exported
        for i = 1, n do
            refCount(objRefCount, (select(i,...)));
        end;
        -- Export Objects with more than one ref and assign name
        -- First, create empty tables for each
        local objRefNames = {};
        local objRefIdx = 0;
        file:write("-- Persistent Data\n");
        file:write("local multiRefObjects = {\n");
        for obj, count in pairs(objRefCount) do
            if count > 1 then
                objRefIdx = objRefIdx + 1;
                objRefNames[obj] = objRefIdx;
                file:write("{};"); -- table objRefIdx
            end;
        end;
        file:write("\n} -- multiRefObjects\n");
        -- Then fill them (this requires all empty multiRefObjects to exist)
        for obj, idx in pairs(objRefNames) do
            for k, v in pairs(obj) do
                file:write("multiRefObjects["..idx.."][");
                write(file, k, 0, objRefNames);
                file:write("] = ");
                write(file, v, 0, objRefNames);
                file:write(";\n");
            end;
        end;
        -- Create the remaining objects
        for i = 1, n do
            file:write("local ".."obj"..i.." = ");
            write(file, (select(i,...)), 0, objRefNames);
            file:write("\n");
        end
        -- Return them
        if n > 0 then
            file:write("return obj1");
            for i = 2, n do
                file:write(" ,obj"..i);
            end;
            file:write("\n");
        else
            file:write("return\n");
        end;
        if type(path) == "string" then
            file:close();
        end;
    end;

    load = function (path)
        local f, e;
        if type(path) == "string" then
            f, e = loadfile(path);
        else
            f, e = path:read('*a')
        end
        if f then
            return f();
        else
            return nil, e;
        end;
    end;
}

-- Private methods

-- write thing (dispatcher)
write = function (file, item, level, objRefNames)
    writers[type(item)](file, item, level, objRefNames);
end;

-- write indent
writeIndent = function (file, level)
    for i = 1, level do
        file:write("\t");
    end;
end;

-- recursively count references
refCount = function (objRefCount, item)
    -- only count reference types (tables)
    if type(item) == "table" then
        -- Increase ref count
        if objRefCount[item] then
            objRefCount[item] = objRefCount[item] + 1;
        else
            objRefCount[item] = 1;
            -- If first encounter, traverse
            for k, v in pairs(item) do
                refCount(objRefCount, k);
                refCount(objRefCount, v);
            end;
        end;
    end;
end;

-- Format items for the purpose of restoring
writers = {
    ["nil"] = function (file, item)
            file:write("nil");
        end;
    ["number"] = function (file, item)
            file:write(tostring(item));
        end;
    ["string"] = function (file, item)
            file:write(string.format("%q", item));
        end;
    ["boolean"] = function (file, item)
            if item then
                file:write("true");
            else
                file:write("false");
            end
        end;
    ["table"] = function (file, item, level, objRefNames)
            local refIdx = objRefNames[item];
            if refIdx then
                -- Table with multiple references
                file:write("multiRefObjects["..refIdx.."]");
            else
                -- Single use table
                file:write("{\n");
                for k, v in pairs(item) do
                    writeIndent(file, level+1);
                    file:write("[");
                    write(file, k, level+1, objRefNames);
                    file:write("] = ");
                    write(file, v, level+1, objRefNames);
                    file:write(";\n");
                end
                writeIndent(file, level);
                file:write("}");
            end;
        end;
    ["function"] = function (file, item)
            -- Does only work for "normal" functions, not those
            -- with upvalues or c functions
            local dInfo = debug.getinfo(item, "uS");
            if dInfo.nups > 0 then
                file:write("nil --[[functions with upvalue not supported]]");
            elseif dInfo.what ~= "Lua" then
                file:write("nil --[[non-lua function not supported]]");
            else
                local r, s = pcall(string.dump,item);
                if r then
                    file:write(string.format("loadstring(%q)", s));
                else
                    file:write("nil --[[function could not be dumped]]");
                end
            end
        end;
    ["thread"] = function (file, item)
            file:write("nil --[[thread]]\n");
        end;
    ["userdata"] = function (file, item)
            file:write("nil --[[userdata]]\n");
        end;
}

return persistence

Пример использования:
Код
local tableToFile = require[[luaPlugins\tableToFile]] -- объявляется один раз в начале скрипта.
-- Объявляем массив
local arr = {10,9,8,7,6,5,4,3,{21,22,23,"'}\"\t\'",{}},1,0}
-- Сохраняем массив
tableToFile.save("1.txt",arr)
-- Закгружаем массив
arr2=tableToFile.load("1.txt")

Изменения оригинального кода - минимальные. Просто теперь можно спокойно подгрузить одной строкой, а не таскать весь код каждый раз за собой. Ну и store нам save поменял.
Вверх
DarkMaster
Предчувствуя следующий вопрос:
Отобразить содержимое таблицы
Код
local function lg(data, comment)
    if  comment ~= nil then
        log(comment)
    end
    
    local tab = ""
    local deep = 0
    
    local function show(data)
        -- Пишем в лог комментарий.
        deep = deep + 1 -- Уровень вложенности вызовов функции.

        if type(data) == "table"    then
            local element_counter = 0
            for k,v in pairs(data) do
                element_counter = element_counter + 1
                if  type (v) == "table" then
                    log(tab..'table: '..k)
                    tab = tab .. "    "
                    show(v)
                    tab = string.sub(tab, 1, -5)
                else
                    if     type(v) == "nil"       then v = "nil"
                    elseif type(v) == "string"    then v = '"' .. v .. '"'
                    elseif type(v) == "number"    then v = tostring(v)
                    elseif type(v) == "function"  then v = tostring(v)
                    elseif type(v) == "thread"    then v = tostring(v)
                    elseif type(v) == "userdata"  then v = "userdata"
                    elseif type(v) == "boolean"   then v = tostring(v)
                    elseif type(v) == "table"     then
                        log(tab..""..k.." = "..v or "nil")
                    else
                        v = "uknown data type"
                    end
                    log(tab..""..k.." = " .. v)
                end
            end    
            log("Elements in table: " .. element_counter)
        else
            log('table is "' .. type(data) .. '" data type. Value: ' .. tostring(data))
        end
        -- Пишем в лог комментарий.
        deep = deep - 1 -- Уровень вложенности вызовов функции.
    end
    
    show(data)
end

Выдернуто куском из кода, там чуть лишнего есть. Использование:
lg(table, "комментарий")
Комментарий можно не писать.
Вверх
sutra
Спасибо большое парни! Оба здорово помогли мне. Сделал средний вариант, не так сложно как у Дарка, но с поддержкой двумерных строково-числовых массивов. И на будущее ещё много чего понял. Ещё раз спасибо.
Вверх
DarkMaster
Цитата
Сделал средний вариант, не так сложно как у Дарка

Смысл в том, что это делать уже не надо - оно уже сделано. Достаточно просто подключить. В итоге получается обыкновенная функция, а что там внутри наворочено вам и не нужно знать по большому счету.
Вверх
sutra
Дарк, а есть такая возможность получить некий результат в виде переменной из скрипта Lua в обычный скрипт? Или только через файл. Замечание я принял, спасибо. Но я всё люблю попробовать сам и понять как это работает, так сказать на всякий случай, в целях самообразования. Просто читаешь иногда посты, там говорят что мол это невозможно, а начинаешь пробовать и всё получается. Вот не помню уж где-то видел, что нельзя анализировать звук, а я анализирую без проблем.
Вверх
DarkMaster
Цитата
Дарк, а есть такая возможность получить некий результат в виде переменной из скрипта Lua в обычный скрипт?

Нет. И подозреваю, что даже между запущенными на луа скриптами будет определенная проблема передать данные. Изначально там была глобальная область видимости для глобальных переменных, т.е.
local a = 10 -- видно в пределах вкладки
a = 10 -- видно из любой. Но т.к. это приводило к катастрофам - все было разделено.
Так что только файликами. В луа думаю можно поискать дллки чтобы с ком портами работать, но в стандартном синтаксисе это только плагин писать либо какими-то невероятным костылями со сторонними exe, и может буфером.

Про звук поделиться не хотите?
Вверх
WKnight
Цитата
а есть такая возможность получить некий результат в виде переменной из скрипта Lua в обычный скрипт?

Теоретически есть. А смысл?
Вверх
sutra
Смысла нет, просто скрипт огромный, хотел частями попробовать, так что проехали.

А про звук ... Ну программер из меня хреновый, а вот придумывать я мастак. Сначала хотел всё делать "по уму", но как я уже сказал, программер из меня... Поэтому сделал просто. Вывожу микшер куда мне надо (засунул на второй монитор в самый низ). А потом всё тем же Файндом просто контролирую шкалу громкости. Как минимум длительность звука и его пиковые пороги контролировать элементарно. Теоретически можно и синусоиду контролировать, тогда нужно чтобы постоянно висела какая-нибудь программулина, но это уж точно изврат.

Файнды - ЭТО СИЛА. Думаю в Lua всё будет "летать" и я никаких проблем и ограничений для себя не вижу. Ещё раз спасибо Кнайту. Несмотряна то, что я нищий, если заведу себе яндекс деньги, то отблагодарю.

С одним монитором в полноэкранном режиме естественно не прокатит. А меня вполне устраивает. А по уму надо как я понимаю плагин прикручивать. Только как вытащить туда звуки системы я не знаю, но теоретически однозначно можно. Микшер то вытаскивает ...
Вверх
Invision Power Board © 2001-2024 Invision Power Services, Inc.
Version for Pocket PC © 2006-2024, IPBest Studio.