[Mod] Timekeeper [timekeeper]

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

[Mod] Timekeeper [timekeeper]

by sorcerykid » Post

Image

Timekeeper Mod v1.3
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
https://github.com/sorcerykid/timekeeper (mirror)

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.
The timekeeper object is instantiated within the on_activate callback of an entity:

Code: Select all

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

Code: Select all

on_step = function (self, dtime)
        local timers = self.timekeeper.on_step(dtime)
        :
end,
The on_step method of the timekeeper object returns a table of running timers. This can be useful for post-processing of timers within the on_step callback. Each timer consists of the following read-only fields: cycles, period, expiry, started, and func.

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

The following method is available, but only at server startup:
  • globaltimer.start( period, name, func, delay )
    Starts a new global timer with the given name and period (name must be prefixed with the current mod name). The callback will execute no sooner than the first server step. An optional delay can be specified to avoid concurrency with other global timers.
Four parameters are provided to the global timer callback for each iteration:
  • cycles - the number of cycles that have accrued, beginning at 1
  • period - the interval between each cycle
  • uptime - the elapsed time since server start
  • overrun - the overrun time from the last cycle
Since global timers are persistent, they are best suited for ongoing tasks that execute for the lifetime of the server. Hence, there is no clear method.

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

globaltimer.start( 2.5, "sample_mod:update_hud", function ( 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 )
Last edited by sorcerykid on Mon Jul 03, 2023 20:38, edited 1 time in total.

User avatar
srutzky
New member
Posts: 6
Joined: Tue Oct 06, 2020 03:13
GitHub: srutzky
Contact:

Re: [Mod] Timekeeper [timekeeper]

by srutzky » Post

Hi there. I'm attempting to test out the Debug Console which requires the Timekeeper mod. However, I can't seem to get it to work. Timekeeper keeps crashing as the game is loading (whether or not Console or Config mods are enabled), with the following details:

Code: Select all

WARNING[Server]: Undeclared global variable "S1" accessed at C:\Program Files\Minetest\bin\..\mods\timekeeper\init.lua:31
ERROR[Main]: ServerError: AsyncErr: environment_Step: Runtime error from mod 'timekeeper' in callback environment_Step(): C:\Program Files\Minetest\bin\..\mods\timekeeper\init.lua:31: attempt to call global 'S1' (a nil value)
ERROR[Main]: stack traceback:
ERROR[Main]: 	C:\Program Files\Minetest\bin\..\mods\timekeeper\init.lua:31: in function 'on_step'
ERROR[Main]: 	C:\Program Files\Minetest\bin\..\mods\timekeeper\init.lua:61: in function <C:\Program Files\Minetest\bin\..\mods\timekeeper\init.lua:60>
ERROR[Main]: 	C:\Program Files\Minetest\bin\..\builtin\game\register.lua:429: in function <C:\Program Files\Minetest\bin\..\builtin\game\register.lua:413>
ERROR[Main]: stack traceback:
Take care,
Solomon...

P.S. It would be really helpful to link to this forum thread on its related ContentDB page :-)
https://content.minetest.net/packages/s ... imekeeper/
⦓ (blog) Sql Quantum Leap   ⟐   (info sites) Collations  •  Module Signing  •  SQLCLR ⦔

User avatar
Blockhead
Member
Posts: 1696
Joined: Wed Jul 17, 2019 10:14
GitHub: Montandalar
IRC: Blockhead256
In-game: Blockhead Blockhead256
Location: Land Down Under
Contact:

Re: [Mod] Timekeeper [timekeeper]

by Blockhead » Post

I would really like to use Timekeeper as a library, but the git version is mismatched with the version published on ContentDB; it doesn't create globaltimer by default. I have a mirror over my GitHub that adds this, but would prefer to be able to point my git remotes directly at the original BitBucket version.
/˳˳_˳˳]_[˳˳_˳˳]_[˳˳_˳˳\ Advtrains enthusiast | My map: Noah's Railyard | My Content on ContentDB ✝️♂

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

Re: [Mod] Timekeeper [timekeeper]

by sorcerykid » Post

I appreciate your bringing this to my attention. I noticed couple weeks ago that the git repo was out of sync with the current master. I'm planning to double-check all of my mod sources (Bitbucket, Github, and ContentDB) to ensure they are up-to-date.

Sorry about the confusion.

User avatar
Blockhead
Member
Posts: 1696
Joined: Wed Jul 17, 2019 10:14
GitHub: Montandalar
IRC: Blockhead256
In-game: Blockhead Blockhead256
Location: Land Down Under
Contact:

Re: [Mod] Timekeeper [timekeeper]

by Blockhead » Post

sorcerykid wrote:
Tue Feb 21, 2023 19:54
I appreciate your bringing this to my attention. I noticed couple weeks ago that the git repo was out of sync with the current master. I'm planning to double-check all of my mod sources (Bitbucket, Github, and ContentDB) to ensure they are up-to-date.

Sorry about the confusion.
Ah that's good news thanks, I'll pull that then, and after that I can delete my fork. Can you elucidate what is on your BitBucket vs your GitHub and why I might use one or the other?
/˳˳_˳˳]_[˳˳_˳˳]_[˳˳_˳˳\ Advtrains enthusiast | My map: Noah's Railyard | My Content on ContentDB ✝️♂

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

Re: [Mod] Timekeeper [timekeeper]

by sorcerykid » Post

As promised, the Bitbucket and GitHub repos are now up-to-date with the master branch. Here's the changelog:

Version 1.1 (06-Sep-2020)
  • Removed shift and unshift methods
  • Removed extraneous delay property
  • Incorporated delay as parameter of start method
  • Added experimental globaltimer object
Version 1.2 (19-Jan-2021)
  • Implemented globaltimer as singleton object
  • Refactored Timekeeper class
  • Added sanity check to start method
Version 1.3 (12-Aug-2022)
  • Simplified handling of initial global timer step
  • Expanded README.txt with full documentation
Please note that the globaltimer implementation in Version 1.2+ is not backwards compatible with Version 1.1, which is currently on ContentDB. So you will need to make adjustments to any mods that depend on that API.

Post Reply

Who is online

Users browsing this forum: No registered users and 27 guests