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

Event That Dont Stop Loops

Started by tvc, 05 August 2013 - 04:16 PM
tvc #1
Posted 05 August 2013 - 06:16 PM
I have a program that i have running that i need to be able to stop by chat command(open peripheral mod)

here is my problem

lets say the program is

x = 1
while true do
x = x + 1
end

but i want to be able to tell it when to stop. I know i cant use

local event, command = os.pullEvent("chat_command")

because it will stop the programs regardless of a command while it waits for one. my current fix which sucks is using the rs.getInput command, and having the input toggle by chat. Any ideals?
Kingdaro #2
Posted 05 August 2013 - 06:25 PM
Actually, the only way to do something like this would be to use os.pullEvent, but without parameters. You'd need to just set up an event loop that constantly pulls events and queues them again, while also listening for a chat command.


os.queueEvent('update')
while true do
  local ev, p1 = os.pullEvent()
  if ev == 'update' then

    --# do whatever you need to do before updating again

    os.queueEvent('update')
  elseif ev == 'chat_command' then
    if p1 == 'stop' then
      break
    end
  end
end

This script starts off by queuing an event called "update", then it starts an event pulling loop. When the loop receives "update", it'll queue the update event again, and pull it again, queue it again, and the cycle repeats.

In this middle of all of this event pulling, however, you can also receive other events, including key, char, mouse_click, and more specifically, chat_command. When we've pulled the chat_command event instead of the update event, and if the command is "stop", we will break out of the loop.
tvc #3
Posted 05 August 2013 - 06:44 PM
Spoileros.loadAPI("ocs/apis/sensor")
power = sensor.wrap("right")
b = peripheral.wrap("left")
b.clear()
os.queueEvent("update")
while true do
local ev, p1 = os.pullEvent()
if ev == "update" then
local total,totalCap = 0,0
for target in pairs(power.getTargets()) do
local details = power.getTargetDetails(target)
if details.Capacity == 10000000 then
total = total + details.Stored
totalCap = TotalCap + details.Capacity
end
end
b.clear()
b.addText(5,5,"MFSU",0xFFFFFF)
b.addText(35,5,tostring(math.floor(total/totalCap * 100)),0xFFFFFF)
b.addText(55,5"%",0xFFFFFF)
os.queueEvent("update")
elseif ev =="chat_command" then
if p1 == "stop" then
b.clear()
end
end
end
Now its not stopping Ill post my code maybe im just being stupid and missing something
Kingdaro #4
Posted 05 August 2013 - 06:55 PM
You didn't include the "break" keyword, which stops the loop.

if p1 == "stop" then
  b.clear()
  break
end
tvc #5
Posted 05 August 2013 - 07:05 PM
You didn't include the "break" keyword, which stops the loop.

if p1 == "stop" then
  b.clear()
  break
end

ops i ment to type that but it is in my code
MysticT #6
Posted 05 August 2013 - 07:19 PM
Well, the problem is that the sensor calls pulls events, so it "eats" the "chat_command" event you want. A solution would be to use the peripheral functions directly without the sensor api. I don't remember the functions and events right now, but take a look at the sensor api file to see how it works.
Lyqyd #7
Posted 05 August 2013 - 08:40 PM
Actually, since you're both getting targets and getting target details each time you update, it's probably easier to simply use a parallel call in this instance. Handling the ocs_response events in the same while loop is probably more complex than it's worth for this program.


os.loadAPI("ocs/apis/sensor")
local power = sensor.wrap("right")
local b = peripheral.wrap("left")
b.clear()
os.queueEvent("update")

function update()
    while true do
        os.pullEvent("update")
        local total,totalCap = 0,0
        for target in pairs(power.getTargets()) do
            local details = power.getTargetDetails(target)
            if details.Capacity == 10000000 then
                total = total + details.Stored
                totalCap = TotalCap + details.Capacity
            end
        end
        b.clear()
        b.addText(5,5,"MFSU",0xFFFFFF)
        b.addText(35,5,tostring(math.floor(total/totalCap * 100)),0xFFFFFF)
        b.addText(55,5"%",0xFFFFFF)
        os.queueEvent("update")
    end
end

function interrupt()
    while true do
        event, text = os.pullEvent("chat_command")
        if text == "stop" then
            break
        end
    end
end

parallel.waitForAny(update, interrupt)

You can see that the code is rearranged into individual functions. Both of them are run in turn, both of them getting the events they are asking for. The parallel.waitForAny call means that as soon as one of the functions (which are turned into coroutines so that they can be resumed repeatedly to take turns running) exits, it will automatically stop the other.