This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
GregoriMarow's profile picture

Multidimensional Table

Started by GregoriMarow, 27 May 2017 - 01:25 PM
GregoriMarow #1
Posted 27 May 2017 - 03:25 PM
Hi,

I have used a menu tutorial and it worked. Now I want to extend it.

Original table

local menu_options = { --This is our menu table. It contains basic data about the menu
[1] = {text="Menu Option 1", color=colors.blue},
[2] = {text="Menu Option 2", color=colors.orange},
[3] = {text="Menu Option 3", color=colors.cyan},
[4] = {text="Menu Option 4", color=colors.orange},
}

And now i want to extend it.


local menu_options = { --This is our menu table. It contains basic data about the menu
[1] = {text="Menu Option 1", color=colors.blue, command="/summon ...."},
[2] = {text="Menu Option 2", color=colors.orange, command="/say Blubb"},
[3] = {text="Menu Option 3", color=colors.cyan, command="/tp....."},
[4] = {text="Menu Option 4", color=colors.orange, command="/toggledownfall"},
[5] = {text="Menu Option 5", color=colors.orange, command="another command"},
[6] = {text="Menu Option 6", color=colors.orange, command="another command"},
[7] = {text="Menu Option 7", color=colors.orange, command="another command"},
[8] = {text="Menu Option 8", color=colors.orange, command="another command"},
[9] = {text="Menu Option 9", color=colors.orange, command="another command"},
[10] = {text="Menu Option 10", color=colors.orange, command="another command"}
}

At the end of the script I get a selector variable

term.write("Selected: "..selector)

So if I choose Menu Option 4 the selector is 4. I want to use this selector now to read the command value "/toggledownfall" and first print it out for testing. Later I will use this at a command computer to execute a command.

How do I do this?
Lupus590 #2
Posted 27 May 2017 - 09:58 PM
you have two options:
menu_options[4].command
menu_options[4]["command"]
GregoriMarow #3
Posted 28 May 2017 - 07:36 AM
hi

thanks it is working. :D/>/>

term.write(menu_options[4]["command"])

also next step

term.write(menu_options[selector]["command"])

Okay next problem.
I am generating the table via php from a mysql database.
the script trows out the hole table.

PHP Output:

{[1] = {text="Burg", color=colors.blue, playerticket="/summon Item 21 22 23 {Item:{id:4787,Count:1,tag:{dest:Burg,owner:GregoriMarow,display:{Name:Fahrticket}}}}", depotticket="", carthopper=""},[2] = {text="Hotel", color=colors.blue, playerticket="/summon Item 24 25 26 {Item:{id:4787,Count:1,tag:{dest:Hotel,owner:GregoriMarow,display:{Name:Fahrticket}}}}", depotticket="", carthopper=""},[3] = {text="WTC", color=colors.blue, playerticket="/summon Item 27 28 29 {Item:{id:4787,Count:1,tag:{dest:WTC,owner:GregoriMarow,display:{Name:Fahrticket}}}}", depotticket="", carthopper=""},}

If I now read the output via http api I get a string. and if I try these:


local menu_options = respondedText

bad argument: table expected, got string

When I search "lua convert string to table" or "computercraft convert string to table" I only got examples that did not fit to my needs.

Can somebody help?
Lyqyd #4
Posted 28 May 2017 - 10:19 PM
You'll likely want to run the table through textutils.unserialize.
GregoriMarow #5
Posted 29 May 2017 - 07:13 AM
I did this before and its not working. I will make a detailed walk through. Be not suprised, I have changed the php output, thought maybe the {}[] in the summon command made problems.
They did not, it is still not working. But I think it is not important because this is just an testing for the later whole program.
Btw. if I paste the php output directly into the code it is working. So output itself is okay. It seems to be a problem with the string.

The new php output with three subway stations.

{ [1] = {text="Burg", color=colors.blue, tickethopper="21 22 23", destination="Burg"}, [2] = {text="Hotel", color=colors.blue, tickethopper="24 25 26", destination="Hotel"}, [3] = {text="WTC", color=colors.blue, tickethopper="27 28 29", destination="WTC"} }

Here is the Error code:
startup: 45: attempt to get length of nil

The Code itself, line 45 is maked with a comment – ###################

local cc_side_traindepot = "right"
local cc_side_ticket = "left"
local cc_side_traingo = "back"
local cc_station = "Marktplatz"
local cc_track = "A"
local cc_line = "U79"
local itemid = "4787"
local myurl = "http://*********.de/*********.php?do=GetOptionTable&st="..cc_station.."&tr="..cc_track.."&li="..cc_line..""

http.request(myurl)
	 local requesting = true
	 while requesting do
	   local event, url, sourceText = os.pullEvent()
	   if event == "http_success" then
		 respondedText = sourceText.readAll()
		 --print ("Antwort: "..respondedText)
		 requesting = false
	   elseif event == "http_failure" then
		 respondedText = ("Server didn't respond.")
		 print ("Antwort: "..respondedText)
		 requesting = false
	   end
	 end


--file_operation = fs.open("menu_options_file.txt", "w")
--file_operation.write(respondedText)
--file_operation.close()

--file = fs.open("menu_options_file.txt","r")
--menu_options = file.readAll()
--file.close()

print (respondedText) -- To be sure something was read out
sleep (1)

local menu_options = textutils.unserialize( respondedText )

--local menu_options = {[1] = {text="Burg", color=colors.blue, playerticket="/summon Item 21 22 23 {Item:{id:4787,Count:1,tag:{dest:Burg,owner:GregoriMarow,display:{Name:Fahrticket}}}}", depotticket="", carthopper=""},[2] = {text="Hotel", color=colors.blue, playerticket="/summon Item 24 25 26 {Item:{id:4787,Count:1,tag:{dest:Hotel,owner:GregoriMarow,display:{Name:Fahrticket}}}}", depotticket="", carthopper=""},[3] = {text="WTC", color=colors.blue, playerticket="/summon Item 27 28 29 {Item:{id:4787,Count:1,tag:{dest:WTC,owner:GregoriMarow,display:{Name:Fahrticket}}}}", depotticket="", carthopper=""},}



local termX, termY = term.getSize() --The x/y size of the terminal
local function menuDraw(selected) --Our main draw function
  local yPos = termY/2 - #menu_options/2 --The initial y position ########################### 45 ###############################
  for index, data in pairs(menu_options) do
	menu_options[index].bounds = { --Create a new table in each option with the boundary data
	  x1 = termX/2 - (#data.text+4)/2;
	  x2 = termX/2 + (#data.text+4)/2;
	  y = yPos;
	}
	term.setTextColor(data.color)
	term.setCursorPos(data.bounds.x1, data.bounds.y)

	local text =
	  index==selected and "[ "..data.text.." ]" or
	  "  "..data.text.."  " --Essentially an if statement, but in a contracted form
	term.write(text)
	yPos = yPos+1 --Increment the initial y pos so we can move on the next line
  end
end

local function checkClick(x,y) --Check the mouse click to see if there's a menu option
  for index, data in pairs(menu_options) do
	if x>= data.bounds.x1 and x<= data.bounds.x2 and y==data.bounds.y then
	  return index --Returns the index of the clicked option
	end
  end
  return false --If it went through the entire for loop without success, return false
end

term.setBackgroundColor(colors.white)
term.clear()

local selector = 1 --Our selector
while true do --The main loop. I would generally put this inside of a function for a program.
  menuDraw(selector) --Draw the menu first
  local e = {os.pullEvent()} --Pull an event and put the returned values into a table
  if e[1] == "key" then --If it's a key...
	if e[2] == keys.down then -- ... and it's the down arrow
	  selector = selector < #menu_options and selector+1 or 1 --Increment the selector if the selector < #menu_options. Otherwise reset it to 1
	elseif e[2] == keys.up then
	  selector = selector > 1 and selector-1 or #menu_options --Decrement the selector if the selector > 1. Otherwise, reset it to #menu_options
	elseif e[2] == keys.enter then
	  break --Break out of the loop
	end
  elseif e[1] == "mouse_click" then
	local value = checkClick(e[3], e[4]) --Check the mouse click
	if value then --If checkClick returns a value and not false
	  selector = value --Set the selector to that value and break out of the loop
	  break
	end
  end
end

term.clear()
term.setCursorPos(1,1)
term.write("Selected: "..selector)
term.setCursorPos(1,2)
term.write(menu_options[selector]["tickethopper"]) -- Just for testing
--term.write(menu_options[selector]["playerticket"])
--commands.exec(menu_options[selector]["playerticket"])
--os.sleep(2)
--rs.setOutput ("left",true)
--os.sleep(0.5)
--rs.setOutput ("left",false)



Sry for the many outcommented code, but I am in the stage of testing XD.
Alternatively if you have a different idea how to transmit a php output and then transfer it to the above table format I would try this also.
I could reduce the amount of data that should be transmitted by only using station name and mysql table id and then later select all necessary datas after user selection of the target station.
Edited on 29 May 2017 - 06:22 AM
Bomb Bloke #6
Posted 29 May 2017 - 09:23 AM
textutils.unserialise() works by creating a new function, "return "..<yourstring>, and returning whatever that returns. The temporary function gets its own empty environment table - this means it can't be used to execute arbitrary code, eg by calling some other function, and it also means it doesn't have access to tables such as the one which makes up the "colours" API.

Either switch colors.blue to its actual numeric value (2048), or create your own unserialiser.
Edited on 29 May 2017 - 07:24 AM