init.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. --[[
  2. Bags for Minetest
  3. Copyright (c) 2012 cornernote, Brett O'Donnell <cornernote@gmail.com>
  4. Source Code: https://github.com/cornernote/minetest-bags
  5. License: BSD-3-Clause https://raw.github.com/cornernote/minetest-bags/master/LICENSE
  6. Edited by TenPlus1
  7. ]]--
  8. if not minetest.global_exists("bags") then bags = {} end
  9. bags.modpath = minetest.get_modpath("bags")
  10. function bags.get_formspec(player, page)
  11. if page == "bags" then
  12. return "size[8,8.5]"
  13. ..default.gui_bg..default.gui_bg_img..default.gui_slots
  14. .."list[current_player;main;0,4.25;8,1;]"
  15. .."list[current_player;main;0,5.5;8,3;8]"
  16. .."button[0,1;2,0.5;main;Back]"
  17. .."button[2.5,1;1.3,0.5;bag1;Bag 1]"
  18. .."button[2.5,2.2;1.3,0.5;bag2;Bag 2]"
  19. .."button[5.2,1;1.3,0.5;bag3;Bag 3]"
  20. .."button[5.2,2.2;1.3,0.5;bag4;Bag 4]"
  21. .."list[detached:"..player:get_player_name().."_bags;bag1;3.8,.8;1,1;]"
  22. .."list[detached:"..player:get_player_name().."_bags;bag2;3.8,2;1,1;]"
  23. .."list[detached:"..player:get_player_name().."_bags;bag3;6.5,.8;1,1;]"
  24. .."list[detached:"..player:get_player_name().."_bags;bag4;6.5,2;1,1;]"
  25. ..default.get_hotbar_bg(0, 4.25)
  26. end
  27. for i = 1, 4 do
  28. if page == "bag" .. i then
  29. local image = player:get_inventory():get_stack("bag"
  30. .. i, 1):get_definition().inventory_image
  31. --[[
  32. return "size[8,9.5]"
  33. ..default.gui_bg..default.gui_bg_img..default.gui_slots
  34. .."list[current_player;main;0,5.5;8,4;]"
  35. .."button[6,0.2;2,0.5;main;Main]"
  36. .."button[4,0.2;2,0.5;bags;Bags]"
  37. .."image[0,0;1,1;" .. image .. "]"
  38. .."list[current_player;bag" .. i .. "contents;0,1;8,4;]"
  39. --]]
  40. local by = 5.05
  41. local bx = 5.37
  42. local bw = 0.57
  43. local bh = 0.41
  44. return "size[8,9.5]"
  45. .. default.gui_bg .. default.gui_bg_img .. default.gui_slots
  46. .. "list[current_player;bag" .. i .. "contents;0,0;8,4;]"
  47. .. "button[0,4.2.2;2,0.5;main;Main]"
  48. .. "label[2,4.2;" .. minetest.formspec_escape("Bag #" .. i .. "") .. "]"
  49. .. "button[6,4.2;2,0.5;bags;Bags]"
  50. .. "image[3,4;1,1;" .. image .. "]"
  51. .. "real_coordinates[true]"
  52. .. "button[" .. bx + bw * 0 .. "," .. by .. ";" .. bw .. "," .. bh .. ";bag1;1]"
  53. .. "button[" .. bx + bw * 1 .. "," .. by .. ";" .. bw .. "," .. bh .. ";bag2;2]"
  54. .. "button[" .. bx + bw * 2 .. "," .. by .. ";" .. bw .. "," .. bh .. ";bag3;3]"
  55. .. "button[" .. bx + bw * 3 .. "," .. by .. ";" .. bw .. "," .. bh .. ";bag4;4]"
  56. .. "button[" .. bx + bw * 0 .. "," .. by + bh .. ";" .. bw * 2 .. "," .. bh .. ";bagdrop" .. i .. ";Chuck]"
  57. .. "button[" .. bx + bw * 2 .. "," .. by + bh .. ";" .. bw * 2 .. "," .. bh .. ";baggrab" .. i .. ";Snatch]"
  58. .. "real_coordinates[false]"
  59. .. "list[current_player;main;0,5.5;8,1;]"
  60. .. "list[current_player;main;0,6.75;8,3;8]"
  61. .. "listring[current_player;main]"
  62. .. "listring[current_player;bag" .. i .. "contents]"
  63. .. default.get_hotbar_bg(0, 5.5)
  64. end
  65. end
  66. end
  67. function bags.get_chest(player)
  68. local lookdir = player:get_look_dir()
  69. local eyeheight = player:get_properties().eye_height
  70. local eye = vector.add(player:get_pos(), {x=0, y=eyeheight, z=0})
  71. local sop = vector.add(eye, vector.multiply(lookdir, 5))
  72. local ray = Raycast(eye, sop, false, false)
  73. local pos, protected
  74. for pointed_thing in ray do
  75. if pointed_thing.type == "node" then
  76. local node = minetest.get_node(pointed_thing.under)
  77. if minetest.get_item_group(node.name, "chest") ~= 0 then
  78. -- Forbid using this on open chests.
  79. -- Theft would be a mere snatch!
  80. if not string.find(node.name, "_open$") then
  81. local trypos = pointed_thing.under
  82. local nodename = minetest.get_node(trypos).name
  83. local nodemeta = minetest.get_meta(trypos)
  84. local nodedef = minetest.registered_nodes[nodename] or {}
  85. -- Check if it's really registered as a chest with the chest API.
  86. if nodedef._chest_basename then
  87. if nodedef.protected then
  88. -- Chest is protected.
  89. if chest_api.has_locked_chest_privilege(trypos, nodename, nodemeta, player) then
  90. pos = trypos
  91. protected = true
  92. break
  93. end
  94. else
  95. -- Chest not protected, no access check.
  96. pos = trypos
  97. break
  98. end
  99. end
  100. end
  101. end
  102. -- Fail if the first node we point at isn't a chest.
  103. -- No reaching through walls!
  104. break
  105. else
  106. -- Fail if pointing at anything other than a node.
  107. -- No reaching through entities!
  108. break
  109. end
  110. end
  111. return pos, protected
  112. end
  113. function bags.drop_items(player, bagnum)
  114. local bag = "bag" .. bagnum .. "contents"
  115. local inv = player:get_inventory()
  116. if not inv then return end
  117. if inv:get_size(bag) <= 0 then return end
  118. local pos, protected = bags.get_chest(player)
  119. if not pos then return end
  120. local meta = minetest.get_meta(pos)
  121. local inv2 = meta:get_inventory()
  122. if not inv2 then return end
  123. if inv2:get_size("main") <= 0 then return end
  124. local size = inv:get_size(bag)
  125. local count = 0
  126. for k = 1, size, 1 do
  127. local stack = inv:get_stack(bag, k)
  128. count = count + stack:get_count()
  129. stack = inv2:add_item("main", stack)
  130. count = count - stack:get_count()
  131. inv:set_stack(bag, k, stack)
  132. end
  133. return pos, count, protected
  134. end
  135. function bags.grab_items(player, bagnum)
  136. local bag = "bag" .. bagnum .. "contents"
  137. local inv = player:get_inventory()
  138. if not inv then return end
  139. if inv:get_size(bag) <= 0 then return end
  140. local pos, protected = bags.get_chest(player)
  141. if not pos then return end
  142. local meta = minetest.get_meta(pos)
  143. local inv2 = meta:get_inventory()
  144. if not inv2 then return end
  145. if inv2:get_size("main") <= 0 then return end
  146. local size = inv2:get_size("main")
  147. local count = 0
  148. for k = 1, size, 1 do
  149. local stack = inv2:get_stack("main", k)
  150. count = count + stack:get_count()
  151. stack = inv:add_item(bag, stack)
  152. count = count - stack:get_count()
  153. inv2:set_stack("main", k, stack)
  154. end
  155. return pos, count, protected
  156. end
  157. function bags.receive_fields(player, formname, fields)
  158. if fields.bags then
  159. inventory_plus.set_inventory_formspec(player, bags.get_formspec(player, "bags"))
  160. return
  161. end
  162. local pname = player:get_player_name()
  163. for i = 1, 4 do
  164. local page = "bag" .. i
  165. local drop = "bagdrop" .. i
  166. local grab = "baggrab" .. i
  167. if fields[page] then
  168. if player:get_inventory():get_stack(page, 1):get_definition().groups.bagslots == nil then
  169. page = "bags"
  170. end
  171. inventory_plus.set_inventory_formspec(player, bags.get_formspec(player, page))
  172. return
  173. end
  174. if fields[drop] then
  175. local target, count, protected = bags.drop_items(player, i)
  176. if target then
  177. local protstr = ""
  178. if protected then protstr = "protected " end
  179. minetest.chat_send_player(pname, "# Server: Bag #" .. i .. ": " .. count .. " items chucked into " .. protstr .. "chest at " .. rc.pos_to_namestr(target) .. ".")
  180. if count > 0 then
  181. easyvend.sound_vend(player:get_pos())
  182. end
  183. else
  184. easyvend.sound_error(pname)
  185. end
  186. return
  187. end
  188. if fields[grab] then
  189. local target, count, protected = bags.grab_items(player, i)
  190. if target then
  191. local protstr = ""
  192. if protected then protstr = "protected " end
  193. minetest.chat_send_player(pname, "# Server: Bag #" .. i .. ": " .. count .. " items snatched from " .. protstr .. "chest at " .. rc.pos_to_namestr(target) .. ".")
  194. if count > 0 then
  195. easyvend.sound_vend(player:get_pos())
  196. end
  197. else
  198. easyvend.sound_error(pname)
  199. end
  200. return
  201. end
  202. end
  203. end
  204. if not bags.loaded then
  205. local c = "bags:core"
  206. local f = bags.modpath .. "/init.lua"
  207. reload.register_file(c, f, false)
  208. bags.loaded = true
  209. minetest.register_on_player_receive_fields(function(...)
  210. return bags.receive_fields(...) end)
  211. minetest.register_on_joinplayer(function(player)
  212. local player_inv = player:get_inventory()
  213. local bags_inv = minetest.create_detached_inventory(player:get_player_name().."_bags",{
  214. on_put = function(inv, listname, index, stack, player)
  215. player:get_inventory():set_stack(listname, index, stack)
  216. player:get_inventory():set_size(listname.."contents", stack:get_definition().groups.bagslots)
  217. end,
  218. on_take = function(inv, listname, index, stack, player)
  219. player:get_inventory():set_stack(listname, index, nil)
  220. end,
  221. allow_put = function(inv, listname, index, stack, player)
  222. if stack:get_definition().groups.bagslots then
  223. return 1
  224. else
  225. return 0
  226. end
  227. end,
  228. allow_take = function(inv, listname, index, stack, player)
  229. if player:get_inventory():is_empty(listname .. "contents") == true then
  230. return stack:get_count()
  231. else
  232. return 0
  233. end
  234. end,
  235. allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
  236. return 0
  237. end,
  238. }, player:get_player_name())
  239. for i = 1, 4 do
  240. local bag = "bag" .. i
  241. player_inv:set_size(bag, 1)
  242. bags_inv:set_size(bag, 1)
  243. bags_inv:set_stack(bag, 1, player_inv:get_stack(bag, 1))
  244. end
  245. end)
  246. -- register bags items
  247. minetest.register_craftitem("bags:small", {
  248. description = "Small Bag",
  249. inventory_image = "bags_small.png",
  250. groups = {bagslots = 8},
  251. })
  252. minetest.register_craftitem("bags:medium", {
  253. description = "Medium Bag",
  254. inventory_image = "bags_medium.png",
  255. groups = {bagslots = 16},
  256. })
  257. minetest.register_craftitem("bags:large", {
  258. description = "Large Bag",
  259. inventory_image = "bags_large.png",
  260. groups = {bagslots = 24},
  261. })
  262. minetest.register_tool("bags:trolley", {
  263. description = "Trolley",
  264. inventory_image = "bags_trolley.png",
  265. groups = {bagslots = 32},
  266. })
  267. -- register bag crafts
  268. minetest.register_craft({
  269. output = "bags:small",
  270. recipe = {
  271. {"farming:string", "group:stick", "farming:string"},
  272. {"group:leather", "group:leather", "group:leather"},
  273. {"group:leather", "group:leather", "group:leather"},
  274. },
  275. })
  276. minetest.register_craft({
  277. output = "bags:medium",
  278. recipe = {
  279. {"farming:string", "group:stick", "farming:string"},
  280. {"bags:small", "bags:small", "bags:small"},
  281. },
  282. })
  283. minetest.register_craft({
  284. output = "bags:large",
  285. recipe = {
  286. {"farming:string", "group:stick", "farming:string"},
  287. {"bags:medium", "bags:medium", "bags:medium"},
  288. },
  289. })
  290. minetest.register_craft({
  291. output = "bags:trolley",
  292. recipe = {
  293. {"", "group:stick", ""},
  294. {"bags:large", "bags:large", "bags:large"},
  295. {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
  296. },
  297. })
  298. -- Register button once.
  299. inventory_plus.register_button("bags", "Bags")
  300. end