diff --git a/.luacheckrc b/.luacheckrc index d9b2fbe..a68b439 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -1,25 +1,8 @@ -unused_args = false -allow_defined_top = true - -exclude_files = {".luacheckrc"} globals = { - "minetest", "core", - - --mod provided "controls", } read_globals = { - string = {fields = {"split"}}, - table = {fields = {"copy", "getn"}}, - - --luac - "math", "table", - - -- Builtin - "vector", "ItemStack", "dump", "DIR_DELIM", "VoxelArea", "Settings", "PcgRandom", "VoxelManip", "PseudoRandom", - - --mod produced - -} \ No newline at end of file + "minetest", +} diff --git a/debug.lua b/debug.lua new file mode 100644 index 0000000..f9f91cd --- /dev/null +++ b/debug.lua @@ -0,0 +1,21 @@ +controls.register_on_press(function(player, key) + local name = player:get_player_name() + minetest.chat_send_player(name, name .. " pressed " .. key) +end) + +controls.register_on_hold(function(player, key, length) + local name = player:get_player_name() + minetest.chat_send_player(name, name .. " held " .. key .. " for " .. length .. " seconds") +end) + +controls.register_on_release(function(player, key, length) + local name = player:get_player_name() + minetest.chat_send_player(name, name .. " released " .. key .. " after " .. length .. " seconds") +end) + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + minetest.chat_send_player(name, #controls.registered_on_press .. " registered_on_press callbacks") + minetest.chat_send_player(name, #controls.registered_on_hold .. " registered_on_hold callbacks") + minetest.chat_send_player(name, #controls.registered_on_release .. " registered_on_release callbacks") +end) diff --git a/init.lua b/init.lua index 1231935..51fbafa 100644 --- a/init.lua +++ b/init.lua @@ -1,82 +1,65 @@ controls = { - --util values - modpath = minetest.get_modpath("controls"), - testsmode = minetest.settings:get_bool("controls_enable_tests", false), - - --location to store callbacks - registered_on_press = {}, - registered_on_hold = {}, - registered_on_release = {}, - - --store player control data - players = {}, + registered_on_press = {}, + registered_on_hold = {}, + registered_on_release = {}, + players = {}, } ---api functions function controls.register_on_press(callback) - table.insert(controls.registered_on_press, callback) + table.insert(controls.registered_on_press, callback) end function controls.register_on_hold(callback) - table.insert(controls.registered_on_hold, callback) + table.insert(controls.registered_on_hold, callback) end function controls.register_on_release(callback) - table.insert(controls.registered_on_release, callback) + table.insert(controls.registered_on_release, callback) end ---set up key store on join -minetest.register_on_joinplayer(function(player, _) - local pname = player:get_player_name() - local controls_names = player:get_player_control() - - --note: could hardcode this, but this is more future proof in case minetest adds more controls - controls.players[pname] = {} - for key, _ in pairs(controls_names) do - --[[ - in theory the control value is false when they join, but hard coding just in case - consider changing this to named key table instead of numeric for better readability??? - ]] - controls.players[pname][key] = {false} - end +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + controls.players[name] = {} + for key in pairs(player:get_player_control()) do + controls.players[name][key] = {false} + end end) ---discard when leaving -minetest.register_on_leaveplayer(function(player, _) - local pname = player:get_player_name() - controls.players[pname] = nil +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + controls.players[name] = nil end) ---event loop -minetest.register_globalstep(function(dtime) - for _, player in pairs(minetest.get_connected_players()) do - local pname = player:get_player_name() - local pcontrols = player:get_player_control() +local function update_player_controls(player, player_controls) + local time_now = minetest.get_us_time() + for key, pressed in pairs(player:get_player_control()) do + if pressed and not player_controls[key][1] then + for _, callback in pairs(controls.registered_on_press) do + callback(player, key) + end + player_controls[key] = {true, time_now} + elseif pressed and player_controls[key][1] then + for _, callback in pairs(controls.registered_on_hold) do + callback(player, key, (time_now - player_controls[key][2]) / 1e6) + end + elseif not pressed and player_controls[key][1] then + for _, callback in pairs(controls.registered_on_release) do + callback(player, key, (time_now - player_controls[key][2]) / 1e6) + end + player_controls[key] = {false} + end + end +end - if not controls.players[pname] then break end --safety check - - --consider using minetest.get_us_time() instead of os.clock()? would need to convert to seconds however - for key, key_status in pairs(pcontrols) do - if key_status and not controls.players[pname][key][1] then - for _, callback in pairs(controls.registered_on_press) do - callback(player, key) - end - controls.players[pname][key] = {true, minetest.get_us_time()} - elseif key_status and controls.players[pname][key][1] then - for _, callback in pairs(controls.registered_on_hold) do - callback(player, key, (minetest.get_us_time() - controls.players[pname][key][2]) / 1e6) - end - elseif not key_status and controls.players[pname][key][1] then - for _, callback in pairs(controls.registered_on_release) do - callback(player, key, (minetest.get_us_time() - controls.players[pname][key][2]) / 1e6) - end - controls.players[pname][key] = {false} - end - end - end +minetest.register_globalstep(function() + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + if controls.players[name] then + update_player_controls(player, controls.players[name]) + end + end end) ---tests -if(controls.testsmode) then - dofile(controls.modpath .. "/test.lua") -end \ No newline at end of file +if minetest.settings:get_bool("controls_enable_debug", false) then + dofile(minetest.get_modpath("controls") .. "/debug.lua") +end diff --git a/mod.conf b/mod.conf index a27ca56..6efa232 100644 --- a/mod.conf +++ b/mod.conf @@ -1,2 +1,2 @@ -name=controls -description=util library for subscribing to events \ No newline at end of file +name = controls +description = Utility library for control press/hold/release events diff --git a/readme.md b/readme.md index 108f4a1..6ef607e 100644 --- a/readme.md +++ b/readme.md @@ -1,25 +1,35 @@ -# api +# Controls [controls] -note: supports all keys minetest does +[![luacheck](https://github.com/mt-mods/controls/workflows/luacheck/badge.svg)](https://github.com/mt-mods/controls/actions) +[![ContentDB](https://content.minetest.net/packages/mt-mods/controls/shields/downloads/)](https://content.minetest.net/packages/mt-mods/controls/) + +Utility library for control press/hold/release events. + +Rewritten and maintained version of [Arcelmi/minetest-controls](https://github.com/Arcelmi/minetest-controls). + + +## API + +Callbacks are supported for all keys in `player:get_player_control()`. ```lua controls.register_on_press(function(player, key) - -- called on key down - -- @player: player object - -- @key: key pressed + -- Called when a key is pressed + -- player: player object + -- key: key pressed end) controls.register_on_hold(function(player, key, length) - -- called while key is held - -- @player: player object - -- @key: key pressed - -- @length: length of time key was held in seconds + -- Called every globalstep while a key is held + -- player: player object + -- key: key pressed + -- length: length of time key has been held in seconds end) controls.register_on_release(function(player, key, length) - -- called on key up - -- @player: player object - -- @key: key pressed - -- @length: length of time key was held in seconds + -- Called when a key is released + -- player: player object + -- key: key pressed + -- length: length of time key was held in seconds end) -``` \ No newline at end of file +``` diff --git a/settingtypes.txt b/settingtypes.txt index 68a05d8..3407555 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -1 +1,2 @@ -controls_enable_tests (enable testing mode for player controls) bool false \ No newline at end of file +# Enable debug mod for player controls. Sends chat messages to the player when callbacks are called. +controls_enable_debug (Enable debug mode) bool false diff --git a/test.lua b/test.lua deleted file mode 100644 index 3bb2e67..0000000 --- a/test.lua +++ /dev/null @@ -1,21 +0,0 @@ -controls.register_on_press(function(player, key) - local pname = player:get_player_name() - minetest.chat_send_player(pname, pname .. " pressed " .. key) -end) - -controls.register_on_hold(function(player, key, length) - local pname = player:get_player_name() - minetest.chat_send_player(pname, pname .. " held " .. key .. " for " .. length .. " seconds") -end) - -controls.register_on_release(function(player, key, length) - local pname = player:get_player_name() - minetest.chat_send_player(pname, pname .. " released " .. key .. " after " .. length .. " seconds") -end) - -minetest.register_on_joinplayer(function(player, _) - local pname = player:get_player_name() - minetest.chat_send_player(pname, #controls.registered_on_press .. " registered_on_press callbacks") - minetest.chat_send_player(pname, #controls.registered_on_hold .. " registered_on_hold callbacks") - minetest.chat_send_player(pname, #controls.registered_on_release .. " registered_on_release callbacks") -end) \ No newline at end of file