Перейти к содержимому

FredoNook

Пользователи
  • Публикации

    5
  • Зарегистрирован

  • Посещение

  • Победитель дней

    1

Сообщения, опубликованные пользователем FredoNook


  1. Понадобилось нечто подобное, человеческого ини парсера найти не удалось, посмотрел эту либу немного переписал. Возможно кому-то больше понравится моя реализация.

     

    Плюсы по сравнению с оригиналом:

    1. Объектный подход

    2. В таблицах не хранятся никакие лишние данные, только непосредственно те что вы там сохранили, вспомогательные данные и методы хранятся в метатаблице

    3. Вытекает из второго в файлы не сохраняются пути до них, сохраняются только ваши данные

     

     

     

    --by 1Ridav, rewritten by FredoNook
    ---http://computercraft.ru
    local PWD = os.getenv("PWD")
     
    local pref = {}
    local meta = {}
     
    meta.filename = ""
    meta.table = {}
     
    local function load(path)
      local table = {}
      local key, value, delimeter
      local len = 0
     
      local f = io.open(path, "r")
      if not f then return nil end
     
      for line in f:lines() do
        len = len + 1
        delimeter = string.find(line, "=")
        key = string.sub(line, 1, delimeter-1)
        value = string.sub(line, delimeter+1, #line)
        table[key] = value
      end
     
      f:close()
      if len == 0 then return nil end
      return table
    end
     
    function meta.__call(op, path)
      local newmeta = {}
      for n, v in pairs(meta) do
        newmeta[n] = v
      end
      local table = load(PWD..path) or {}
      newmeta.table = table
      newmeta.filename = PWD..path
      newmeta.__index = newmeta
      setmetatable(table, newmeta)
      return table
    end
     
    function meta:save()
      local f = io.open(self.filename, "w")
      if not f then return false end
      for k, v in pairs(self.table) do
        f:write(k.."="..v.."\n")
      end
      f:close()
      return true
    end
     
    setmetatable(pref, meta)
    return pref

     

     

     

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

    preferences = pref("filepath")
    

    В случае если файл найден открывает его и парсит в переменную preferences, в случае если файл отсутствует создает новую таблицу в preferences.

    preferences:save()
    

    Сохраняет таблицу в файл (по пути который был задан в pref("filename"))

     

    Пример:

    pref = require("pref") // подключаем либу
    
    settings = pref("bob.cfg") -- В рабочей директории нет файла bob.cfg поэтому создается новая таблица
    settings.fname = "Bob"  -- Добавляем значения к таблице
    settings.lname = "Marley"
    settings.year = 90
    settings.status = "Narcoman"
    settings:save() -- сохраняем таблицу в файл bob.cfg в рабочей директории
     
    settings = pref("bob.cfg") -- Открываем файл bob.cfg поскольку он есть в рабочей директории
    settings.year = 00  -- Меняем значения в загруженной таблице
    settings.status = "Icon"
    settings:save() -- Сохраняем таблицу в файл bob.cfg в рабочей директории
    
    

    PS Переписано за пять минут, толком не тестировалось. Возможны ошибки, хотя крайне маловероятны. Feedback welcome.

    • Нравится 3

  2. Фрэдо, правда, а сделай графический редактор? Пусть эти макросы действительно как в CCedu будут блоками. Объеденись с кем нибудь и замути. Будет ведь суперски.

     

    Теоретически можно, но сейчас я тут разбираюсь в модах поскольку я ничего о них не знаю, и обживаюсь на сервере. Как маломальски адекватный уровень будет, можно разбираться будет с gpu'ом, как оно там все работает и рисует. Я мельком взглянул на апи не совсем понял что там к чему. 


  3. Недавно делал шину(bus) в star-made там нету компутеров так что все на логике. Короче считаешь сколько тебе нужно вариантов 2^Xbit. допутим я делал 5ти битную шину, значит у меня было 0-31, тоесть 32 значения. Дальше подключаю к шине компараторы идентичности, ну в луа обойдемся == тоесть если пришедший бит == тому который ждем отлично нас зовут. еще одна линия (6) в шине Tx то есть линия отправки сигнала. Все слушают Tx если Tx 1 значит надо читать шину. Для расшифровки я делал бинарный кодер и декодер. здесь я думаю можно обойтись tonumber(val,x). Сигналы можно пускать в очередь, тоесть на пятибитной шине можно передать число любого размера главное что бы n * 32 было >= числу, где n колличество передач сигнала. Так же я использовал сигнал 11111 (31) для резета шины, поскольку на шине каждый прибор был с очередью все приборы кроме того код которого слался блокировались до того как отработал этот прибор и послал 11111 в шину. 
    Не спал много часов, прогал несколько часов подряд поэтому мысли очень сумбурны).

     

    PS Насколько я знаю в майнкрафте 20 тиков в секунду. соответственно скорость сети будет (10 * Xbit) / 8 byte/sec , 10 потому что я бы делал перерыв по одному тику между ближайшими Tx'ми.


  4. Круто, на CC делал подобное, но теперь там есть http://www.computercraft.info/2015/07/01/introducing-computercraftedu/

     

    Интересно, но я не люблю визуальное программирование, если это не behaviour-tree или fsm ну или какой нибудь граф типа диалога или квеста).


  5. Привет! Небольшое предисловие. Программа которую я подготовил сделана специально для того чтобы получить доступ на сервер. Код может быть ужасен, потому что это моя первая программа на Lua. Да сегодня утром я еще ничего не знал о Lua, а пару дней назад я не знал о OpenComputers и вообще что в к майнкрафту появилась куча интересных плагинов. Последний раз я играл в майнкрафт в 2012 году и это была ванилла.
     
    А теперь к делу - программа эта одновременно интерпритатор макроязыка который я назвал IronMacros и библиотека которая позволяет его расширять. Синтаксис довольно аутистский но очень краткий.
     
    Пример тестового макроса (скрины результата приложены):

    S1# select 1st slot
    R020C# make 2
    R060B# 6 cubes
    R0502# x5 cubes planes
    P0M# place cube go up
    >^<WWWWW#move next stripe
    S2# select pickaxe
    R0502
    XFM
    <^>WWWWW
    XFM<^>#star cut U
    R030A
    R0402
    XFM
    <^>WWWW
    WXF<^>
    R0502
    XFM#star cut R
    W<^>XF
    WWXFWW
    <^>
    R030C
    XFMXFMMXF
    <^>WWW
    <^>
    R0502
    XFM
    

    Можно одной строкой (жесть):

    S1R020CR060BR0502P0M>^<WWWWWS2R0502XFM<^>WWWWWXFM<^>R030AR0402XFM<^>WWWWWXF<^>R0502XFMW<^>XFWWXFWW<^>R030CXFMXFMMXF<^>WWW<^>R0502XFM
    

    Результат:

     

     

    2d8qmvq.png

     

    29m679z.png

     

    svl16g.png

     

    kain7o.png

     

    258cy89.png

     

    2rhrbqx.png

     

     

     

    Сама библиотека/интерпритатор:

     

    -- ====================
    -- IronMacros.lua
    -- Created by FredoNook
    -- ====================
     
    local rb = require("robot")
    local sh = require("shell")
     
    -- module table
    local im = {}
    -- symbols restricted to unregister
    local restrictedSymbols = {"#"}
    -- macros queue
    local macros = {}
    -- macros execution register
    im.pc = {["x"] = 1, ["y"] = 1}
    -- registred macro commands
    local macroses = {}
     
    -- ===========================
    -- MACROS MANAGEMENT FUNCTIONS
    -- ===========================
     
    -- Register an macro symbol with func
    function im.registerMacros(symbol, func)
      if #symbol > 1 then
        error("Macro command can't be longer then one symbol")
      end
      if isSymbolRestricted(symbol) then
        error("Symbol \""..symbol.."\" is restricted")
        return
      end
      macroses[tostring(symbol)] = func
    end
     
    -- unregister an macro symbol
    function im.unregisterMacros(symbol)
      if #symbol > 1 then
        error("Macro command can't be longer then one symbol")
      end
      if isSymbolRestricted(symbol) then
        error("Symbol \""..symbol.."\" is restricted")
        return
      end
      macroses[tostring(symbol)] = nil
    end
     
    -- ====================
    -- PC REGISTER FUNCTION
    -- ====================
     
    -- register x step forward
    im.pc.fstep = function(count)
      if count == nil then im.pc.x = im.pc.x + 1
      else im.pc.x =  im.pc.x + count end
    end
     
    -- register y step down
    im.pc.dstep = function(count)
      if count == nil then im.pc.y = im.pc.y + 1
      else im.pc.y = im.pc.y + count end
      im.pc.x = 1
    end
     
    -- set register reg to value val
    im.pc.set = function(reg, val)
      if reg == "x" then im.pc.x = val
      elseif reg == "y" then im.pc.y = val
      else error("Wrong register idintificator")
      end
    end
     
    -- ===================
    -- EXECUTION FUNCTIONS
    -- ===================
     
    -- run macro file with filename
    function im.run(filename)
      local file = io.open(filename)
      local i = 1
      for line in file:lines() do
        macros[i] = line
            i = i + 1
      end
      file:close()
      local cmd = " "
      while cmd do
        cmd = im.readCmd()
        if cmd == nil then break end
        im.exec(cmd)
      end
    end
     
    -- exec macro command cmd
    function im.exec(cmd)
      if cmd ~= nil then macroses[cmd]() end
    end
     
    -- read command from registers position
    function im.readCmd()
      local cmd
      if im.pc.x == #macros[im.pc.y] + 1 then
        if #macros == im.pc.y then
          io.write("MACROS COMPLETED")
          return nil
        else
              im.pc.dstep()
          cmd = macros[im.pc.y]:sub(im.pc.x, im.pc.x)
          im.pc.fstep()
          io.write("CURRENT CMD: "..cmd.."\n")
          return cmd
        end
      end
      cmd = macros[im.pc.y]:sub(im.pc.x, im.pc.x)
      im.pc.fstep()
      io.write("CURRENT CMD: "..cmd.."\n")
      return cmd
    end
     
    -- ================
    -- MODULE FUNCTIONS
    -- ================
     
    -- check symbol for restriction
    local function isSymbolRestricted(symbol)
      for key, value in pairs(restrictedSymbols) do
        if value == symbol then return true end
      end
    end
     
    -- =========================
    -- REGISTER DEFAULT MACROSES
    -- =========================
     
    -- set # as commentary command
    macroses["#"] = function()
      if #macros == im.pc.y then
        im.pc.x = #macros[im.pc.y] + 1
      else
        im.pc.dstep()
      end
    end
    -- set " " as NOP command
    macroses[" "] = function() end
    -- set ^ as forward command
    macroses["^"] = function() rb.forward() end
    -- set > as turn right command
    macroses[">"] = function() rb.turnRight() end
    -- set V as backward command
    macroses["V"] = function() rb.back() end
    -- set < as turn left command
    macroses["<"] = function() rb.turnLeft() end
    -- set M as up command
    macroses["M"] = function() rb.up() end
    -- set W as down command
    macroses["W"] = function() rb.down() end
    -- set R as repeat command.
    -- format: RXXYY where
    -- XX loop count in hex
    -- YY count of forward command to repeat
    -- except # " " and parameters of other commands
    macroses["R"] = function()
      local cycleCount = tonumber(im.readCmd()..im.readCmd(), 16)
      local cmdCount = tonumber(im.readCmd()..im.readCmd(), 16)
      local cycleStartPoint = {["x"] = im.pc.x, ["y"] = im.pc.y}
      local cycc, cmdc = 1, 1
      while cycc < cycleCount do
        while cmdc <= cmdCount do
          local cmd = im.readCmd()
          if cmd == "#" then cmdc = cmdc - 1 end
          if cmd == " " then cmdc = cmdc - 1 end
          im.exec(cmd)
          cmdc = cmdc + 1
        end
        cmdc = 1
        im.pc.x = cycleStartPoint.x
        im.pc.y = cycleStartPoint.y
        cycc = cycc + 1
      end
    end
    -- set S as select inventory slot command
    -- format: SX
    -- where X number of slot to select in hex
    macroses["S"] = function()
      local item = tonumber(im.readCmd(), 16)
      rb.select(item)
    end
    -- set P as place command
    -- format: PX
    -- where X number of placing block side
    macroses["P"] = function()
      local side = tonumber(im.readCmd(), 16)
      rb.place(side)
    end
    -- set X as remove/attack command
    -- format: XY
    -- where Y number of removing block side
    macroses["X"] = function()
      local side = tonumber(im.readCmd(), 16)
      local remfin = true
      while remfin do
        if side == 15 then rb.swing()
            else rb.swing(side) end
            if not rb.detect() then remfin = false end
      end
    end
     
     
    --- ===========
    --- ENTRY POINT
    --- ===========
     
    -- get execution args
    local args = sh.parse(...)
    if #args == 0 then
      io.write("Usage: ironmacros <macrosfile> [repeatly(true/false)]")
    elseif #args == 1 then
      im.run(args[1])
    else
      -- TODO: Repeatly execution
    end
     
    return im
    

     


    Как использовать:
    1. Пишем макрос сохраняем в файл
    2. В терминале пишем ironmacros <filename>
        filename это имя нашего макроса
    3. Profit
     
    Имплементированные макрокоманды
    # - комментарий, после символа вся строка пропускается
    ^ - двигаться вперед 
    V - двигаться назад
    > - повернуться вправо
    < - повернуться влево
    M - двигаться вверх
    W - двигаться вниз
    RXXYY - цикл, где XX количество повторов в 16тиричной системе. YY количество команд, которые следует повторять в 16тиричной системе ( считаются только команды, аргументы, передаваемые командам, упускаются)
    SX - выбрать слот инвентаря с номером X, номер X 16тиричный
    PX - поставить блок впереди себя X - на какой сайд ставить (аналог place([side]))
    XY - махнуть активным слотом (атака/поломка блоков) где Y по какому сайду бить (аналог swing([side]) при передаче в качестве параметра F вызывается подефолту swing()
     
    Ну и как вы уже заметили (я надеюсь) сейчас все это заточено исключительно под робота.
     
     
    Вкратце о внутренностях:
     
    1. функции управления литералами макрокоманд
    registerMacros(symbol, func)
    unregisterMacros(symbol)
    регистрирует или снимает регистрацию заданного символа. func функция обработчик
    например так:

    im = require("ironmacros")
    
    local func = function() print("ZzzZzzZzzZ") end
    im.registerMacros("Z",func)
    
    

    теперь если записать в макрос Z будет в терминал будет напечатано "ZzzZzzZzzZ"
    Эти функции нужны лишь для того что бы расширять язык. Для пользования текущей версией они не нужны.
     
    2. функции исполнения
    run(filename) - открывает файл в котором записана последовательность макрокоманд и запускает ее. filename - имя файла
    readCmd() - читает макрокоманду соответственно значению регистра pc(pc.x pc.y)
    exec(cmd) - запускает команду cmd на исполнение. Под командой имеется ввиду макрокоманда "Z" или ">"
    Эти функции нужны лишь для того что бы расширять язык. Для пользования текущей версией они не нужны.
     
    3. Функции управления регистром
    fstep([count]) - функция инкрементирует значение регистра pc.x (если требуется инкрементировать pc.y , pc.x присваивается 1 ). count опционально коллчество шагов
    dstep([count]) - функция инкрементирует pc.y присваивает pc.x 1 если больше нет команд на исполнение заканчивает скрипт. count опционально коллчество шагов
    set(reg, val) - установить регистр reg ("x" или "y") на значение val
    Эти функции нужны лишь для того что бы расширять язык. Для пользования текущей версией они не нужны.
     
    4. Добавление своей макро команды
    В исходнике все макрокоманды добавлены используя вышеприведенные функции.
    Можно ознакомится, там все просто. Раздел REGISTRED DEFAULT MACROSES
     
     
     
    PS Да забыл pastebin.com:
     
    lib: http://pastebin.com/eBbZrRGi
    macros: http://pastebin.com/Q4DRDKDV

    • Нравится 6
×
×
  • Создать...