init.lua 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. --[[
  2. Bags for Minetest
  3. Copyright (c) 2012 cornernote, Brett O'Donnell <cornernote@gmail.com>
  4. Original Source Code: https://github.com/cornernote/minetest-bags
  5. License: BSD-3-Clause https://raw.github.com/cornernote/minetest-bags/master/LICENSE
  6. Tweaked by TenPlus1 and Security improvements by Krock
  7. ]]--
  8. -- translator check for backwards compatibility
  9. local S
  10. if minetest.get_translator then
  11. S = minetest.get_translator("sfinv_bags")
  12. else
  13. S = function(str, ...)
  14. local args = {...}
  15. return str:gsub("@%d+", function(match)
  16. return args[tonumber(match:sub(2))]
  17. end)
  18. end
  19. end
  20. local function get_player_bag_stack(player, i)
  21. return minetest.get_inventory({
  22. type = "detached",
  23. name = player:get_player_name() .. "_bags"
  24. }):get_stack("bag" .. i, 1)
  25. end
  26. local get_formspec = function(player, page)
  27. if page == "bags" then
  28. local name = player:get_player_name()
  29. return "size[8,7.5]"
  30. .. "button[1,-0.4;3,3;bag1;" .. S("Bag") .. " 1]"
  31. .. "button[1,0.6;3,3;bag2;" .. S("Bag") .. " 2]"
  32. .. "button[1,1.6;3,3;bag3;" .. S("Bag") .. " 3]"
  33. .. "button[1,2.6;3,3;bag4;" .. S("Bag") .. " 4]"
  34. .. "list[detached:" .. name .. "_bags;bag1;6,0.5;1,1;]"
  35. .. "list[detached:" .. name .. "_bags;bag2;6,1.5;1,1;]"
  36. .. "list[detached:" .. name .. "_bags;bag3;6,2.5;1,1;]"
  37. .. "list[detached:" .. name .. "_bags;bag4;6,3.5;1,1;]"
  38. .. "image[4.5,0.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"
  39. .. "image[4.5,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"
  40. .. "image[4.5,2.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"
  41. .. "image[4.5,3.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"
  42. .. "list[current_player;main;0,5.2;8,1;]"
  43. .. "list[current_player;main;0,6.35;8,3;8]"
  44. .. default.get_hotbar_bg(0,5.2)
  45. end
  46. for i = 1, 4 do
  47. if page == "bag" .. i then
  48. local image = get_player_bag_stack(player, i)
  49. :get_definition().inventory_image
  50. return "size[8,9]"
  51. .. "list[current_player;bag" .. i .. "contents;0,0;8,4;]"
  52. .. "button[6,4.2.2;2,0.5;bags;" .. S("Main") .. "]"
  53. .. "image[3.5,4;1,1;" .. image .. "]"
  54. .. "list[current_player;main;0,5.2;8,1;]"
  55. .. "list[current_player;main;0,6.35;8,3;8]"
  56. .. default.get_hotbar_bg(0,5.2)
  57. .. "listring[current_player;main]"
  58. .. "listring[current_player;bag" .. i .. "contents]"
  59. end
  60. end
  61. end
  62. local function save_bags_metadata(player, bags_inv)
  63. local is_empty = true
  64. local bags = {}
  65. local meta = player:get_meta()
  66. for i = 1, 4 do
  67. local bag = "bag" .. i
  68. if not bags_inv:is_empty(bag) then
  69. -- Stack limit is 1, otherwise use stack:to_string()
  70. bags[i] = bags_inv:get_stack(bag, 1):get_name()
  71. is_empty = false
  72. end
  73. end
  74. if is_empty then
  75. meta:set_string("bags:bags", nil)
  76. else
  77. meta:set_string("bags:bags", minetest.serialize(bags))
  78. end
  79. end
  80. local function load_bags_metadata(player, bags_inv)
  81. local player_inv = player:get_inventory()
  82. local meta = player:get_meta()
  83. local bags_meta = meta:get_string("bags:bags")
  84. local bags = bags_meta and minetest.deserialize(bags_meta) or {}
  85. local dirty_meta = false
  86. if not bags_meta then
  87. -- Backwards compatiblity
  88. for i = 1, 4 do
  89. local bag = "bag" .. i
  90. if not player_inv:is_empty(bag) then
  91. -- Stack limit is 1, otherwise use stack:to_string()
  92. bags[i] = player_inv:get_stack(bag, 1):get_name()
  93. dirty_meta = true
  94. end
  95. end
  96. end
  97. -- Fill detached slots
  98. for i = 1, 4 do
  99. local bag = "bag" .. i
  100. bags_inv:set_size(bag, 1)
  101. bags_inv:set_stack(bag, 1, bags[i] or "")
  102. -- Deprecated, clean up garbage
  103. player_inv:set_size(bag, 0)
  104. end
  105. if dirty_meta then
  106. -- Requires detached inventory to be set up
  107. save_bags_metadata(player, bags_inv)
  108. end
  109. end
  110. minetest.register_on_joinplayer(function(player)
  111. local player_name = player:get_player_name()
  112. local bags_inv = minetest.create_detached_inventory(player_name .. "_bags", {
  113. on_put = function(inv, listname, index, stack, player)
  114. player:get_inventory():set_size(listname .. "contents",
  115. stack:get_definition().groups.bagslots)
  116. save_bags_metadata(player, inv)
  117. end,
  118. allow_put = function(inv, listname, index, stack, player)
  119. if not stack:get_definition().groups.bagslots then
  120. return 0
  121. end
  122. if not player:get_inventory():is_empty(listname .. "contents") then
  123. return 0
  124. end
  125. return 1
  126. end,
  127. allow_take = function(inv, listname, index, stack, player)
  128. if player:get_inventory():is_empty(listname .. "contents") then
  129. return stack:get_count()
  130. end
  131. return 0
  132. end,
  133. on_take = function(inv, listname, index, stack, player)
  134. player:get_inventory():set_size(listname .. "contents", 0)
  135. save_bags_metadata(player, inv)
  136. end,
  137. allow_move = function(inv, from_list, from_index, to_list, to_index,
  138. count, player)
  139. return 0
  140. end,
  141. }, player_name)
  142. load_bags_metadata(player, bags_inv)
  143. end)
  144. -- register bags page
  145. sfinv.register_page("sfinv_bags:bags", {
  146. title = S("Bags"),
  147. get = function(self, player, context)
  148. context.bagpage = context.bagpage or "bags"
  149. return sfinv.make_formspec(player, context, get_formspec(player, context.bagpage))
  150. end,
  151. on_player_receive_fields = function(self, player, context, fields)
  152. local name = player:get_player_name()
  153. if fields.bags then
  154. context.bagpage = "bags"
  155. sfinv.set_player_inventory_formspec(player, context)
  156. return
  157. end
  158. for i = 1, 4 do
  159. local page = "bag" .. i
  160. if fields[page] then
  161. local stack = get_player_bag_stack(player, i)
  162. if not stack:get_definition().groups.bagslots then
  163. page = "bags"
  164. end
  165. context.bagpage = page
  166. sfinv.set_player_inventory_formspec(player, context)
  167. return
  168. end
  169. end
  170. end
  171. })
  172. -- register bags items
  173. minetest.register_craftitem(":bags:small", {
  174. description = S("Small Bag"),
  175. inventory_image = "bags_small.png",
  176. groups = {bagslots = 8, flammable = 2},
  177. })
  178. minetest.register_craftitem(":bags:medium", {
  179. description = S("Medium Bag"),
  180. inventory_image = "bags_medium.png",
  181. groups = {bagslots = 16, flammable = 2},
  182. })
  183. minetest.register_craftitem(":bags:large", {
  184. description = S("Large Bag"),
  185. inventory_image = "bags_large.png",
  186. groups = {bagslots = 24, flammable = 2},
  187. })
  188. minetest.register_tool(":bags:trolley", {
  189. description = S("Trolley"),
  190. inventory_image = "bags_trolley.png",
  191. groups = {bagslots = 32, flammable = 2},
  192. })
  193. -- default craft items
  194. local item1 = "group:wood"
  195. local item2 = "group:stick"
  196. -- use leather if mobs redo found
  197. if minetest.get_modpath("mobs") then
  198. item1 = "mobs:leather"
  199. -- use leather if petz found
  200. elseif minetest.get_modpath("petz") then
  201. item1 = "petz:leather"
  202. end
  203. -- use string if farming found
  204. if minetest.get_modpath("farming") then
  205. item2 = "farming:string"
  206. end
  207. -- register bag crafts
  208. minetest.register_craft({
  209. output = "bags:small",
  210. recipe = {
  211. {"", item2, ""},
  212. {item1, item1, item1},
  213. {item1, item1, item1},
  214. },
  215. })
  216. minetest.register_craft({
  217. output = "bags:medium",
  218. recipe = {
  219. {"", item2, ""},
  220. {"bags:small", "bags:small", "bags:small"},
  221. },
  222. })
  223. minetest.register_craft({
  224. output = "bags:large",
  225. recipe = {
  226. {"", item2, ""},
  227. {"bags:medium", "bags:medium", "bags:medium"},
  228. },
  229. })
  230. minetest.register_craft({
  231. output = "bags:trolley",
  232. recipe = {
  233. {"", item2, ""},
  234. {"bags:large", "bags:large", "bags:large"},
  235. },
  236. })
  237. print ("[MOD] Sfinv Bags loaded")