A complete guide to Lua controllers can be found at: http://mesecons.net/luacontroller
Some of the crafting recipes are different.

Tutorial na

https://h2mm.gitlab.io/web/tutorials/digilines.html


 

ukázku kódu z Minetestu

CACTUS FARM by PeterisU1

code 1 z prvniho luacontrolleru:

local channel = "button1"

-- Define temp globally to ensure it exists prior to any event handling
local temp = {}

local function minfy(sec)
  return math.floor(sec / 60)
end

mem.names = mem.names or {}  -- Ensure persistence of names across events

if event.type == "program" then
  digiline_send(channel, "stop")
  digiline_send("lcd", "Hello, want some cactus?")
  digiline_send("debug", "Hello! \n TABLE <-- --> last digiline msg \n\n down - clean table")
end

local function padString(str, length)
    local paddedStr = str
    while #paddedStr < length do
        paddedStr = paddedStr .. " "
    end
    return paddedStr
end

--- clean table on DOWN
if event.type == "digiline" and event.msg == "down" then
   mem.names = {}
   digiline_send("debug","--TABLE cleaned--")
end

-- Check for Digiline event and "left" message
if event.type == "digiline" and event.msg == "left" then
    local message = ""
    if type(mem.names) == "table" then
        for player, details in pairs(mem.names) do
            local playerName = padString(player, 20)
            local lastTime = padString(tostring(details.lt), 10)
            local cactusCount = padString(tostring(details.q), 6)
            message = message .. playerName .. ": Last Time - " .. lastTime .. " - Cactus: " .. cactusCount .. "\n"
        end
    else
        message = "Error: mem.names is not a table or does not exist."
    end
    digiline_send("debug", message)
end

if event.type == "digiline" and event.channel == channel then
  if event.msg.action == "player" and event.msg.name then
    local playerName = event.msg.name
    local lcdstr = ""
    temp.names = mem.names or {}
    temp.ct = minfy(os.time())
    local dt = temp.names[playerName] or {q=0, lt=0}
    
    if dt.q == 0 then  -- Only serve if they have never received cactus before
      local cactus_amount = 10
      dt.q = cactus_amount
      dt.lt = temp.ct
      lcdstr = playerName .. ": Welcome! You get " .. cactus_amount .. " initial cactus."
      digiline_send("storage", "output default:cactus " .. cactus_amount)
      temp.names[playerName] = dt
    else
      lcdstr = playerName .. ": Sorry, no more cactus available."
    end

    mem.names = temp.names
    digiline_send("lcd", lcdstr)

    -- Optional: Reset message after a delay
    interrupt(10, "reset_message")
  end
elseif event.type == "interrupt" and event.iid == "reset_message" then
  digiline_send("lcd", "Hello, want some cactus?")
end

code 2 z druheho luacontrolleru:

-- Define global variables
local interval1_duration = 60 -- will harvest once a 5 minutes
local interval2_duration = 2  -- Duration of interval2 s
local max_count = 6           -- Maximum count for the loop

if event.type == "program" then
    mem.counter = 0 -- Initialize a counter in memory to keep track of the loop iterations
    interrupt(interval1_duration, "interval1") -- Start the first interval
elseif event.type == "interrupt" and event.iid == "interval1" then
    mem.counter = mem.counter + 1 -- Increment the counter
    if mem.counter <= max_count then -- Check if the counter is within the desired range
        digiline_send("br", "break " .. mem.counter) -- Send the message
        interrupt(interval2_duration, "interval2") -- Set the next interrupt for the pause
    else
        mem.counter = 0 -- Reset the counter after reaching the max count
        interrupt(interval1_duration, "interval1") -- Set the next interrupt for the main interval
    end
elseif event.type == "interrupt" and event.iid == "interval2" then
    -- After the pause, continue or restart the process
    if mem.counter < max_count then
        interrupt(interval2_duration, "interval1") -- Immediately set the next main interval if more messages need to be sent
    else
        interrupt(interval1_duration, "interval1") -- Restart the main interval after the last message
    end
end


STEAK HOUSE

code luacontroller:

local channel = "button1"  --
local function minfy(sec)
  return math.floor(sec / 60)
end

local function gms(min)
  return math.floor(minfy(os.time()) - min)
end

local temp = {}
mem.names = mem.names or {}  -- Ensure persistence of names across events

if event.type == "program" then
  digiline_send(channel, "stop")  -- Adjusted to use the new channel
  digiline_send("lcd", "Hello, want some steak?")
  digiline_send("debug", "Hello! \n TABLE <-- --> last digiline msg \n\n down - clean table")
end

local function padString(str, length)
    local paddedStr = str
    while #paddedStr < length do
        paddedStr = paddedStr .. " "  -- Using spaces for padding for better readability
    end
    return paddedStr
end


--- clean table on DOWN
if event.type == "digiline" and event.msg == "down" then
   mem.names = {}
   digiline_send("debug","--TABLE cleaned--")
end

-- Check for Digiline event and "left" message
if event.type == "digiline" and event.msg == "left" then
    local message = ""
    if type(mem.names) == "table" then
        for player, details in pairs(mem.names) do
            local playerName = padString(player, 20)
            local lastTime = padString(tostring(details.lt), 10)
            local steaks = padString(tostring(details.q), 6)
            message = message .. playerName .. ": Last Time - " .. lastTime .. " - Steaks: " .. steaks .. "\n"
        end
    else
        message = "Error: mem.names is not a table or does not exist."
    end
    digiline_send("debug", message)
end

if event.type == "digiline" and event.channel == channel then
  if event.msg.action == "player" and event.msg.name then
    local playerName = event.msg.name
    local lcdstr = ""
    temp.names = mem.names or {}
    temp.ct = minfy(os.time())
    local dt = temp.names[playerName] or {q=0, lt=0}  -- Adjusted to not subtract from current time initially
    
    local timepassed = temp.ct - (dt.lt or 0)
    local isNew = dt.q == 0

    if isNew then
      local initial_steaks = 5
      dt.q = initial_steaks
      dt.lt = temp.ct  -- Update time here as steaks are given
      lcdstr = playerName .. ": Welcome! You get " .. initial_steaks .. " initial steak(s). And some wood to craft your first armor and things."
      digiline_send("storage", "output animalia:beef_cooked " .. initial_steaks)
      digiline_send("storage", "output df_trees:blood_thorn " .. 10)
      temp.names[playerName] = dt  -- Update table here
    elseif timepassed > 119 then
      local new_steaks = math.min(math.floor(timepassed / 120), 30)
      dt.q = dt.q + new_steaks
      dt.lt = temp.ct  -- Update time here as steaks are given
      lcdstr = playerName .. ": You get " .. new_steaks .. " steak(s) for your patience."
      digiline_send("storage", "output animalia:beef_cooked " .. new_steaks)
      temp.names[playerName] = dt  -- Update table here
    else
      lcdstr = playerName .. ": Hey! You got steaks " .. timepassed .. " minutes ago. You can have more steaks in " .. (120 - timepassed) .. " minutes."
      -- Note: We do NOT update the table here since no steaks are given
    end

    mem.names = temp.names
    digiline_send("lcd", lcdstr)

    -- Optional: Reset message after a delay
    interrupt(10, "reset_message")
  end
elseif event.type == "interrupt" and event.iid == "reset_message" then
  -- Reset the message on the LCD to a general welcome or status message
  digiline_send("lcd", "Hello, want some steak?")
end

 

 


BOARD DIGILINE

digiline_send("board","/1NazevKteryChciAbyBezelNaLEDCe")
/1 az /9 cisla urcuji barvu pisma

 

 MOVE MACHINE CODE:

-- [digimovestone="a"/"b"/"c"/"d"] to match labeling of luacontroller
-- [digimovestone="fence"][luacontroller][digimovestone="fence"]
-- [digimovestone="a"/"b"/"c"/"d"] to match labeling of luacontroller
-- Can extend length by adding digimese or digiline between luacontroller and any "fence"
-- Clear channelname of any "fence" to pause, requires two "fence" to be running.

if event.type=="program" then
  mem = {offset={a={x=-1,z=0},b={x=0,z=1},c={x=1,z=0},d={x=0,z=-1}}}
end

if event.type=="digiline" then

  if (event.channel=="fence") and event.msg.pos then
    if not mem.fence then
      mem.fence = {}
    elseif #mem.fence < 2 then
      table.insert(mem.fence, event.msg.pos)
    end
    if #mem.fence == 2 and (mem.fence[1].y - mem.fence[2].y == 0)  then
      dx = mem.fence[1].x - mem.fence[2].x
      dz = mem.fence[1].z - mem.fence[2].z
      if (dx == 0) and not (dz == 0) then
        digiline_send("a", {command = "getstate"})
        digiline_send("c", {command = "getstate"})
      elseif (dz == 0) and not (dx == 0) then
        digiline_send("b", {command = "getstate"})
        digiline_send("d", {command = "getstate"})
      end
    end
  end

  if (mem.offset[event.channel] ~= nil) and (#mem.fence == 2) and event.msg.pos then
    idx = 1
    if (mem.offset[event.channel].z == 0 and
        (math.abs(event.msg.pos.z - mem.fence[1].z) <
        math.abs(event.msg.pos.z - mem.fence[2].z))) or
       (mem.offset[event.channel].x == 0 and
        (math.abs(event.msg.pos.x - mem.fence[1].x) <
        math.abs(event.msg.pos.x - mem.fence[2].x))) then
      idx = 2
    end

    digiline_send(event.channel,{command="absmove",
        x=mem.fence[idx].x + mem.offset[event.channel].x,
        y=mem.fence[idx].y,
        z=mem.fence[idx].z + mem.offset[event.channel].z})
  end

end

if event.type == "interrupt" then
  mem.fence={}
  digiline_send("fence", {command = "getstate"})
end

interrupt(5,"-")


LAVA MACHINE (meni lavu na obsidian)

if event.type == "program" then
  mem=true
end

if event.type == "interrupt" then
  if mem==true then
    mem=false
    digiline_send("up", "retract")
    digiline_send("over", "extend")
  else
    mem=true
    digiline_send("up", "extend")
    digiline_send("over", "retract")
  end
end

interrupt(6)


BLOODSTEM COLLECTOR (nastaveni lua controleru)


-- Define global variables
local interval1_duration = 120 -- Duration of interval1 s
local interval2_duration = 2  -- Duration of interval2 s
local max_count = 5           -- Maximum count for the loop

if event.type == "program" then
    mem.counter = 0 -- Initialize a counter in memory to keep track of the loop iterations
    interrupt(interval1_duration, "interval1") -- Start the first interval
elseif event.type == "interrupt" and event.iid == "interval1" then
    mem.counter = mem.counter + 1 -- Increment the counter
    if mem.counter <= max_count then -- Check if the counter is within the desired range
        digiline_send("br", "break " .. mem.counter) -- Send the message
        interrupt(interval2_duration, "interval2") -- Set the next interrupt for the pause
    else
        mem.counter = 0 -- Reset the counter after reaching the max count
        interrupt(interval1_duration, "interval1") -- Set the next interrupt for the main interval
    end
elseif event.type == "interrupt" and event.iid == "interval2" then
    -- After the pause, continue or restart the process
    if mem.counter < max_count then
        interrupt(interval2_duration, "interval1") -- Immediately set the next main interval if more messages need to be sent
    else
        interrupt(interval1_duration, "interval1") -- Restart the main interval after the last message
    end
end

 
 

 -- ======================================================================================
-- We will be using the Queue data structure three times, so it is worth getting it right
-- ======================================================================================
local Queue = {}
Queue.PREV = {}
Queue.NEXT = {}
Queue.FIRST = {}
Queue.LAST = {}

function Queue.new()
  local tab = {}
  tab[Queue.FIRST] = {}
  tab[Queue.FIRST][Queue.NEXT] = nil
  tab[Queue.LAST] = {}
  tab[Queue.LAST][Queue.PREV] = nil
  return tab
end

function Queue.is_empty(q)
  if q[Queue.FIRST] == nil then
    return true
  else
    return q[Queue.FIRST][Queue.NEXT] == nil
  end
end

function Queue.contains(q, el)
  return el ~= nil and (q[el] ~= nil or q[Queue.LAST][Queue.PREV] == el)
end

function Queue.get_first(q)
  if q[Queue.FIRST] ~= nil then
    return q[Queue.FIRST][Queue.NEXT]
  else
    return nil
  end
end

function Queue.set_first(q, el)
  q[Queue.FIRST][Queue.NEXT] = el
  return true
end

function Queue.get_last(q)
  return q[Queue.LAST][Queue.PREV]
end

function Queue.set_last(q, el)
  q[Queue.LAST][Queue.PREV] = el
  return true
end

function Queue.insert(q, el)
  if el ~= nil and not Queue.contains(q, el) then
    if Queue.is_empty(q) then
      Queue.set_first(q, el)
      q[el] = {}
      Queue.set_last(q, el)
    else
      local tail = Queue.get_last(q)
      q[tail][Queue.NEXT] = el
      q[el] = {}
      q[el][Queue.PREV] = tail
      Queue.set_last(q, el)
    end
    return true
  end
  return false
end

function Queue.remove(q)
  if Queue.is_empty(q) then
    return
  end
  if Queue.get_first(q) then
    local head = Queue.get_first(q)
    local new_head = q[head][Queue.NEXT]
    q[head] = nil
    if q[new_head] and q[new_head][Queue.PREV] then
      q[new_head][Queue.PREV] = nil
    end
    Queue.set_first(q, new_head)
    return head
  else
    return nil
  end
end

function Queue.loop(q, func)
  local next = q[Queue.FIRST][Queue.NEXT]
  local output_table = {}
  while next ~= nil do
    local curr = next
    if func then
      func(curr)
    else
      table.insert(output_table, curr)
    end
    next = q[curr][Queue.NEXT]
  end
  if not func then
    return output_table
  else
    return true
  end
end
-- ======================================================================================

local function tableLength(T)
  local L = 0
  for i, _ in pairs(T) do
    L = L + 1
  end
  return L
end

local function tableLengths(listOfTables)
  local totalLength = 0
  for i, t in pairs(listOfTables) do
    totalLength = totalLength + tableLength(t)
  end
  return totalLength
end

local function processAction(action, tbl)
  local unitID = Queue.remove(tbl[1])
  digiline_send(unitID .. "_" .. action, tbl[3])
  if tbl[2] then
    Queue.insert(tbl[2], unitID)
  end
  sendMessage("display", unitID)
  return true
end

local function process(action)
  local queues = {}
  queues["break"] = {mem.break_queue, mem.plant_queue, "break 1"}
  queues["plant"] = {mem.plant_queue, mem.input_queue, "deploy " .. mem.crop.item}
  queues["input"] = {mem.input_queue, false, "output " .. mem.crop.item .. " 1"}
  for _, action in ipairs({"input", "plant", "break"}) do
    processAction(action, queues[action])
  end
end

local function isFindUnit(event)
  if string.find(event.channel, "_find", 1, true) then
    return true
  else
    return false
  end
end

local function splitString(inputstr, sep)
  if sep == nil then
    sep = "%s"
  end
  local t = {}
  for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
    table.insert(t, str)
  end
  return t
end

local function obtainUnitID(event)
  local s, e = string.find(event.channel, "_find", 1, true)
  return string.sub(event.channel, 1, s-1)
end

local function sendMessage(channel, C)
  digiline_send(channel, "*** Farm monitor ***\nLast dug: " .. mem.crop.name .. "\nChannel: " .. C .. "\nNum dug: " .. mem.dugs .. "\nLength of queue: " .. tableLength(mem.queue))
end

local function reset()
  mem.dugs = 0
  mem.break_queue = Queue.new()
  mem.plant_queue = Queue.new()
  mem.input_queue = Queue.new()
end

local function controlPanel(event)
  if event.msg == "back" then reset() end
end

local function findUnit(event)
  local M = event.msg.detected[1]
  local C = obtainUnitID(event)
  if M.label ~= mem.crop.item .. "_" .. mem.crop.harvest then
    return
  end
  Queue.insert(mem.break_queue, C)
  mem.dugs = mem.dugs + 1
  sendMessage("display", C)
end

if event.type == "program" then
  mem.crop = {
    item = "farming:potato",
    harvest = "4",
    name = "Potato"
  }
  reset()
  digiline_send("display", "Initialised!\nLength of break queue is " .. tableLength(mem.break_queue)-2)
  mem.initialised = true
end

if event.type == "digiline" and mem.initialised then
  if isFindUnit(event) then
    findUnit(event)
  end
end

if event.type == "on" then
  for _, i in pairs({"input", "plant", "break"}) do
    process(i)
  end
end


TREE BREAKER ASPEN by niceride

code luacontroller:

Id = "cb"

List = {}

function List.new ()
  return {first = 0, last = -1}
end

function List.pushl (l, v)
  l.first = l.first - 1
  l[l.first] = v
end

function List.popr (l)
  local v = nil
  if l.first <= l.last then
    v = l[l.last]
    l[l.last] = nil
    l.last = l.last - 1
  end
  return v
end

function harvest ()
  List.pushl(mem.q, {ch="dig " .. Id, cmd="break 1"})
  List.pushl(mem.q, {ch="dig " .. Id, cmd="break 2"})
  List.pushl(mem.q, {ch="dig " .. Id, cmd="break 3"})
  List.pushl(mem.q, {ch="dig " .. Id, cmd="break 4"})
  List.pushl(mem.q, {ch="dig " .. Id, cmd="break 5"})
  interrupt(0.2)
end

if event.type == "program" then
  mem = { q = List.new() }
  harvest()
end

if event.type == "digiline" and event.channel == "det " .. Id and event.msg.action == "detect" then
  for ak, av in pairs (event.msg.detected) do
    for dk, dv in pairs (event.msg.detected[ak]) do
      if dk == "name" and dv == "default:aspen_tree" and mem.q.last < mem.q.first then
        harvest()
      end
    end
  end
end

if event.type == "on" and event.pin.name == string.upper(string.sub(Id, -1, -1)) then
  if mem.q.last < mem.q.first then harvest() end
end

if event.type == "interrupt" then
  if mem.q.last >= mem.q.first then
    local r = List.popr(mem.q)
    digiline_send(r.ch, r.cmd)
    interrupt(heat+0.2)
  end
end