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

I am completely lost! Need help fixing this neat program

Started by L0NE, 01 April 2017 - 09:16 AM
L0NE #1
Posted 01 April 2017 - 11:16 AM
Okay so to get started I would like to say I am very new to this forum, i just started my own server and i have been playing with my friends. I am not new to programming and thats why i am so frustrated i can't fix this, it just doesn't get in my head…and i still have to learn better syntax of Lua.

So what is program about:

The program is almost like a universal wireless control for a "base". You have 2 pieces of code, one for clients and one for lets say server, or a mainframe.
The client one is a standalone computer that is connected to redstone….could be multiple of standalone ones because the server ties them together.
The server is a computer that makes a montior screen, user makes his own buttons and the program is supposed to turn on/off on monitorclick the specific computer redstone signal

What is the problem:

1. ) I am sure there will be more problems since this is the one that showed at almost startup, but i couldn't get through it so i don't know what waits for me next.
On startup it runs, I press the "+" on cursor pos 1,1 so i can add a button, i add one, and i press on the left corner of the button which is supposed to call a function to changebox i think, so i can assign a standalone computer to that button. Then I get a attemt to call nil on :104


		repeat
  :104			  term.restore()
				local w, h = term.getSize()
		until w == 51 and h == 19

I am not familiar with Lua, but i have read that restore is a Lua function? So that can't be call nil in my opinion

2. )

even if i don't click on the left of the button to edit it…but i just create a button and reboot the program…it gives me on line :90 table expected, got nil….i have looked and looked, nothing crossed my mind


:90 for id,b in pairs(box) do
				drawBox(b,id)
		end

If there is any way you could help me i would appreciate it :D/>
The full codes and pastebin:

Server:
https://pastebin.com/faNYCykU
Client:
https://pastebin.com/m8MmwvX7


Here is the full code for server:

Spoiler

-- by UNOBTANIUM 4.4.2014
local default = {text="???", color=14, colorActive=6, colorText=15, w = 4, h = 3}
local addMode = false
local selected = 0
local square = 4
local w,h = term.getSize()
local colorName = {colors.white, colors.orange, colors.magenta, colors.lightBlue, colors.yellow, colors.lime, colors.pink, colors.lightGray, colors.cyan, colors.purple, colors.blue, colors.brown, colors.green, colors.red, colors.black}
local box = {}

function save()
local file = fs.open("redstone","w")
  file.writeLine(textutils.serialize(default))
  file.writeLine(textutils.serialize(colorName))
  file.writeLine(textutils.serialize(box))
file.close()
end

function load()
if fs.exists("redstone") then
  local file = fs.open("redstone", "r")
   default = textutils.unserialize(file.readLine())
   colorName = textutils.unserialize(file.readLine())
   box = textutils.unserialize(file.readLine())
  file.close()
end
end

function drawBox(b,id)
id = id or -1
for i=b.x, b.x+b.w do
  for j=b.y, (b.y+b.h-1) do
   term.setCursorPos(i, j)
   if addMode and selected == id then
	if i==b.x and j==b.y then
	 term.setBackgroundColor(colorName[b.color])
	else
	 if b.color+1 > 14 then
	  term.setBackgroundColor(colorName[1])
	 else
	  term.setBackgroundColor(colorName[b.color+1])
	 end
	end
   elseif b.active then
	term.setBackgroundColor(colorName[b.colorActive])
   else
	term.setBackgroundColor(colorName[b.color])
   end
   term.write(" ")
  end
end
term.setCursorPos(math.ceil(b.x+b.w/2-#b.text/2), b.y+math.floor(b.h/2))
term.setTextColor(colorName[b.colorText])
term.write(b.text)
end


function draw()
term.setCursorPos(1,1)
term.setBackgroundColor(colors.black)
term.clear()
if addMode then
  term.setTextColor(colors.black)
  term.setBackgroundColor(colors.red)
  term.setCursorPos(1, 1)
  term.write( string.rep(' ', w) )
  term.setCursorPos(1, h)
  term.write( string.rep(' ', w) )
  for i=2,h-1 do
   term.setCursorPos(1, i)
   term.write(" ")
   term.setCursorPos(w, i)
   term.write(" ")
  end
  term.setCursorPos(w-14, h)
  term.write("by UNOBTANIUM")
else
  term.setTextColor(colors.red)
end
term.setCursorPos(1, 1)
term.write("+")
for id,b in pairs(box) do
  drawBox(b,id)
end
end

function changeBox()
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(7,13)
term.write("Look at the computer screen!")
repeat
	term.restore()
	local w, h = term.getSize()
  until w == 51 and h == 19
  local b = box[selected]
  while true do
   term.setBackgroundColor(colors.black)
   term.clear()
   for i=19, 19+square do
   for j=2, (2+math.ceil(square/2)) do
	term.setCursorPos(i, j)
	term.setBackgroundColor(colorName[b.color])
	term.write(" ")
   end
  end
  term.setTextColor(colorName[b.colorText])
  write(b.text, math.ceil(19+square/2-#b.text/2), 2+math.ceil(square/2)-1)
  for i=27, 27+square do
   for j=2, (2+math.ceil(square/2)) do
	term.setCursorPos(i, j)
	term.setBackgroundColor(colorName[b.colorActive])
	term.write(" ")
   end
  end
  term.setTextColor(colorName[b.colorText])
  write(b.text, math.ceil(27+square/2-#b.text/2), 2+math.ceil(square/2)-1)
   term.setTextColor(colors.white)
   term.setBackgroundColor(colors.black)
  write("DELETE",6, 3)
  write("BACK",40,3)
   write("+",20,15)
   write("+",30,15)
   write("-",20,17)
   write("-",30,17)
   write(b.w+1, 20, 16)
   write(b.h, 30, 16)
   write("Text (click to edit): " ..  b.text, 1, 7)
   write("Text Color:", 1,9)
   for i=1,15 do
	term.setCursorPos(15+i*2, 9)
	term.setBackgroundColor(colorName[i])
	term.write("  ")
   end
   term.setBackgroundColor(colors.black)
  term.setCursorPos(1,11)
   term.write("Backgroundcolor:")
   for i=1,15 do
	term.setCursorPos(15+i*2, 11)
	term.setBackgroundColor(colorName[i])
	term.write("  ")
   end
   term.setBackgroundColor(colors.black)
  term.setCursorPos(1,13)
   term.write("Active Color:")
   for i=1,15 do
	term.setCursorPos(15+i*2, 13)
	term.setBackgroundColor(colorName[i])
	term.write("  ")
   end
   term.setBackgroundColor(colors.black)
  term.setTextColor(colors.white)

  local event = {os.pullEvent()}
  if event[1] == "mouse_click" then
   local x,y = event[3], event[4]
   if y == 3 and x <= 17 then
	table.remove(box, selected)
	selected = 0
	break
   elseif y == 3 and x >= 40 then
	break
   elseif y == 7 then
	b.text = betterRead(23,7)
   elseif y == 9 and x >= 17 and x < 47 then
	b.colorText = math.ceil((x-16)/2)
   elseif y == 11 and x >= 17 and x < 47 then
	b.color = math.ceil((x-16)/2)
   elseif y == 13 and x >= 17 and x < 47 then
	b.colorActive = math.ceil((x-16)/2)
   elseif y == 15 then
	if x < 25 then
	 b.w = b.w + 1
	elseif x > 25 then
	 b.h = b.h + 1
	end
   elseif y == 17 then
	if x < 25 and b.w > 1 then
	 b.w = b.w - 1
	elseif x > 25 and b.h > 2 then
	 b.h = b.h - 1
	end
   end
  end
end
term.clear()
term.setCursorPos(1, 1)
term.write("Look at the monitor!")
local monitor = peripheral.wrap("right")
term.redirect(monitor)
w,h = term.getSize()
end
function write(text,x,y)
term.setCursorPos(x, y)
term.write(tostring(text))
end
function betterRead(x,y) -- DONE 1
  term.setTextColor(colors.lightGray)
  term.setCursorBlink(true)
   local s = tostring(box[selected].text)

   while true do
	 term.setCursorPos(x,y)
	 term.write( string.rep(' ', w - x + 1) )
	 term.setCursorPos(x,y)
	 if s:len()+x < w then
		term.write(s)
	 else
	   term.write(s:sub( s:len() - (w-x-2)))
	 end
	 local e = { os.pullEvent() }
  if e[1] == "mouse_click" then
   break
  elseif e[1] == "char" then
   s = s .. e[2]
  elseif e[1] == "key" then
   if e[2] == keys.enter then
	  break
   elseif e[2] == keys.backspace then
	  s = s:sub( 1, s:len() - 1 )
   end
  end
   end

   term.setTextColor(colors.white)
   term.setCursorBlink(false)
   return s
end
function countArray(a)
local elements = 0
for k,v in pairs(a) do
  elements = elements + 1
end
return elements
end
function main()
while true do
  save()
  draw()
  local event = {os.pullEvent()}
  if event[1] == "monitor_touch" then
   local Px,Py = event[3], event[4]
   if Px == 1 and Py == 1 then -- toggle between mode
	addMode = not addMode
	selected = 0
   elseif addMode then -- edit
	local createNew = true
	for id,b in pairs(box) do
	 if (Px >= b.x and Px <= b.x+b.w) and (Py >= b.y and Py <= b.y+math.ceil(b.h/2)) then
	  if selected == id and b.x==Px and b.y ==Py then
	   changeBox()
	   createNew = false
	   break
	  elseif selected == id then
	   createNew = false
	   selected = 0
	   break
	  else
	   selected = id
	   createNew = false
	   break
	  end
	 elseif selected == id then
	  box[selected].x = Px
	  box[selected].y = Py
	  createNew = false
	  break
	 end
	end
	if createNew and selected == 0 then
	 table.insert(box, countArray(box)+1, {x=Px,y=Py,w=default.w,h=default.h,text=default.text,color=default.color,colorActive=default.colorActive,colorText=default.colorText,active=false})
	end
   else -- activate
	for id,b in pairs(box) do
	 if (Px >= b.x and Px <= b.x+b.w) and (Py >= b.y and Py <= b.y+math.ceil(b.h/2)) then
	  b.active = not b.active
	  rednet.broadcast("" .. b.text .. tostring(b.active))
	 end
	end
   end
  end
  sleep(0)
end
end
function openRednet()
for _, side in pairs(redstone.getSides()) do
	  if peripheral.getType(side) == "modem" then
		rednet.open(side)
	  end
	end
end
openRednet()
term.clear()
term.setCursorPos(1, 1)
term.write("Look at the monitor!")
local monitor = peripheral.wrap("right")
term.redirect(monitor)
w,h = term.getSize()
if not (w == 39 or h == 26) then
repeat
	term.restore()
	local w, h = term.getSize()
  until w == 51 and h == 19
  term.clear()
  term.setCursorPos(1, 1)
print("You are not using a 4x4 monitor!")
else
load()
main()
end


Full code client:

Spoiler

-- by UNOBTANIUM 4.4.2014
local id = "TEXT"
local state = false
local w,h = term.getSize()
function save()
local file = fs.open("redstone","w")
  file.writeLine(id)
  file.writeLine(tostring(state))
file.close()
end
function load()
if fs.exists("redstone") then
  local file = fs.open("redstone","r")
   id = file.readLine()
   if file.readLine() == "true" then
	state = true
   end
  file.close()
end
end
function openRednet()
for _, side in pairs(redstone.getSides()) do
	  if peripheral.getType(side) == "modem" then
		rednet.open(side)
	  end
	end
end
function setRedstone()
for _, side in pairs(redstone.getSides()) do
  redstone.setOutput(side, state)
end
end

function set()
sleep(0)
term.setCursorPos(1, 5)
term.clearLine()
write("Text: ", 14, 5)
id = betterRead(20,5)
end
function betterRead(x,y) -- DONE 1
  term.setCursorBlink(true)
   local s = id

   while true do
	 term.setCursorPos(x,y)
	 term.write( string.rep(' ', w - x + 1) )
	 term.setCursorPos(x,y)
	 if s:len()+x < w then
		term.write(s)
	 else
	   term.write(s:sub( s:len() - (w-x-2)))
	 end
	 local e = { os.pullEvent() }
  if e[1] == "char" then
   s = s .. e[2]
  elseif e[1] == "key" then
   if e[2] == keys.enter then
	  break
   elseif e[2] == keys.backspace then
	  s = s:sub( 1, s:len() - 1 )
   end
  end
   end
   term.setCursorBlink(false)
   return s
end
function draw()
term.clear()
write("Text: " .. id, 14,5)
write("Current State: " .. tostring(state), 5,6)
write("Hit a button to change the text!",8,8)
end
function write(text, x, y)
term.setCursorPos(x,y)
term.write(tostring(text))
end

function main()
while true do
  draw()
  openRednet()
  local event = {os.pullEvent()}
  if event[1] == "rednet_message" then
   if event[3] == ("" .. id .. tostring(not state)) then
	state = not state
	setRedstone()
   end
  elseif event[1] == "key" then
   set()
  end
  save()
end
end

load()
setRedstone()
main()
Edited on 01 April 2017 - 12:26 PM
Bomb Bloke #2
Posted 01 April 2017 - 02:35 PM
I am not familiar with Lua, but i have read that restore is a Lua function? So that can't be call nil in my opinion

term.restore() is a ComputerCraft-specific function that only exists in versions of the mod prior to 1.6. When using later releases, you're expected to keep track of previous terminals yourself. term.redirect() actually returns the previous terminal every time you tell it to switch to a new one, which helps somewhat with this.

it gives me on line :90 table expected, got nil….

If "box" is nil, then that implies line 26 within your load() function is setting it as such:

box = textutils.unserialize(file.readLine())

Bearing in mind that textutils.serialize() typically produces multiple lines of output (again, this is version dependant), you can probably see why.

If you want to write multiple tables to a file, then it's easiest to place them all within a single "master" table, then serialise that all in one go. You can then read it back later with a "readAll", and it'll work regardless of version.
L0NE #3
Posted 01 April 2017 - 04:37 PM
Well that makes things more clear….i will try to fix it now by knowing this and get back on this post if i need some further help. Thank you for your time :D/>