123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- --mt_api_addons
- --License: MIT License
- --Event registration lists
- minetest.registered_removeentity_events = {}
- minetest.registered_clear_objects_events = {}
- minetest.registered_playerstep_events = {}
- --Hooks a function onto a function
- local function hook(func, func2)
- if type(func) == "function" then
- return function(...)
- func2(...)
- return func(...)
- end
- end
- return nil
- end
- --Handler needed for specific events
- local function do_handler(category, ...)
- local events = minetest["registered_"..category.."_events"]
- if events then
- for count,func in pairs(events) do
- func(...)
- end
- end
- end
- --Handle playerstep events
- local function handle_playerstep_events(dtime)
- local events = minetest.registered_playerstep_events
- if events then
- for _,player in pairs(minetest.get_connected_players()) do
- for count,event in pairs(events) do
- local name = player:get_player_name()
- local interval = event.interval
- if not minetest.registered_playerstep_events[count].players[name] then
- minetest.registered_playerstep_events[count].players[name] = {time = 0}
- end
- local time = minetest.registered_playerstep_events[count].players[name].time
- time = time + dtime
- if time >= interval then
- event.func(player, dtime)
- minetest.registered_playerstep_events[count].players[name].time = 0
- else
- minetest.registered_playerstep_events[count].players[name].time = time
- end
- end
- end
- else
- return
- end
- end
- --Use globalstep to handle playerstep events
- minetest.register_globalstep(function(dtime)
- handle_playerstep_events(dtime)
- end)
- --Safely injects a hook to builtin function clear_objects
- core.clear_objects = hook(core.clear_objects, function(option)
- do_handler("clear_objects", option)
- end)
- --Safely Inject hooks to all registered entities after all mods have been loaded
- minetest.register_on_mods_loaded(function(player)
- for name,def in pairs(minetest.registered_entities) do
- minetest.registered_entities[name].get_staticdata = hook(def.get_staticdata, function(self)
- if not self.hook_injected then
- local meta = getmetatable(self.object)
- meta.remove = hook(meta.remove, function(self)
- --get entity properties
- self = self:get_luaentity()
- if not(self.removed or self.removed == true) then
- self.removed = true
- do_handler("removeentity", self)
- end
- end)
- --Update objectref's Metatable
- setmetatable(meta, meta)
- end
- end)
- end
- minetest.log("action", "Entity on_remove hook injected successfully.")
- end)
- --Backwards compatability substitute for on_rightclickplayer (for those who are using outdated clients)
- if not minetest.register_on_rightclickplayer then
- local update_interval = minetest.settings:get("player_rightclick_step") or 0.1
- minetest.registered_rightclickplayer_events = {}
- --Check if the player right-clicked a player
- local function verify_clicked_player(clicker, range)
- local result = nil
- local ray_start = vector.add(clicker:get_pos(), {x=0, y= clicker:get_properties().eye_height, z=0})
- local ray_modif = vector.add(vector.multiply(clicker:get_look_dir(), range), clicker:get_eye_offset())
- local ray_end = vector.add(ray_start, ray_modif)
- local ray = minetest.raycast(ray_start, ray_end, true, false)
- local clicked = ray:next()
- clicked = ray:next()
- if clicked and clicked.type == "object" and clicked.ref:is_player() and clicked.ref ~= clicker then
- result = clicked.ref
- end
- return result
- end
- --Handle rightclicking for older minetest versions
- local function handle_rightclickplayer()
- local events = minetest.registered_rightclickplayer_events
- if events then
- for _,clicker in pairs(minetest.get_connected_players()) do
- local right_click = clicker:get_player_control().RMB or false
- if clicker and right_click == true then
- local name = clicker:get_player_name()
- local clicked = verify_clicked_player(clicker, 4)
- if clicked then
- for _,func in pairs(events) do
- func(clicker, clicked)
- end
- end
- break
- end
- end
- minetest.after(update_interval, function()
- handle_rightclickplayer()
- end)
- end
- end
-
- --Register on rightclick player (Called when a player rightclicked a fellow player)
- function minetest.register_on_rightclickplayer(func)
- assert(type(func) == "function", "you must include a function with the following arguements (player, clicker).")
- table.insert(minetest.registered_rightclickplayer_events, func)
- end
- end
- --Register on playerstep (Just like globalstep, but specifically for players. interval included for convenience and performance reasons)
- function minetest.register_playerstep(interval, func)
- assert(interval and type(interval) == "number", "must include a interval number value.")
- assert(func and type(func) == "function", "must include a function with the following arguements (dtime).")
- table.insert(minetest.registered_playerstep_events, {["players"] = {}, ["interval"] = interval, ["func"] = func})
- end
- --Register on remove entity (Called after objectref:remove() gets called)
- function minetest.register_on_removeentity(func)
- assert(type(func) == "function", "you must include a function with the following arguement (self).")
- table.insert(minetest.registered_removeentity_events, func)
- end
- --Register on remove entity (Called when builtin core.clear_objects() gets called)
- function minetest.register_on_clearobjects(func)
- assert(type(func) == "function", "you must include a function with the following arguement (option).")
- table.insert(minetest.registered_clear_objects_events, func)
- end
|