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

[Programming Error Or Bug] My Program Crashes When Clicking On The Redstone Button Too Much

Started by oxygencraft, 25 November 2015 - 07:38 AM
oxygencraft #1
Posted 25 November 2015 - 08:38 AM
What i am trying to do is make a computer to send a request to the door server to open the door. Pressing the button once wont open the door and does not send the request. But when i press the button until the computer sends the request and the server door opens the door, my program crashes says peripheral:74: Too long without yielding. I don't know if this is a Computercraft bug or programming error my code is down below:


redstoneinput = redstone.getInput("left")
rednet.open("bottom")
while true do
   if redstoneinput == true then
	  rednet.send(16, "OPEN")
	  end
end
Bomb Bloke #2
Posted 25 November 2015 - 09:21 AM
When a computer/turtle starts running code, ComputerCraft starts a ten second timer. If that code doesn't yield before that timer ends then ComputerCraft will either crash the script or the whole computer (depending on the nature of the functions your script is calling). After each yield, any other systems waiting to run code may do so, then after they've all yielded, processing continues with a new time limit.

The reason why is that running your code chews up valuable server processing power, and so it shouldn't be able to monopolise it. In fact, only ONE CC device can run code at a time: While one is doing something, none of the others can do anything until it yields.

Whether or not it takes more than ten seconds for your code to execute has a little to do with the power of the Minecraft server it's running on, and a lot to do with how often you allow your code to yield. Pulling events (eg getting typed characters or checking timers) triggers a yield, and many commands (eg turtle movements, sleeping, or getting text input from the user) have to pull events to work anyway. Basically, anything that triggers a pause is pulling an event in order to do it, and in order to pull an event the code yields.

In your code, you're not yielding at all. You're checking your redstone input once, and then either spamming messages or not, depending on what single result you got.

It looks like you were going for something like this:

rednet.open("bottom")

while true do
	if redstone.getInput("left") then
		rednet.send(16, "OPEN")
	else
		rednet.send(16, "CLOSE")  -- I guess?
	end

	os.pullEvent("redstone")  -- Yield until a redstone state change occurs.
end
oxygencraft #3
Posted 26 November 2015 - 05:07 AM
When a computer/turtle starts running code, ComputerCraft starts a ten second timer. If that code doesn't yield before that timer ends then ComputerCraft will either crash the script or the whole computer (depending on the nature of the functions your script is calling). After each yield, any other systems waiting to run code may do so, then after they've all yielded, processing continues with a new time limit.

The reason why is that running your code chews up valuable server processing power, and so it shouldn't be able to monopolise it. In fact, only ONE CC device can run code at a time: While one is doing something, none of the others can do anything until it yields.

Whether or not it takes more than ten seconds for your code to execute has a little to do with the power of the Minecraft server it's running on, and a lot to do with how often you allow your code to yield. Pulling events (eg getting typed characters or checking timers) triggers a yield, and many commands (eg turtle movements, sleeping, or getting text input from the user) have to pull events to work anyway. Basically, anything that triggers a pause is pulling an event in order to do it, and in order to pull an event the code yields.

In your code, you're not yielding at all. You're checking your redstone input once, and then either spamming messages or not, depending on what single result you got.

It looks like you were going for something like this:

rednet.open("bottom")

while true do
	if redstone.getInput("left") then
		rednet.send(16, "OPEN")
	else
		rednet.send(16, "CLOSE")  -- I guess?
	end

	os.pullEvent("redstone")  -- Yield until a redstone state change occurs.
end

Ok i tested this and pressing the button lots of times wont do anything. And sending an open request will auto close after 8 seconds. But i guess you want all the computers code.

Door exit button code:


redstoneinput = redstone.getInput("left")
rednet.open("bottom")
while true do
   if redstoneinput == true then
		  rednet.send(16, "OPEN")
		  end
		 
		  os.pullEvent("redstone")
end

Door's main lock:


-- Simple Door Lock
-- Created by DannySMc
-- Version 1.2
-- Platform: Lua Virtual Machine
-- Security Method
oldEvent = os.pullEvent
os.pullEvent = os.pullEventRaw
-- Check for API
os.loadAPI("uapi")
rednet.open("bottom")
-- Installer for Configuration File
if fs.exists(".uLockConf") == false then
  uapi.cs()
  print("Running Installer...")
  sleep(0.5)
  term.setCursorPos(1,3)
  term.write("Redstone output side: ")
  strSide = read()
  term.setCursorPos(1,5)
  term.write("Redstone pulse time: ")
  strPulse = tonumber(read())
  term.setCursorPos(1,7)
  term.write("Terminal Label: ")
  strName = read()
  term.setCursorPos(1,9)
  term.write("Password for unlock: ")
  strPassword = read("*")
  term.setCursorPos(1,11)
  print("What is the name this program is saved as?")
  term.setCursorPos(1,12)
  term.write("Program Name: ")
  strProgName = read()
 
  strPassword = uapi.checksum(strPassword, 1000)
 
  -- Create Configuration File
  uapi.saveConfig({['progName']=strProgName, ['terminalName']=strName, ['redSide']=strSide, ['redPulse']=strPulse, ['lockPassword']=strPassword}, ".uLockConf")
 
  -- Startup File
  term.setCursorPos(1,14)
  print("Do you wish to create a startup file?")
  term.setCursorPos(1,15)
  repeat
  term.write("YES/NO: ")
  startupAnswer = read()
  until ((startupAnswer == "YES") or (startupAnswer == "NO"))
 
  if startupAnswer == "YES" then
    startFile = fs.open("startup", "w")
    startFile.writeLine('os.loadAPI("uapi")')
    startFile.writeLine('config = uapi.loadConfig(".uLockConf")')
    startFile.writeLine("shell.run(config.progName)")
    startFile.close()
    print("Install Complete!")
    sleep(0.5)
  else
    print("Install Complete!")
    sleep(0.5)
  end
 
  print("Rebooting the terminal...")
  sleep(1)
  os.reboot()
end
-- Load Configuration File
config = uapi.loadConfig(".uLockConf")
-- Password Lock Program
uapi.cs()
uapi.drawBox(1, 51, 1, 5, " ", "white", "cyan")
uapi.drawBox(2, 51, 2, 3, " ", "white", "cyan")
uapi.drawBox(3, 51, 3, 1, " ", "white", "cyan")
uapi.printC(config.terminalName, 3, false, "white", "cyan")
uapi.drawBox(1, 51, 19, 1, " ", "white", "cyan")
uapi.printC("Password Lock (Ver 1.2) -> Created By DannySMc", 19, false, "white", "cyan")
uapi.resetCol()
term.setCursorPos(1, 10)
term.write(">	 Password: ")
password = read("*")
password = uapi.checksum(password, 1000)
if password == config.lockPassword then
  term.setCursorPos(1,11)
  print(">	 Password Correct!")
  rednet.send(16, "OPEN")
  sleep(0.5)
  os.reboot()
else
  term.setCursorPos(1,11)
  print(">	 Password Incorrect!")
  sleep(1.5)
  os.reboot()
end

Door server code:


rednet.open("front")
local function open()
  rs.setOutput("top", true)
  sleep(0.75)
  rs.setOutput("right", true)
  sleep(0.75)
  rs.setOutput("bottom", true)
  sleep(0.75)
  rs.setOutput("left", true)
  sleep(0.75)
  rs.setOutput("left", false)
end
local function close()
  rs.setOutput("bottom", false)
  sleep(0.75)
  rs.setOutput("right", false)
  sleep(0.75)
  rs.setOutput("top", false)
end
while true do
  local args = { os.pullEvent("rednet_message") }
  if args[3] == "OPEN" then
  print(args[2]..": "..args[3])
    open()
    sleep(8)
    close()
  end
end

And that's all the code.
Bomb Bloke #4
Posted 26 November 2015 - 05:36 AM
As mentioned, you're checking the state of your redstone input once. If you want to do so every time your loop repeats, then put the redstone.getInput() call into that loop.