Jump to content




Thaumcraft Automation Programming

help lua peripheral

49 replies to this topic

#1 the_hyren

  • Members
  • 29 posts

Posted 02 December 2015 - 08:38 PM

Sorry about the Wall'o text:

So I have a nearly finished autocrafting system for thaumcraft but I need some help programming an advanced computer to run the process, but I've been having trouble getting code to work. There is 5 computers, 1 needs programmed to read the number of cobble in a chest and annouce that number via a peripheral++ chatbox to one of four other computers. I call this one the manager. The first program simply takes the cobble input and annouces it to one of the other 4 computers, based on which are currently not crafting. This should be easy with 4 bool variables and a switch statement. The other 4 computers are mostly identical except for orientation, i call these infuser1 through 4. These contain a table loaded from a file, which has all the recipes, the number of cobble annouced represents on of these recipes. Next I for loop this column in the table into a method that retrieves and crafts items as necessary from my ME system, placing them in a chest that fills the pillars in order clockwise and center last, the rest of the items go into a set of alchemical furnaces that generate the essentia needed. Once this is complete the computer needs to emit a redstone signal to the rear enabling a itemduct retriever that grabs my filler item (wood sword). This item represents all the empty pillar slots that there will be while crafting. 30 seconds later we disable that redstone. Next wait a few minutes for most the essentia items to finish (gonna try sleep(180) to start). Then we emit redstone to the left which makes an autonomous activator wand whack the matrix.

I have my 4 helper functions written and they work fine:
function listen(string myname) waits until a chat event with the infusers name tag. it then returns the message sent
function start() sets left redstone on for 2 seconds, triggering activator
function removeFiller() sets rear redstone on for 30 seconds, removing the filler item (wood swords)
function grabItem(name) tries to grab the item, crafts it on failure, and then trys again

But in the while loop I'm having trouble with my if statements:

while true do
command = listen("infuser1:")
prefix = string.sub(command, 1, 6)
chat.say("Running command: " .. prefix)
if prefix == "infuse" then
txtnum = string.sub(command, 8)
chat.say("Getting recipe " .. txtnum)
num = tonumber(txtnum)

end
end

All I got but so far even if prefix == "infuse" the code in the if doesnt run...

#2 Lyqyd

    Lua Liquidator

  • Moderators
  • 8,462 posts

Posted 02 December 2015 - 10:03 PM

Moved to Ask a Pro.

#3 Dragon53535

  • Members
  • 971 posts
  • LocationIn the Matrix

Posted 02 December 2015 - 10:31 PM

I'm not sure if chatbox chat shows up for other chatbox's. Have you tested that?

#4 the_hyren

  • Members
  • 29 posts

Posted 03 December 2015 - 05:30 AM

I have not...ill do that now

right, minor issue there haha, doesnt seem to work. So if anyone has other suggestions about communication. if not ill wire all 4 bridges to one computer and integrate both programs. Either way i'd like to get the basic crafting loop done. Then i can make it a function and deal with the multi tasking part

#5 Dragon53535

  • Members
  • 971 posts
  • LocationIn the Matrix

Posted 03 December 2015 - 02:02 PM

You could just use wireless modems.

Can you show us your entire code please? I'd like to see the rest of it. Because I have a sneaking suspicion that the listen code returns "Infuser" and not "infuser"

Edited by Dragon53535, 03 December 2015 - 02:03 PM.


#6 the_hyren

  • Members
  • 29 posts

Posted 03 December 2015 - 07:14 PM

bridge = peripheral.wrap("right")
chat = peripheral.wrap("top")
fillerItem = "minecraft:wooden_sword"
mytag = "infuser1:"
recipefile = "recipes.txt"

function grabItem(name)

num = bridge.retrieve(name, 1, "north")
if num ~= 1 then
bridge.craft(name, 1)
crafting = true
while crafting do
local event, complete, crafted, num, bytes = os.pullEvent("craftingComplete")
crafting = complete
end
bridge.retrieve(name, 1, "north")
end
end

function listen(mytag)
listening = true
while listening do
local event, name, text = os.pullEvent("chat")
start, stop = string.find(text, mytag)
if start ~= nil and start >= 0 then
return string.sub(text, stop + 1)
end
end
end

function startInfusion()
redstone.setOutput("left", true)
sleep(2)
redstone.setOutput("left", false)
end

function removeFiller()
redstone.setOutput("back", true)
sleep(30)
redstone.setOutput("back", false)
end

function loadRecipes(filename)
file = fs.open(file, "r")
data = file.readAll()
file.close()
return textutils.unserialize(data)
end

function saveRecipes(filename, recipes)
file = fs.open(filename, "w")
data = textutils.serialize(recipes)
file.write(data)
file.close()
end

while true do
command = listen(mytag)
prefix = string.sub(command, 1, 6)
chat.say("Running command: " .. prefix)

end

#7 the_hyren

  • Members
  • 29 posts

Posted 03 December 2015 - 07:17 PM

So as I said, my helper functions all work as intended so far. But I cant seem to make any comparison in an if statement with my prefix var to get any code to work inside said if statement to happen. Brand new to lua language so im sure im just not used to tthe syntax. But I've done lots of php and java so coding algorithm isnt new to me at all

#8 the_hyren

  • Members
  • 29 posts

Posted 03 December 2015 - 08:03 PM

O and if anyone can shed light on if the serialize and unserialize functions (from textutils) works on matrices of strings. Since I'd prefer to not write a file parsing function of my own for loading the recipe file

#9 the_hyren

  • Members
  • 29 posts

Posted 03 December 2015 - 08:24 PM

wrote some new code:
a helper function; takes in matrix of strings which are the recipes for all infusions and the recipe row number

function infuse(recipes, recipenum)
length = table.getn(recipes[recipenum])
for i=1,length do
grabItem(recipes[recipenum][i])
end
removeFiller()
sleep(180)
startInfustion()
end

recipes = loadRecipes(recipefile)
while true do
command = listen(mytag)
prefix = string.sub(command, 1, 6)
info = string.sub(command, 8)

end

and the chat message: the listen function chops the name tag out 'infuser1:' in this case and returns the command so 'reload' or 'infuse someinteger'
prefix is the first 6 so 'reload' or 'infuse' this is what Im having trouble comparing. And info is any excess after a space, so '1' or '22' etc.

#10 Dragon53535

  • Members
  • 971 posts
  • LocationIn the Matrix

Posted 03 December 2015 - 11:31 PM

Quick couple things:

When typing a message there should be two <> up top, click on those and it will open a "code editor" just paste your code into that and it will allow it to show like this:
--#Heeey
Otherwise, you can use the [.code] [/code] tags to do the same thing.

Second: What do you mean by matrices of strings? Do you mean arrays of strings? If so, yeah it works on those.

What is table.getn? Do you mean maxn?

Edited by Dragon53535, 03 December 2015 - 11:34 PM.


#11 moomoomoo3O9

  • Members
  • 82 posts
  • LocationPork roll land

Posted 04 December 2015 - 12:00 AM

 Dragon53535, on 03 December 2015 - 11:31 PM, said:

Quick couple things:

When typing a message there should be two <> up top, click on those and it will open a "code editor" just paste your code into that and it will allow it to show like this:
--#Heeey
Otherwise, you can use the [.code] [/code] tags to do the same thing.

Second: What do you mean by matrices of strings? Do you mean arrays of strings? If so, yeah it works on those.

What is table.getn? Do you mean maxn?

table.getn() can be used to get the length, but if you're just using numerical indices (1-whatever) and don't plan on removing any values from the table, I recommend using #tbl (where tbl is the table you want the length of) instead of table.getn(tbl).

#12 Dragon53535

  • Members
  • 971 posts
  • LocationIn the Matrix

Posted 04 December 2015 - 12:37 AM

 moomoomoo309, on 04 December 2015 - 12:00 AM, said:

table.getn() can be used to get the length, but if you're just using numerical indices (1-whatever) and don't plan on removing any values from the table, I recommend using #tbl (where tbl is the table you want the length of) instead of table.getn(tbl).
Huh, learn new things every day, never used it, always either used ipairs/pairs or #tbl

#13 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 04 December 2015 - 02:24 AM

Truth be told, table.getn() isn't 100% reliable - it goes off and gets a cached value stored alongside the table which tracks its length, but it's possible to "confuse" that value (albeit via rather obscure methods) and the call doesn't check to see if it's accurate. table.maxn() does check, so naturally it was removed for Lua 5.2.

So long as there are no "gaps" in a table, # will work just fine (and seems to be the fastest choice execution-wise).

http://www.computerc...e-manipulation/

 the_hyren, on 03 December 2015 - 08:03 PM, said:

O and if anyone can shed light on if the serialize and unserialize functions (from textutils) works on matrices of strings.

Assuming by "matrix" you mean "table" (Lua's only container type), so long as they hold no functions or coroutines, and also use no recursion, serialise / unserialise should work just fine.

 the_hyren, on 03 December 2015 - 07:17 PM, said:

So as I said, my helper functions all work as intended so far. But I cant seem to make any comparison in an if statement with my prefix var to get any code to work inside said if statement to happen. Brand new to lua language so im sure im just not used to tthe syntax. But I've done lots of php and java so coding algorithm isnt new to me at all

You're still referring to this chunk?:

while true do
	command = listen("infuser1:")
	prefix = string.sub(command, 1, 6)
	chat.say("Running command: " .. prefix)
	
	if prefix == "infuse" then
		txtnum = string.sub(command, 8)
		chat.say("Getting recipe " .. txtnum)
		num = tonumber(txtnum)
	end
end

The logic there appears fine to me. It sounds like you're saying that it does chat "Running command: infuse", but does not chat anything further? I can't see how that would be the case. Could you elaborate on the exact behaviour you're seeing?

#14 the_hyren

  • Members
  • 29 posts

Posted 04 December 2015 - 03:20 AM

Thanks for the html tags for stuff, im not familiar with forums and posts, I usually figure it out on my own by now but I've gotten frustrated.
And thanks for the #tbl part. I have been learning lua syntax from the computercraft wiki and google so any help with easier ways is much appreciated.
And by matrix i do mean table, its just what the computercraft wiki calls 2d arrays, and a quick question, can lua tables be ragged, which is a java term for when arrays of arrays have different dimensions; as in table[1].length doesnt have to equal table[2].length

And finally, the exact problem I'm having is this: I tell it 'infuser1: infuse X' it replies 'Running command: infuse' then nothing else happens and the program stops running. No errors have been logged or crashes happened. Don't know what's up.

I'm using an advanced computer, and I was wondering what the difference between it and normal ones is

#15 the_hyren

  • Members
  • 29 posts

Posted 04 December 2015 - 03:33 AM

Ok an update of code using new function and #

bridge = peripheral.wrap("right")
chat = peripheral.wrap("top")
fillerItem = "minecraft:wooden_sword"
mytag = "infuser1:"
recipefile = "recipes.txt"
function grabItem(name)
  num = bridge.retrieve(name, 1, "north")
  if num ~= 1 then
    bridge.craft(name, 1)
    crafting = true
    while crafting do
	  local event, complete, crafted, num, bytes = os.pullEvent("craftingComplete")
	  crafting = complete
    end
    bridge.retrieve(name, 1, "north")
  end
end
function listen(mytag)
  listening = true
  while listening do
    local event, name, text = os.pullEvent("chat")
    start, stop = string.find(text, mytag)
    if start ~= nil and start >= 0 then
	  return string.sub(text, stop + 1)
    end
  end
end
function startInfusion()
  redstone.setOutput("left", true)
  sleep(2)
  redstone.setOutput("left", false)
end
function removeFiller()
  redstone.setOutput("back", true)
  sleep(30)
  redstone.setOutput("back", false)
end
function loadRecipes(filename)
  file = fs.open(file, "r")
  data = file.readAll()
  file.close()
  return textutils.unserialize(data)
end
function saveRecipes(filename, recipes)
  file = fs.open(filename, "w")
  data = textutils.serialize(recipes)
  file.write(data)
  file.close()
end
function infuse(recipes, recipenum)
  length = #recipes[recipenum]
  for i=1,length do
    grabItem(recipes[recipenum][i])
  end
  removeFiller()
  sleep(180)
  startInfustion()
end
recipes = loadRecipes(recipefile)
while true do
  command = listen(mytag)
  prefix = string.sub(command, 1, 6)
  info = string.sub(command, 8)
  chat.say("Running command: " .. prefix, 30)
  if prefix == "reload" then
    recipes = loadRecipes(recipefile)
    chat.say("Recipes reloaded.", 30)
  elseif prefix == "save  " then
    saveRecipes(recipefile, recipes)
    chat.say("Recipes saved.", 30)
  elseif prefix == "addnew" then
   
  elseif prefix == "infuse" then
    recipenum = tonumber(info)
    chat.say("Running infuse recipe: " .. info, 30)
    infuse(recipes, recipenum)
    chat.say("Infusion complete.", 30)
  end
end

Quick other question: does lua have a string function that trims white space from strings, as in removes tabs, newlines, and spaces from the front and back of the string? I would like to see if perhaps I have phantom spaces causing trouble

#16 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 04 December 2015 - 03:50 AM

 the_hyren, on 04 December 2015 - 03:20 AM, said:

quick question, can lua tables be ragged, which is a java term for when arrays of arrays have different dimensions; as in table[1].length doesnt have to equal table[2].length

Yes, they can, and the language doesn't ever make assumptions that they might not be. You can also stick any data type in any table, at any index - table[1] can be a string, table[2] might point to another table (or even the same table, if you wanted!), table[3] might contain a function pointer leading to executable code, table[4] might be nil, table[5] might have a number... they're incredibly dynamic.

Arrays are relatively limited. You can treat a Lua table as an array, and you can also treat a table as a hashmap... or even have it act as both, at the same time.

 the_hyren, on 04 December 2015 - 03:20 AM, said:

And finally, the exact problem I'm having is this: I tell it 'infuser1: infuse X' it replies 'Running command: infuse' then nothing else happens and the program stops running. No errors have been logged or crashes happened. Don't know what's up.

When you say "the script stops running", you mean pauses (until you manually terminate it, via eg Ctrl + T), or you mean you're returned to the CraftOS command prompt?

I'm guessing you mean the latter case, which would mean that an error is occurring but for some reason the resulting message isn't making it to the screen. Throw in some more print statements - in particular, immediately before and after each line which calls chat.say() - in an attempt to narrow down exactly which one is crashing you out.

 the_hyren, on 04 December 2015 - 03:20 AM, said:

I'm using an advanced computer, and I was wondering what the difference between it and normal ones is

The most obvious difference is that normal computers are only able to output shades of grey to their screens, whereas advanced ones have a 16 colour palette.

But in addition, advanced computers boot up using multishell, which allows them to easily run multiple scripts at once.

In terms of turtles, the above is also true but advanced models furthermore have a higher maximum fuel capacity.

In terms of processing power all systems are the same.

 the_hyren, on 04 December 2015 - 03:33 AM, said:

Quick other question: does lua have a string function that trims white space from strings, as in removes tabs, newlines, and spaces from the front and back of the string? I would like to see if perhaps I have phantom spaces causing trouble

Not built in, but you could create one. I don't think that's your problem, however.

#17 Lupus590

  • Members
  • 2,011 posts
  • LocationUK

Posted 04 December 2015 - 11:11 AM

 Bomb Bloke, on 04 December 2015 - 03:50 AM, said:

 the_hyren, on 04 December 2015 - 03:20 AM, said:

I'm using an advanced computer, and I was wondering what the difference between it and normal ones is

The most obvious difference is that normal computers are only able to output shades of grey to their screens, whereas advanced ones have a 16 colour palette.

But in addition, advanced computers boot up using multishell, which allows them to easily run multiple scripts at once.

In terms of turtles, the above is also true but advanced models furthermore have a higher maximum fuel capacity.

In terms of processing power all systems are the same.

advanced computers also allow for mouse input, which normal computers don't.

#18 the_hyren

  • Members
  • 29 posts

Posted 04 December 2015 - 01:50 PM

Quote

I'm guessing you mean the latter case, which would mean that an error is occurring but for some reason the resulting message isn't making it to the screen. Throw in some more print statements - in particular, immediately before and after each line which calls chat.say() - in an attempt to narrow down exactly which one is crashing you out.

Indeed it is the later. It exits to command prompt, which I assumed meant an error but I've checked all my logs, java error and minecraft both. Havent seen anything except for a gui error related to /help 6 command, which has been in my mod pack for all of 1.7. I put a chat before my if/elseif block, it runs, anything in or after does not...really frustrating

#19 the_hyren

  • Members
  • 29 posts

Posted 04 December 2015 - 08:01 PM

Another update: found a trim function online and implemented it

bridge = peripheral.wrap("right")
chat = peripheral.wrap("top")
fillerItem = "minecraft:wooden_sword"
mytag = "infuser1:"
recipefile = "recipes.txt"
function grabItem(name)
  if name == nil or name == "" then
    name = fillerItem
  end
  num = bridge.retrieve(name, 1, "north")
  if num ~= 1 then
    bridge.craft(name, 1)
    crafting = true
    while crafting do
	  local event, complete, crafted, num, bytes = os.pullEvent("craftingComplete")
	  crafting = complete
    end
    bridge.retrieve(name, 1, "north")
  end
end
function listen(mytag)
  listening = true
  while listening do
    local event, name, text = os.pullEvent("chat")
    start, stop = string.find(text, mytag)
    if start ~= nil and start >= 0 then
	  return string.sub(text, stop + 1)
    end
  end
end
function startInfusion()
  redstone.setOutput("left", true)
  sleep(2)
  redstone.setOutput("left", false)
end
function removeFiller()
  redstone.setOutput("back", true)
  sleep(30)
  redstone.setOutput("back", false)
end
function loadRecipes(filename)
  file = fs.open(file, "r")
  data = file.readAll()
  file.close()
  return textutils.unserialize(data)
end
function saveRecipes(filename, recipes)
  file = fs.open(filename, "w")
  data = textutils.serialize(recipes)
  file.write(data)
  file.close()
end
function infuse(recipes, recipenum)
  length = #recipes[recipenum]
  for i=1,length do
    grabItem(recipes[recipenum][i])
  end
  removeFiller()
  sleep(180)
  startInfustion()
end
function trim(s)
  return (s:gsub("^%s*(.-)%s*$", "%1"))
end
--recipes = loadRecipes(recipefile)
recipes = {}
while true do
  command = listen(mytag)
  words = {}
  for word in command:gmatch("%S+") do table.insert(words, trim(word)) end
  prefix = table.remove(words, 1)
  chat.say("Running command: "..prefix, 30)
  if prefix == "reload" then
    recipes = loadRecipes(recipefile)
    chat.say("Recipes reloaded.", 30)
  elseif prefix == "save" then
    saveRecipes(recipefile, recipes)
    chat.say("Recipes saved.", 30)
  elseif prefix == "addnew" then
    recipenum = tonumber(table.remove(words, 1))
    recipes[recipenum] = words
    chat.say("Recipe added.", 30)
  elseif prefix == "infuse" then
    recipenum = tonumber(table.remove(words, 1))
    chat.say("Running infuse recipe:".. info, 30)
    infuse(recipes, recipenum)
    chat.say("Infusion complete.", 30)
  end
end


#20 the_hyren

  • Members
  • 29 posts

Posted 04 December 2015 - 08:21 PM

Found a few things I forgot to update in my code. but before I continue posting it every time how do I use a spoiler tag? That way every post isn't a mile long.

Anyways, it seems the new trim and split functions are helping. I can run reload and save commands and get the chat from them. But the program still crashes somehow so I have to rerun the program between commands. The infuse and addnew commands do not work yet





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users