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

Inactivity period

Started by Mr_Programmer, 15 October 2014 - 10:58 PM
Mr_Programmer #1
Posted 16 October 2014 - 12:58 AM
hello, i was wondering is there away to detect weather the cursor is moving say like it aint moved for 2 mins then after the 2 mins it will start scanning for rednet messages and if the cursor was moving then the program would work just fine?

i would like to know as im working on a program where i want multiply clients but when 1 client logs in from the same Username and password, the server will reconise this and log out the user on the computer that he isnt using but keep him logged in the one hes just logged in.

my way of thinking this is that if the cursor or computer has been active for 2 mins then it will start scanning for rednet messages then once it has recived one then it will run this command such as logging of? Also auto updates from the server so if 1 client is using it and turns somthing on then the other client say my friends, if his computer was inactive it would auto update the stats of things?

is this possible? Thanks
Edited on 15 October 2014 - 10:59 PM
valithor #2
Posted 16 October 2014 - 01:08 AM
There is no mouse hover, or mouse movement events so it is not possible to check whether or not the cursor is moving, or if it is moving. You could listen for events, though such as click events or keypress events instead of movement events.
ShadowDisruptor #3
Posted 16 October 2014 - 03:41 AM

rednet.open("top")--change to side

function logoff()
  --Put your logoff function in here
end

function onEvent()
  os.pullEvent = os.pullEvent()
  --You could have if statements here to determine which events will trigger the return
  return
end

function waitRednet()
  rednet.recieve()
  return
end

function onAFK()
  x = parrallel.waitForAny(waitRednet, onEvent)
  if x = 1 then
	logoff()
  end
end

function timer()
  sleep(120)--2 minutes in seconds
  return
end

function checkAFK()
   x = parrallel.waitForAny(timer, onEvent)
   if x = 1 then
	 onAFK()
   end
end


Never used parallels before, but it looks like thats how to use them. Please correct me if I used them wrong. Basically, how this works is if you suspect the user is AFK, run checkAFK(). If no event occurs for 2 minutes (mouse click, button press, ect) then it will run onAFK(). What this does it wait for events and wait for a rednet message. If the user moves the mouse before a rednet message, it'll go back to the code. If a rednet is received and no event, then the logoff() function is run. (If you want to pick which events fire the return, use ifs and elseifs and a loop) Reply if you have any questions! And remember, not sure the parallels are set up right.
Edited on 16 October 2014 - 01:42 AM
Mr_Programmer #4
Posted 19 October 2014 - 12:11 AM

rednet.open("top")--change to side

function logoff()
  --Put your logoff function in here
end

function onEvent()
  os.pullEvent = os.pullEvent()
  --You could have if statements here to determine which events will trigger the return
  return
end

function waitRednet()
  rednet.recieve()
  return
end

function onAFK()
  x = parrallel.waitForAny(waitRednet, onEvent)
  if x = 1 then
	logoff()
  end
end

function timer()
  sleep(120)--2 minutes in seconds
  return
end

function checkAFK()
   x = parrallel.waitForAny(timer, onEvent)
   if x = 1 then
	 onAFK()
   end
end


Never used parallels before, but it looks like thats how to use them. Please correct me if I used them wrong. Basically, how this works is if you suspect the user is AFK, run checkAFK(). If no event occurs for 2 minutes (mouse click, button press, ect) then it will run onAFK(). What this does it wait for events and wait for a rednet message. If the user moves the mouse before a rednet message, it'll go back to the code. If a rednet is received and no event, then the logoff() function is run. (If you want to pick which events fire the return, use ifs and elseifs and a loop) Reply if you have any questions! And remember, not sure the parallels are set up right.
Could you please explain this code more indepth?
valithor #5
Posted 19 October 2014 - 01:25 AM

rednet.open("top")--change to side

function logoff()
  --Put your logoff function in here
end

function onEvent()
  os.pullEvent = os.pullEvent()
  --You could have if statements here to determine which events will trigger the return
  return
end

function waitRednet()
  rednet.recieve()
  return
end

function onAFK()
  x = parrallel.waitForAny(waitRednet, onEvent)
  if x = 1 then
	logoff()
  end
end

function timer()
  sleep(120)--2 minutes in seconds
  return
end

function checkAFK()
   x = parrallel.waitForAny(timer, onEvent)
   if x = 1 then
	 onAFK()
   end
end


Never used parallels before, but it looks like thats how to use them. Please correct me if I used them wrong. Basically, how this works is if you suspect the user is AFK, run checkAFK(). If no event occurs for 2 minutes (mouse click, button press, ect) then it will run onAFK(). What this does it wait for events and wait for a rednet message. If the user moves the mouse before a rednet message, it'll go back to the code. If a rednet is received and no event, then the logoff() function is run. (If you want to pick which events fire the return, use ifs and elseifs and a loop) Reply if you have any questions! And remember, not sure the parallels are set up right.
Could you please explain this code more indepth?

I will explain them in the order that they are called.

So when you want to start checking to see whether or not the user is doing anything on the computer you will run checkAfk(). This function begins by assigning the value parallel.waitForAny(timer, onEvent) to x. It then runs what x equals and if the first function is the first one to end then it returns 1 if the second one is the first to return it will return 2. The timer function basically tells the computer to wait for 120 seconds then it tells it to end the function. This would cause x to equal 1 because timer is the first function to end, however, if the user presses a key or does anything which causes a event the onEvent function will fire which will mean that the person is not afk. If the timer function fires then the onAfk() function is run. This function begins by assigning the value parallel.waitForAny(waitRednet, onEvent) to x. In the if statement it is also looking for the first function to fire, which is the waitRednet function. The waitRednet function is there so that you can send a rednet message to tell the computer to log off, but it also still has the onEvent function so that if the user does come back and do something it will no longer act like he is afk.

It basically goes
checkAfk()
it runs timer and onEvent
if timer returns first then run onAfk
if there is a event then the player is not afk

onAfk
it runs waitRednet and onEvent
if it receives a rednet message then run your logout function which will cause the computer to logout
if it receives a nonrednet event then the player is no longer afk.
AgentE382 #6
Posted 19 October 2014 - 04:12 AM
In case you didn't know, computers always listen for rednet messages. When they receive a message, they queue a rednet_message event along with the details (senderID, message, distanceTravelled).

The rednet.receive function actually just waits for a rednet_message event, then returns the details. os.sleep does the same thing, except it queues a timer, then waits for the corresponding event (while eating all other events until the timer is up).

Instead of calling rednet.receive, you can listen for these events in your program. So, if you're already doing something with events, like listening for user input, you're better off listening for rednet_messages yourself. Also, if you start a timer yourself instead of calling os.sleep, all the other events still get processed instead of bypassed.

From your post, it looks like this is what you want:
Handle user input.
If it's been two minutes since the last input, accept remote commands.
If the user does anything else, stop accepting remote commands.

Knowing what we know about rednet_messages and timers, and also knowing that user input fires events, I came up with this simple algorithm:
Grab an event.
If it's user input, stop / don't handle rednet messages, and start a timer to see when two minutes is up.
If it's a timer we already started (one is started for each user input), make sure it's the timer for the last user input. If it is, start handling rednet messages.
If it's a rednet message, and we're handling them, translate the message into a command.

This code should implement that algorithm and be pretty close what you want, or at least an example to base your code on. In any case, I don't know what functions you would use to translate rednet messages into remote commands.

while true do
    local event = {os.pullEvent()}
    local eType = event[1]
    local inactivityTimer, isInactive
    if eType == "char" or eType == "key" or eType == "paste" or eType == "mouse_click" or eType == "mouse_scroll" or eType == "mouse_drag" or eType == "monitor_touch" then --# User input happened.
        isInactive = false
        inactivityTimer = os.startTimer(120)
    elseif eType == "timer" then --# It's been two minutes since one thing the user did.
        if event[2] == inactivityTimer then --# It was the last thing the user did.
            isInactive = true
        end
    elseif eType == "rednet_message" then
        if isInactive then
            --# Call your rednet handling functions here.
        end
    else
        --# Do whatever other event handling you need here.
    end
end
The event type is the first field of the event table, then the other fields are the event's details, in order. You can check the os.pullEvent wiki page for what details each event has.

If you want this to run in the background for everything, you'll want to copy this BIOS Level Coroutine Override into the top of your startup file and put this at the end of your startup file (don't forget to put whatever functions you use for translating rednet_messages between the override and this):
run(
    function()
        parallel.waitForAny(
            function()
                if term.isColor() then
                    os.run({}, "rom/programs/advanced/multishell")
                else
                    os.run({}, "rom/programs/shell")
                end
                os.run({}, "rom/programs/shutdown")
            end,
            function()
                rednet.run()
            end,
            function()
                --# Paste the whole event-handling (while true do) loop above here.
            end
        )
    end
)
The first two functions in the parallel.waitForAny are what computers run by default. Using the override like this kills everything that's running, then puts it all back, along with the code to handle remote commands.
Edited on 19 October 2014 - 02:56 AM