**Title:** Timekeeper

**Description:** 

**Details:**
The Timekeeper class provides a simple and efficient means of executing code at regular intervals. The constructor itself is global, so typically it will be used in conjunction with entities.

* **Timekeeper( this )**  
Instantiates and returns a new timekeeper object, with an optional meta table for use by callbacks (typically this will be a reference to the entity itself). Ideally the Timekeeper constructor will be called as soon as the LuaEntitySAO has been added to the environment.

```
on_activate(self)
        self.timekeeper = Timekeeper(self)
        :
end
```

The following methods are available:

* **timekeeper.start( period, name, func, delay )**  
Begins a new timer with the given name and period. The callback will execute no sooner than the next server step. If the callback returns false, then the timer will be cancelled and removed from the queue. An optional delay can be specified to avoid concurrency with other running timers.

* **timekeeper.start_now( period, name, func )**  
Identical to timekeeper.start(), except the first iteration of the callback will be executed immediately.

* **timekeeper.clear( name )**  
Cancels an existing timer with the given name.

Four parameters are provided to the timer callback for each iteration:

* this - the meta table that was originally passed to the constructor
* cycles - the number of cycles that have accrued, beginning at 1
* period - the interval between each cycle
* elapsed - the elapsed time for all cycles
* overrun - the overrun time from the last cycle

In order for the timers to be processed correctly, you must call the on_step() method of the timekeeper object during every server step. For example, in the case of entities:

```lua
on_step = function (dtime)
        local timers = self.timekeeper.on_step(dtime)

end,
```

With a globalstep callback, it is similar albeit the timekeeper object will likely be defined at the head of the script.

```lua
local timekeeper = Timekeeper { }

minetest.register_globalstep(function(dtime)
        local timers = timekeeper.on_step(dtime)
end)
```

Notice that the on_step method of the timekeeper object returns a table of timers. This can be useful for processing one or more timer events directly within the globalstep callback.

For convenience, a global timekeeper object is  available for use by all mods. This can avoid the need to register additional globalsteps when a simple timer mechanism is all that is required. In this case, it is  recommened that timer names be prefixed with the mod name and a colon to avoid collisions.

Here is an example mod that displays the player's orientation at the bottom of the screen.

```lua
local player_huds = { }

local dir_names = {
	["N"] = "north",
	["NE"] = "northeast",
	["E"] = "east",
	["SE"] = "southeast",
	["S"] = "south",
	["SW"] = "southwest",
	["W"] = "west",
	["NW"] = "northwest",
	["U"] = "up",
	["D"] = "down",
}

minetest.register_on_joinplayer( function( player )
        local player_name = player:get_player_name( )

        player_huds[ player_name ] = player:hud_add( {
                hud_elem_type = "text",
                text = "",
                position = { x = 0.5, y = 1 },
                scale = { x = -100, y = -100 },
                number = 0xFFFFFF,
                alignment = { x = 0, y = 0 },
                offset = { x = 0, y = -105 }
        } )
end )

minetest.register_on_leaveplayer( function( player )
	player_huds[ player:get_player_name( ) ] = nil
end )

local function to_facing( dir )
	local dx = math.floor( dir.x + 0.5 )
	local dz = math.floor( dir.z + 0.5 )

	if dx == 0 and dz == 0 then
		return dir.y > 0 and "U" or "D"
	else
		return ( { [1] = "N", [0] = "", [-1] = "S" } )[ dz ] .. ( { [1] = "E", [0] = "", [-1] = "W" } )[ dx ]
	end
end

globaltimer.start( 2.5, "sample_mod:update_hud", function ( this, cycles )
	for _, player in ipairs( minetest.get_connected_players( ) ) do
		local cur_dir = to_facing( player:get_look_dir( ) )
		local player_name = player:get_player_name( )
		player:hud_change( player_huds[ player_name ], "text", string.format( "You are facing %s", dir_names[ cur_dir ] ) )
	end
end )
```

**Tags:** library
**Repository:** https://bitbucket.org/sorcerykid/timekeeper.git
**License:** MIT