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

Error in my WIP API

Started by OhTrueful, 22 March 2014 - 06:26 PM
OhTrueful #1
Posted 22 March 2014 - 07:26 PM
SOLVED: (kind of), I rewrote the whole thing in a different way suggested by CometWolf


I am in the process of making an API for items to be displayed on a monitor. These item types would include: buttons, text boxes, pictures, screens (which would fill the entire screen and contain other types of items inside of them), etc. I have, however, only worked on the buttons and the screens, and I am now getting an error when I test it.
The API is here, and the program I am using to test it is here.
When I run "main" (the program I am using to test it), I get the error "204". I have never seen this one before, and couldn't find anything about it on Google. I recently changed something, and before that I was getting an error on items:84, "Attempt to index ? (a nil value)".

I can tell you what it is supposed to do:

initialize(side) wraps the monitor on specified side, and creates some necessary variables/arrays.

mkItem(…) adds an entry into the array items, which contains data for all created items. It takes the arguments in this form:
if making a button then: mkItem(type,name,text,w,h,txtColor,bgColor,fn,args) where:
"type" = "btn" (for "button")
"name" = a string for the button to be called with
"text" = text to be displayed on the button
"w","h" = width and height of button on monitor
"txtColor" = color of text displayed on button (colors API)
"bgColor" = color of button (background) (colors API)
"fn" = function to be called when button is pressed
"args" = an array of arguments to call the function with

if making a screen then: mkItem(type,name,items,bgColor) where:
"type" = "scn" (for "screen")
"name" = a string for the screen to be called with
"items" = an array containing the items to be displayed on this screen. It has the structure:
{{item1_name,item1_x,item1_y},{item1_name,item1_x,item1_y}} where:
"name" = the name declared in mkItem()
"x" = the x coord to display that item at
"y" = the y coord to display that item at
"bgColor" = the color for the background of the screen (colors API)

dispItem(…) actually puts already created items onto the screen. It takes the arguments in this form:

if displaying a button then: dispItem(name,x,y) where:
"name" = the name declared in mkItem()
"x" = the x coord to display the item at
"y" = the y coord to display the item at

if displaying a screen then: dispItem(name) where
"name" - the name of the screen declared in mkItem()
(it doesn't need x,y because it takes up the whole screen)

waitEvent() waits for the monitor to be touched, and, if a button is clicked, it calls that button's function.

Thank you.
Edited on 23 March 2014 - 04:02 AM
CometWolf #2
Posted 22 March 2014 - 08:19 PM
you're using … all wrong.

local args = {...} --stores the arguments in a table called args
args{1] --first argument
args[2] --second argument
-- and so on
Also, you'd probably be better off returning the objects instead of storing them all in the same table.
OhTrueful #3
Posted 22 March 2014 - 08:56 PM
you're using … all wrong.

local args = {...} --stores the arguments in a table called args
args{1] --first argument
args[2] --second argument
-- and so on
Also, you'd probably be better off returning the objects instead of storing them all in the same table.

okay, so then why does this print "hello world"?

function test(...)
  print(arg[1].." "..arg[2])
end

test("hello","world")

Also, returning the objects is a good idea, however, I don't know how I would then keep track of where they are displayed (for pressing the buttons).
Anavrins #4
Posted 22 March 2014 - 11:11 PM
you're using … all wrong.

local args = {...} --stores the arguments in a table called args
args{1] --first argument
args[2] --second argument
-- and so on
Also, you'd probably be better off returning the objects instead of storing them all in the same table.
That's not the problem, you can use arg[] instead when using … in functions.

What do you mean by "error 204"?
Does it just show a red 204 or something?, maybe a screenshot?
OhTrueful #5
Posted 22 March 2014 - 11:29 PM
What do you mean by "error 204"? Does it just show a red 204 or something?, maybe a screenshot?

Yes, it was just simply the number "204" (in red), however, now it's back to a different error which I also could not solve:


items:85 attempt to index ? (a nil value)

I didn't change anything since last time, so I don't know what the "204" error was, or why it is gone. This other error is the one I am more puzzled by, though.
CometWolf #6
Posted 22 March 2014 - 11:44 PM
Well i'll be damned, learn something everyday…
I don't see you defining item.items anywhere, so yeah line 84

    for i = 1, #item["items"] do
will probably error.

As for returning the objects themselves, store the coordinates within them. Personally i use the keyes sX,sY and eX,eY. You could generate a seperate touchMap for the entire screen to know what happens when the user clicks where.

local touchMap = {}
for x=obj.sX,obj.eX do
  touchMap[x] = touchMap[x] or {}
  for y=obj.sY,obj.eY do
    touchMap[x][y] = obj.function
  end
end
local tEvent = {os.pullEvent()}
  if tEvent[1] == "mouse_click" then
    local x,y = tEvent[3],tEvent[4]
    if touchMap[x][y] then --check the touchmap for function
	  touchMap[x][y]() --function found, executing
    end
  end
end
theoriginalbit #7
Posted 22 March 2014 - 11:49 PM
the only problem with using arg in functions as opposed to making your own args table is that you need to be careful as there's an extra key n in the table

function foo(...)
  for k,v in pairs(arg) do
    print(k, ' : ', v)
  end
end
foo("hello", "world")
the above outputs
1 : hello
2 : world
n : 2
OhTrueful #8
Posted 23 March 2014 - 01:43 AM
I don't see you defining item.items anywhere, so yeah line 84

	for i = 1, #item["items"] do
will probably error.
I do define it, I think.
Line 35 sets

items[id]["items"] = arg[3]
and then line 65 sets

item = items[i]
Id is a number representing the item (so that I can do for loops with the items array easily), and i is the variable of a for loop which searches for an item with the "name" value the same as the argument in dispItem().

As for returning the objects themselves, store the coordinates within them. Personally i use the keyes sX,sY and eX,eY. You could generate a seperate touchMap for the entire screen to know what happens when the user clicks where.

local touchMap = {}
for x=obj.sX,obj.eX do
  touchMap[x] = touchMap[x] or {}
  for y=obj.sY,obj.eY do
	touchMap[x][y] = obj.function
  end
end
local tEvent = {os.pullEvent()}
  if tEvent[1] == "mouse_click" then
	local x,y = tEvent[3],tEvent[4]
	if touchMap[x][y] then --check the touchmap for function
	  touchMap[x][y]() --function found, executing
	end
  end
end
This would work very well for returning the objects. Thanks! I may change it to work (like this) without the huge "items" array.

the only problem with using arg in functions as opposed to making your own args table is that you need to be careful as there's an extra key n in the table
Thanks, I believe I am only using numbers to reference the arg arrays currently. Also, why is that, when you can just do #arg?
Edited on 23 March 2014 - 01:02 AM