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

Event not running correctly

Started by Almerish, 21 December 2014 - 07:17 AM
Almerish #1
Posted 21 December 2014 - 08:17 AM
Trying to automate my big reactor with manual button inputs to turn on and off the reactor in order to not waste fuel. When i reach the lower end of the spectrum the reactor will not turn on automatically. I have atm edited the code again to see if a fix i thought of works. it takes about 4-5 hours after the auto turnoff to see if the program will work correctly (this is mainly due to my power consumption rate is low). Below is the current code that i am working with. The reactor will automatically turn off correctly but will not turn back on. Due note that the code has to work with the buttons. And if you can't tell this is running on an advance computer.

Edit* So it seems that once i use a button that it begins to act weird. It no longer runs in 1 second intervals like i set up in the code. Only 100% fix i have found is to reboot the whole computer after pressing the button.


--Created by Almerish
--Single rod no liquid big reactor
while true do
local reactor = peripheral.wrap("BigReactors-Reactor_0")
local energy = reactor.getEnergyStored()
local Active = paintutils.loadImage("button")
local DeActive = paintutils.loadImage("button2")
--printing information and button
print("Connected: ", reactor.getConnected())
print("Stored Energy: ", energy)
print("Reactor Status: ", reactor.getActive())
paintutils.drawImage(Active, 6, 12)
term.setCursorPos(7, 14)
print("Activate")
paintutils.drawImage(DeActive, 38, 12)
term.setCursorPos(38, 14)
print("DeActivate")
local refresh = os.startTimer(1)
local event, button, x, y = os.pullEvent()
--click-able button
if event == "mouse_click" and x >= 6 and x <= 16 and y >= 12 and y <= 17 then
reactor.setActive(true)
elseif event == "mouse_click" and x >= 38 and x <= 48 and y >= 12 and y <= 17 then
reactor.setActive(false)
--auto-update for turning reactor on and off
elseif event == "timer" and button == refresh then
if energy >= 9800000 then
  reactor.setActive(false)
elseif energy <= 200000 then
  reactor.setActive(true)
end
end

--resetting screen
term.setBackgroundColor(colors.black)
term.clear()
term.setCursorPos(1,1)
end
Edited on 21 December 2014 - 07:32 AM
Bomb Bloke #2
Posted 21 December 2014 - 10:52 AM
It's 'cause you're starting a new timer with each and every iteration.

Let's say the buttons aren't being clicked and the timers are simply being allowed to do their thing. On the first iteration, "refresh" gets set to eg 1, and when the timer event comes through, "button" will be set to 1. And so there's a match and the energy-checking code does its thing. On the next iteration "refresh" and "button" will be 2, and so on.

But what if you click? On the first iteration, "refresh" might be 1. Then you click to trigger the second iteration - you start a new timer, and "refresh" is now 2. Then the original timer event gets pulled from the queue - "button" is 1, which doesn't match "refresh", and so another timer is started and… they'll never match up again.

The key is to only start a new timer when you successfully find the last one in the event queue. I'd also re-arrange things a bit so that you're not re-running certain bits of code, or spending so long in the screen redrawing process:

local reactor, refresh = peripheral.wrap("BigReactors-Reactor_0"), os.startTimer(1)

--resetting screen
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)
term.clear()

--draw buttons
term.setCursorPos(7, 14)
print("Activate")
term.setCursorPos(38, 14)
print("DeActivate")
paintutils.drawImage(paintutils.loadImage("button"), 6, 12)
paintutils.drawImage(paintutils.loadImage("button2"), 38, 12)

while true do
	local energy = reactor.getEnergyStored()
	
	--printing information
	term.setCursorPos(1,1)
	term.clearLine()
	print("Connected: ", reactor.getConnected())
	term.clearLine()
	print("Stored Energy: ", energy)
	term.clearLine()
	print("Reactor Status: ", reactor.getActive())
	
	local event, button, x, y = os.pullEvent()

	--click-able button
	if event == "mouse_click" and x >= 6 and x <= 16 and y >= 12 and y <= 17 then
		reactor.setActive(true)
	elseif event == "mouse_click" and x >= 38 and x <= 48 and y >= 12 and y <= 17 then
		reactor.setActive(false)

	--auto-update for turning reactor on and off
	elseif event == "timer" and button == refresh then
		if energy >= 9800000 then
			reactor.setActive(false)
		elseif energy <= 200000 then
			reactor.setActive(true)
		end
		
		refresh = os.startTimer(1)
	end
end
Almerish #3
Posted 21 December 2014 - 10:13 PM
Thanks man working great now. However you have to remember when doing the buttons draw image first then put text. The image will overlay the text if you write the text first. Also have to reset the background color to black due to the way that computercraft image loader works will make the screen with the updating text red and not black. Never used buttons with updating text in the background before so I was stumped and you helped out greatly.


--draw buttons
paintutils.drawImage(paintutils.loadImage("button"), 6, 12)
term.setCursorPos(7, 14)
print("Activate")
paintutils.drawImage(paintutils.loadImage("button2"), 38, 12)
term.setCursorPos(38, 14)
print("DeActivate")
term.setBackgroundColor(colors.black)

It's 'cause you're starting a new timer with each and every iteration.

Let's say the buttons aren't being clicked and the timers are simply being allowed to do their thing. On the first iteration, "refresh" gets set to eg 1, and when the timer event comes through, "button" will be set to 1. And so there's a match and the energy-checking code does its thing. On the next iteration "refresh" and "button" will be 2, and so on.

But what if you click? On the first iteration, "refresh" might be 1. Then you click to trigger the second iteration - you start a new timer, and "refresh" is now 2. Then the original timer event gets pulled from the queue - "button" is 1, which doesn't match "refresh", and so another timer is started and… they'll never match up again.

The key is to only start a new timer when you successfully find the last one in the event queue. I'd also re-arrange things a bit so that you're not re-running certain bits of code, or spending so long in the screen redrawing process:

local reactor, refresh = peripheral.wrap("BigReactors-Reactor_0"), os.startTimer(1)

--resetting screen
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)
term.clear()

--draw buttons
term.setCursorPos(7, 14)
print("Activate")
term.setCursorPos(38, 14)
print("DeActivate")
paintutils.drawImage(paintutils.loadImage("button"), 6, 12)
paintutils.drawImage(paintutils.loadImage("button2"), 38, 12)

while true do
	local energy = reactor.getEnergyStored()
	
	--printing information
	term.setCursorPos(1,1)
	term.clearLine()
	print("Connected: ", reactor.getConnected())
	term.clearLine()
	print("Stored Energy: ", energy)
	term.clearLine()
	print("Reactor Status: ", reactor.getActive())
	
	local event, button, x, y = os.pullEvent()

	--click-able button
	if event == "mouse_click" and x >= 6 and x <= 16 and y >= 12 and y <= 17 then
		reactor.setActive(true)
	elseif event == "mouse_click" and x >= 38 and x <= 48 and y >= 12 and y <= 17 then
		reactor.setActive(false)

	--auto-update for turning reactor on and off
	elseif event == "timer" and button == refresh then
		if energy >= 9800000 then
			reactor.setActive(false)
		elseif energy <= 200000 then
			reactor.setActive(true)
		end
		
		refresh = os.startTimer(1)
	end
end