[Mod] Timekeeper [timekeeper]

Post Reply
User avatar
sorcerykid
Member
Posts: 1344
Joined: Fri Aug 26, 2016 15:36
GitHub: sorcerykid
In-game: Nemo
Location: Illinois, USA

[Mod] Timekeeper [timekeeper]

by sorcerykid » Post

Timekeeper Mod v1.0
timekeeper (by sorcerykid)

Timekeeper acts as a centralized dispatcher for all time-sensitive routines, obviating the need for redundant timer implementations within each mod.

Repository:

https://bitbucket.org/sorcerykid/timekeeper

Download Archive (.zip)
Download Archive (.tar.gz)

Dependencies:

None.

Source Code License:

The MIT License (MIT)

Overview:

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.

Code: Select all

on_activate(self)
        self.timekeeper = Timekeeper(self)
        :
end
The following methods are available:
  • timekeeper.start( period, name, func )
    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.

    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.

    timekeeper.shift( dtime )
    Delays the execution of new timers by the given dtime, which may prove useful to avoid concurrency.

    timekeeper.unshift( )
    Restores the default execution of new timers without a delay.
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:

Code: Select all

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.

Code: Select all

minetest.register_globalstep(function(dtime)
        local timers = globaltimer.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.

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

Code: Select all

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

local globaltimer = Timekeeper { }

globaltimer.start( 2.5, "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 )

minetest.register_globalstep( function ( dtime )
	globaltimer.on_step( dtime )
end )

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests