init.lua 3.5 KB

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