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

Hooks and Timers

Started by my_hat_stinks, 31 May 2012 - 06:14 PM
my_hat_stinks #1
Posted 31 May 2012 - 08:14 PM
What is it?

It's a tool for coders, it makes it a lot simpler to create timed functions and repetitions, and to call groups of functions at the same time.
Background applications are very simple to create with this.

How does it work?

The hooks will allow you to call multiple functions as and when an event occurs. By default, all events available in os.pullEventRaw are available in the hooks, including up to 5 arguments. The "timer" event isn't available as a hook, but there is the addition of a "Think" hook which will be called roughly once every tick, to be used for constant repetitive events, in place of an endless loop.
Adding a hook will allow code to continue running, too, so you can have as many different programs running as you want, without complicating anything, and reduced chance they'll interfere with each other.

The timers allow complete and easy control over delays, and the number of times to repeat.

It will run what is, for most purposes, the default shell, so programs which do not make use of these functions should still be compatible. (Just make sure that if they have an endless loop, they're included last :)/>/>)

Hook functions

hook.Add( String Hook, String Name, Function [, Arguments (No limit)] )
Adds a new hook. If Arguments are specified, they will override arguments from hook.Call for this function. Other functions on the same hook are unaffected.
local function CharEntered( char )
  write("Character "..char.." was entered!n")
end
hook.Add("char", "CharacterEntered", CharEntered)
hook.Add("Think", "SimpleThinkHook", function() write(".") end)

hook.Remove( String Hook, String Name)
Removes a hook.
hook.Add("Think", "SimpleThinkHook", function() write(".") end)
hook.Remove("Think", "SimpleThinkHook")

hook.Call( String Hook [, Arguments (No limit)] )
Calls a hook. Useful for custom hooks.
hook.Add("HookName", "SimpleHook", function( string ) write( string ) end)
hook.Call("HookName", "Called a function!")

hook.GetTable()
Returns a table with all the current hooks.

Alternative function names
--Aliases
--[[__________________________]]--
hook.add = hook.Add
hook.remove = hook.Remove
hook.call = hook.Call
hook.getTable = hook.GetTable
Timer Functions

timer.Create( String Name, Number Delay, Number Repetitions, Function [, Arguments] )
Creates a named timer. Creating another timer with the same name will overwrite the older one. Inserting 0 to number of repetitions will repeat indefinitely. Returns a boolean, true if created, otherwise false.
Note that timer names are case sensitive. Use unique and descriptive names to avoid accidental overwriting.
timer.Create("BinaryCounterTimer", 1, 0, Operate, 2)

timer.Simple( Number Delay, Function [,Arguments] )
Creates a simple timer. Will only fire once. Returns a boolean, true if created, otherwise false.
Unlike named timers, these cannot be modified or restarted.
write("Shutting down in 10 seconds. Please save any work.n")
timer.Simple(10, os.shutdown)

timer.Exists( String Name )
Checks for the existence of a timer. Returns a boolean.
if timer.Exists("Random Timer name") then print("The timer exists!") end

timer.Pause( String Name )
Attempts to pause the timer. Returns a boolean, true if successful, otherwise false.
local time = 0
timer.Create("Timer", 1, 0, function() time=time+1 end)
print("You are now being timed. Press any key to pause.")
hook.Add("key", "PauseTimer", function() timer.Pause("Timer") end)

timer.Unpause( String Name )
Resumes a paused timer. Will restart a timer if it has ended. Returns a boolean, true if successful, otherwise false.
timer.Unpause("Timer")

timer.Toggle( String Name )
Toggles a timer between paused and unpaused states. Returns a boolean, true if successful, otherwise false.
function PauseGame()
   paused = not paused
   timer.Toggle( "Game Timer" )
end

timer.Destroy( String Name )
Removes a timer. Returns true if successful, otherwise false.
timer.Destroy("Timer")

timer.Restart( String Name )
Restarts a timer. Similar to creating the timer again with the same name. Returns a boolean, true if successful, otherwise false.
function Restart()
   timer.Restart( "Main Timer" )
end

timer.Modify( String Name, Number Delay, Number Recurrence, Function, Arguments )
Modifies an active timer. Identical format as creating a new timer. If any argument is Nil, it will not modify that field. If the timer does not exist, it will create that timer and pause it. Only Name is mandatory.
Any nil values in a newly created timer from this function are as follows:
Delay 1, Recurrence 0 (Infinite), Function function() write("Timer error: Nil function.") end, Args Nil
Returns a boolean, true if successful, otherwise false.
timer.Create("Some Timer Name", 1, 0, write, "This timer will last for ever!")

timer.Modify("Some Timer Name", nil, 10) --Now it will only run 10 times


Alternative function names
--Aliases
--[[__________________________]]--
timer.simple = timer.Simple
timer.create = timer.Create
timer.exists = timer.Exists
timer.destroy = timer.Destroy
timer.restart = timer.Restart
timer.pause = timer.Pause
timer.unpause = timer.Unpause
timer.toggle = timer.Toggle

timer.Remove = timer.Destroy
timer.remove = timer.Destroy

timer.Resume = timer.Unpause
timer.resume = timer.Unpause

Simple demostration of the uses

(Finally got this working :)/>/>)
[media]http://www.youtube.com/watch?v=UevnwczBCRQ[/media]

That lights script can be found here
Nothing too impressive, just to show you what it can do

Installation

Download:
Hooks file
Timers file

Installer (Installer will NOT work on tekkit recommended build, it uses the pastebin command which isn't available)

Using the installer
Save the installer on the computer you want to install to, then run the file and follow the on-screen instructions.
Once you're done, add shell.run( [[Whatever your hooks file is, default "hook"]] ) to the first line of your startup file

Manual install to backing storage (HDD)
Save the hooks file anywhere on the computer, then make a folder beside it called [Hooks file name]_addons
Insert the timer file with any name into the _addons folder, then add a shell.run pointing to the hooks file, into the first line of your startup file

Manual install to ROM
Simply enter the hooks file into the rom/autorun folder (Create it if you don't have one), then insert the timer file to rom/autorun/[hook file name]_addons/ with any name
This is not designed as an appi, don't put it in the appi folder!




Have fun, and don't forget to show us anything interesting you make with it!



ToDo
-Support for modifying active named timers Done
-Get a better demonstration video Done (Enjoy the mediocrity!)
Edited on 04 June 2012 - 01:23 PM
cant_delete_account #2
Posted 01 June 2012 - 01:01 AM
Again, another Adf.ly link…
*facepalm*
kazagistar #3
Posted 01 June 2012 - 05:03 AM
Wow, this is pretty well done, I might make some tweaks to it, but it looks pretty solid overall. I was thinking a priority system, where it pulls all the events, but then passes them to observers by priority. I feel that things like a turtle moving, since it freezes up the system for a bit, should be lower priority, so important stuff gets done first. Also, something like passing on a message might take priority over other things, to speed up multihop network transfers.

Edit: I am confused… how is this installed exactly? Is it an OS, or does it multitask?
my_hat_stinks #4
Posted 01 June 2012 - 03:32 PM
Just gonna re-upload that video, looks like it's gone "Blegh"
It's nothing too impressive, though, just a quick example so you can see what it can do


Edit: I am confused… how is this installed exactly? Is it an OS, or does it multitask?

It's more multi-tasking, but if you're using a custom os it might have a conflict (Because of how it works, it needs to re-create the interface)



To install it, you just put the script anywhere, and run it on startup
Better to have it included on the first line of the startup file, because anything before it will be run twice

The timers file is dependant on the hook file, so there's a simple addon system built in. You can't have the timers without the hooks, but you can have the hooks without the timers
Just stick the timer file in a folder called "[wherever your hook file is]/[what you called it]_addons/" and it'll be run automatically, immediately after hooks are set up

For example, if you're using the default settings from that installer, you'd end up with a root directory like this:
rom [Directory]   hook_addons [Directory]
hook [File]

If you're wanting to put it into the rom folder, so it's automatically on all computers, it'd be something like this
rom/autorun/hook [File]   rom/autorun/hook_addons [Directory]
You might not have an autorun folder, but if you create it the default os already deals with it properly
Any changes to rom have to happen outside the game though, so you'd need to go to "%appdata%\.minecraft\mods\ComputerCraft\lua\rom\autorun" on your comptuer to edit it (For tekkit, replace the ".minecraft" with ".techniclauncher\tekkit")

I've tried to keep it as flexible as possible, if you make a utility that relies on the hooks you can just stick it in your _addons folder, and not have to worry about it
Although I do recommend you use the usual methods for any other code



If you've got the installer file, just run it (eg, if you've called it "installer" you'd just type "installer" in the command line), then it'll ask you where to place it, then it'll download the files automatically

A lot simpler, but relies on the "pastebin" program
my_hat_stinks #5
Posted 01 June 2012 - 09:51 PM
Updated the timers, added new functions that make them a lot more useful (And, in my opinion, a lot more superior to the in-built timer :)/>/>)

Same link to update, and if you're using the installer file just run it again (It'll back up the old files, if you really need them)


Not sure why the video's uploading so poorly, if someone gets a better demonstration I'll add theirs instead

Additions (Also shown in the first post)
Spoilertimer.Exists( String Name )
Checks for the existence of a timer. Returns a boolean.
if timer.Exists("Random Timer name") then print("The timer exists!") end

timer.Pause( String Name )
Attempts to pause the timer. Returns a boolean, true if successful, otherwise false.
local time = 0
timer.Create("Timer", 1, 0, function() time=time+1 end)
print("You are now being timed. Press any key to pause.")
hook.Add("key", "PauseTimer", function() timer.Pause("Timer") end)

timer.Unpause( String Name )
Resumes a paused timer. Will restart a timer if it has ended. Returns a boolean, true if successful, otherwise false.
timer.Unpause("Timer")

timer.Toggle( String Name )
Toggles a timer between paused and unpaused states. Returns a boolean, true if successful, otherwise false.
function PauseGame()
   paused = not paused
   timer.Toggle( "Game Timer" )
end

timer.Destroy( String Name )
Removes a timer. Returns true if successful, otherwise false.
timer.Destroy("Timer")

timer.Restart( String Name )
Restarts a timer. Similar to creating the timer again with the same name. Returns a boolean, true if successful, otherwise false.
function Restart()
   timer.Restart( "Main Timer" )
end

timer.Modify( String Name, Number Delay, Number Recurrence, Function, Arguments )
Modifies an active timer. Identical format as creating a new timer. If any argument is Nil, it will not modify that field. If the timer does not exist, it will create that timer and pause it. Only Name is mandatory.
Any nil values in a newly created timer from this function are as follows:
Delay 1, Recurrence 0 (Infinite), Function function() write("Timer error: Nil function.") end, Args Nil
Returns a boolean, true if successful, otherwise false.
timer.Create("Some Timer Name", 1, 0, write, "This timer will last for ever!")

timer.Modify("Some Timer Name", nil, 10) --Now it will only run 10 times


Alternative function names
--Aliases
--[[__________________________]]--
timer.simple = timer.Simple
timer.create = timer.Create
timer.exists = timer.Exists
timer.destroy = timer.Destroy
timer.restart = timer.Restart
timer.pause = timer.Pause
timer.unpause = timer.Unpause
timer.toggle = timer.Toggle

timer.Remove = timer.Destroy
timer.remove = timer.Destroy

timer.Resume = timer.Unpause
timer.resume = timer.Unpause


Also, if anyone was wondering about that license, it's just the basic Creative Commons Attribution license
That means you can do whatever you want with it, including modify it, sell it, or use it in something you sell :)/>/>