init.lua 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. -- The global scope for all _**Minetestia Forge**_ mods.
  2. minetestia = minetestia or {}
  3. -- All players inventory `"main"` lists, indexed by player name.
  4. ---@type table<string, mt.ItemStack[]>
  5. minetestia.player_inventory_main_lists = {}
  6. ---@alias mf.on_player_inventory_change fun(player:mt.PlayerObjectRef, old_item:mt.ItemStack, new_item:mt.ItemStack, index:integer, action_name:"move"|"put"|"take"|"dig"|"place"|"pickup"|"eat"|string|nil, inventory_info:mt.InvInfo|nil)
  7. -- All registered inventory change handlers.
  8. ---@type {[integer]: mf.on_player_inventory_change}
  9. minetestia.registered_on_player_inventory_change = {}
  10. -- Register global inventory change callback.
  11. ---@param func mf.on_player_inventory_change
  12. function minetestia.register_on_player_inventory_change(func)
  13. table.insert(minetestia.registered_on_player_inventory_change, func)
  14. end
  15. -- Detect and trigger callbacks manually.
  16. ---@param player mt.PlayerObjectRef|table
  17. ---@param action string|nil
  18. ---@param info mt.InvInfo|nil
  19. function minetestia.handle_player_inventory_changes(player, action, info)
  20. minetest.after(0.1, function()
  21. if not player.is_player or not player:is_player() then return end
  22. local inv = player:get_inventory()
  23. local player_name = player:get_player_name()
  24. local old_list = minetestia.player_inventory_main_lists[player_name]
  25. local new_list = inv:get_list "main"
  26. for i, new_item in ipairs(new_list) do
  27. local old_item = old_list[i]
  28. if new_item ~= old_item then
  29. old_list[i] = new_item
  30. for _, fn in ipairs(minetestia.registered_on_player_inventory_change) do
  31. fn(player, old_item, new_item, i, action, info)
  32. end
  33. end
  34. end
  35. end)
  36. end
  37. ---------------------
  38. -- REGISTER EVENTS --
  39. ---------------------
  40. local handler = minetestia.handle_player_inventory_changes
  41. minetest.register_on_joinplayer(
  42. function(player)
  43. minetestia.player_inventory_main_lists[player:get_player_name()] =
  44. player:get_inventory():get_list "main"
  45. end
  46. )
  47. minetest.register_on_player_inventory_action(
  48. function(player, action, _, inventory_info)
  49. handler(player, action, inventory_info)
  50. end
  51. )
  52. minetest.register_on_dignode(function(_, _, player) handler(player, "dig") end)
  53. minetest.register_on_placenode(
  54. function(_, _, player) handler(player, "place") end
  55. )
  56. minetest.register_on_item_pickup(
  57. function(_, player) handler(player, "pickup") end
  58. )
  59. minetest.register_on_item_eat(
  60. function(_, _, _, player) handler(player, "eat") end
  61. )
  62. -------------------------------------
  63. -- WORKAROUND FOR THIRD-PARTY MODS --
  64. -------------------------------------
  65. local handle_changes = minetestia.handle_player_inventory_changes
  66. local players_online
  67. if minetest.is_singleplayer() then
  68. ---@return {[1]: mt.PlayerObjectRef|nil}
  69. players_online = function()
  70. if not minetestia.player_inventory_main_lists.singleplayer then
  71. return {}
  72. end
  73. return { minetest.get_player_by_name "singleplayer" }
  74. end
  75. else
  76. players_online = minetest.get_connected_players
  77. end
  78. -- Using this function is not recommended, but if you don't have the ability to
  79. -- handle events from someone else's mods, just turn it on with one line:
  80. -- ```lua
  81. -- minetest.register_on_mods_loaded(minetestia.auto_detect_inventory_changes)
  82. -- ```
  83. function minetestia.auto_detect_inventory_changes()
  84. minetest.after(1, function()
  85. for _, player in ipairs(players_online()) do
  86. -- log(player:get_player_name())
  87. handle_changes(player, "auto")
  88. end
  89. minetestia.auto_detect_inventory_changes()
  90. end)
  91. end
  92. -----------
  93. -- DEBUG --
  94. -----------
  95. -- local modpath = minetest.get_modpath(minetest.get_current_modname())
  96. -- dofile(modpath .. "/test.lua")