init.lua 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. --File name: init.lua
  2. --Project name: compost, a Mod for Minetest
  3. --License: General Public License, version 3 or later
  4. --Original Work Copyright (C) 2016 cd2 (cdqwertz) <cdqwertz@gmail.com>
  5. --Modified Work Copyright (C) Vitalie Ciubotaru <vitalie at ciubotaru dot tk>
  6. -- Load support for intllib.
  7. local MP = minetest.get_modpath(minetest.get_current_modname())
  8. local S, NS = dofile(MP.."/intllib.lua")
  9. compost_version = '0.0.3'
  10. compost = {}
  11. compost.compostable_groups = {'flora', 'leaves', 'flower'}
  12. compost.compostable_nodes = {
  13. 'default:cactus',
  14. 'default:papyrus',
  15. 'default:dry_shrub',
  16. 'default:junglegrass',
  17. 'default:grass_1',
  18. 'default:dry_grass_1',
  19. 'farming:wheat',
  20. 'farming:straw',
  21. 'farming:cotton',
  22. }
  23. compost.compostable_items = {}
  24. for _, v in pairs(compost.compostable_nodes) do
  25. compost.compostable_items[v] = true
  26. end
  27. local function formspec(pos)
  28. local spos = pos.x..','..pos.y..','..pos.z
  29. local formspec =
  30. 'size[8,8.5]'..
  31. default.gui_bg..
  32. default.gui_bg_img..
  33. default.gui_slots..
  34. 'list[nodemeta:'..spos..';src;0,0;8,1;]'..
  35. 'list[nodemeta:'..spos..';dst;3.5,2;1,1;]'..
  36. 'list[current_player;main;0,4.25;8,1;]'..
  37. 'list[current_player;main;0,5.5;8,3;8]'..
  38. 'listring[nodemeta:'..spos ..';dst]'..
  39. 'listring[current_player;main]'..
  40. 'listring[nodemeta:'..spos ..';src]'..
  41. 'listring[current_player;main]'..
  42. default.get_hotbar_bg(0, 4.25)
  43. return formspec
  44. end
  45. local function is_compostable(input)
  46. if compost.compostable_items[input] then
  47. return true
  48. end
  49. for _, v in pairs(compost.compostable_groups) do
  50. if minetest.get_item_group(input, v) > 0 then
  51. return true
  52. end
  53. end
  54. return false
  55. end
  56. local function swap_node(pos, name)
  57. local node = minetest.get_node(pos)
  58. if node.name == name then
  59. return
  60. end
  61. node.name = name
  62. minetest.swap_node(pos, node)
  63. end
  64. local function count_input(pos)
  65. local q = 0
  66. local meta = minetest.get_meta(pos)
  67. local inv = meta:get_inventory()
  68. local stacks = inv:get_list('src')
  69. for k in pairs(stacks) do
  70. q = q + inv:get_stack('src', k):get_count()
  71. end
  72. return q
  73. end
  74. local function is_empty(pos)
  75. local meta = minetest.get_meta(pos)
  76. local inv = meta:get_inventory()
  77. local stacks = inv:get_list('src')
  78. for k in pairs(stacks) do
  79. if not inv:get_stack('src', k):is_empty() then
  80. return false
  81. end
  82. end
  83. if not inv:get_stack('dst', 1):is_empty() then
  84. return false
  85. end
  86. return true
  87. end
  88. local function update_nodebox(pos)
  89. if is_empty(pos) then
  90. swap_node(pos, "compost:wood_barrel_empty")
  91. else
  92. swap_node(pos, "compost:wood_barrel")
  93. end
  94. end
  95. local function update_timer(pos)
  96. local timer = minetest.get_node_timer(pos)
  97. local meta = minetest.get_meta(pos)
  98. local count = count_input(pos)
  99. if not timer:is_started() and count >= 8 then
  100. timer:start(30)
  101. meta:set_int('Progress', 0)
  102. meta:set_string('infotext', S("progress: @1%", "0"))
  103. return
  104. end
  105. if timer:is_started() and count < 8 then
  106. timer:stop()
  107. meta:set_string('infotext', S("To start composting, place some organic matter inside."))
  108. meta:set_int('progress', 0)
  109. end
  110. end
  111. local function create_compost(pos)
  112. local q = 8
  113. local meta = minetest.get_meta(pos)
  114. local inv = meta:get_inventory()
  115. local stacks = inv:get_list('src')
  116. for k in pairs(stacks) do
  117. local stack = inv:get_stack('src', k)
  118. if not stack:is_empty() then
  119. local count = stack:get_count()
  120. if count <= q then
  121. inv:set_stack('src', k, '')
  122. q = q - count
  123. else
  124. inv:set_stack('src', k, stack:get_name() .. ' ' .. (count - q))
  125. q = 0
  126. break
  127. end
  128. end
  129. end
  130. local dirt_count = inv:get_stack('dst', 1):get_count()
  131. inv:set_stack('dst', 1, 'default:dirt ' .. (dirt_count + 1))
  132. end
  133. local function on_timer(pos)
  134. local timer = minetest.get_node_timer(pos)
  135. local meta = minetest.get_meta(pos)
  136. local progress = meta:get_int('progress') + 10
  137. if progress >= 100 then
  138. create_compost(pos)
  139. meta:set_int('progress', 0)
  140. else
  141. meta:set_int('progress', progress)
  142. end
  143. if count_input(pos) >= 8 then
  144. meta:set_string('infotext', S("progress: @1%", progress))
  145. return true
  146. else
  147. timer:stop()
  148. meta:set_string('infotext', S("To start composting, place some organic matter inside."))
  149. meta:set_int('progress', 0)
  150. return false
  151. end
  152. end
  153. local function on_construct(pos)
  154. local meta = minetest.get_meta(pos)
  155. local inv = meta:get_inventory()
  156. inv:set_size('src', 8)
  157. inv:set_size('dst', 1)
  158. meta:set_string('infotext', S("To start composting, place some organic matter inside."))
  159. meta:set_int('progress', 0)
  160. end
  161. local function on_rightclick(pos, node, clicker, itemstack)
  162. minetest.show_formspec(
  163. clicker:get_player_name(),
  164. 'compost:wood_barrel',
  165. formspec(pos)
  166. )
  167. end
  168. local function can_dig(pos,player)
  169. local meta = minetest.get_meta(pos)
  170. local inv = meta:get_inventory()
  171. if inv:is_empty('src') and inv:is_empty('dst') then
  172. return true
  173. else
  174. return false
  175. end
  176. end
  177. local function allow_metadata_inventory_put(pos, listname, index, stack, player)
  178. if listname == 'src' and is_compostable(stack:get_name()) then
  179. return stack:get_count()
  180. else
  181. return 0
  182. end
  183. end
  184. local function on_metadata_inventory_put(pos, listname, index, stack, player)
  185. update_timer(pos)
  186. update_nodebox(pos)
  187. return
  188. end
  189. local function on_metadata_inventory_take(pos, listname, index, stack, player)
  190. update_timer(pos)
  191. update_nodebox(pos)
  192. return
  193. end
  194. local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
  195. local inv = minetest.get_meta(pos):get_inventory()
  196. if from_list == to_list then
  197. return inv:get_stack(from_list, from_index):get_count()
  198. else
  199. return 0
  200. end
  201. end
  202. local function on_punch(pos, node, player, pointed_thing)
  203. local meta = minetest.get_meta(pos)
  204. local inv = meta:get_inventory()
  205. local wielded_item = player:get_wielded_item()
  206. if not wielded_item:is_empty() then
  207. local wielded_item_name = wielded_item:get_name()
  208. local wielded_item_count = wielded_item:get_count()
  209. if is_compostable(wielded_item_name) and inv:room_for_item('src', wielded_item_name) then
  210. player:set_wielded_item('')
  211. inv:add_item('src', wielded_item_name .. ' ' .. wielded_item_count)
  212. update_nodebox(pos)
  213. update_timer(pos)
  214. end
  215. end
  216. local compost_count = inv:get_stack('dst', 1):get_count()
  217. local wielded_item = player:get_wielded_item() --recheck
  218. if compost_count > 0 and wielded_item:is_empty() then
  219. inv:set_stack('dst', 1, '')
  220. player:set_wielded_item('default:dirt ' .. compost_count)
  221. update_nodebox(pos)
  222. update_timer(pos)
  223. end
  224. end
  225. minetest.register_node("compost:wood_barrel_empty", {
  226. description = S("Empty Compost Bin"),
  227. tiles = {
  228. "default_wood.png",
  229. },
  230. drawtype = "nodebox",
  231. node_box = {
  232. type = "fixed",
  233. fixed = {{-1/2, -1/2, -1/2, 1/2, -3/8, 1/2},
  234. {-1/2, -1/2, -1/2, -3/8, 1/2, 1/2},
  235. {3/8, -1/2, -1/2, 1/2, 1/2, 1/2},
  236. {-1/2, -1/2, -1/2, 1/2, 1/2, -3/8},
  237. {-1/2, -1/2, 3/8, 1/2, 1/2, 1/2}},
  238. },
  239. selection_box = {
  240. type = "fixed",
  241. fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
  242. },
  243. paramtype = "light",
  244. is_ground_content = false,
  245. groups = {choppy = 3},
  246. sounds = default.node_sound_wood_defaults(),
  247. on_timer = on_timer,
  248. on_construct = on_construct,
  249. on_rightclick = on_rightclick,
  250. can_dig = can_dig,
  251. allow_metadata_inventory_put = allow_metadata_inventory_put,
  252. allow_metadata_inventory_move = allow_metadata_inventory_move,
  253. on_metadata_inventory_put = on_metadata_inventory_put,
  254. on_metadata_inventory_take = on_metadata_inventory_take,
  255. on_punch = on_punch,
  256. })
  257. minetest.register_node("compost:wood_barrel", {
  258. description = S("Compost Bin"),
  259. tiles = {
  260. "default_wood.png^compost_compost.png",
  261. "default_wood.png",
  262. },
  263. drawtype = "nodebox",
  264. node_box = {
  265. type = "fixed",
  266. fixed = {{-1/2, -1/2, -1/2, 1/2, -3/8, 1/2},
  267. {-1/2, -1/2, -1/2, -3/8, 1/2, 1/2},
  268. {3/8, -1/2, -1/2, 1/2, 1/2, 1/2},
  269. {-1/2, -1/2, -1/2, 1/2, 1/2, -3/8},
  270. {-1/2, -1/2, 3/8, 1/2, 1/2, 1/2},
  271. {-3/8, -1/2, -3/8, 3/8, 3/8, 3/8}},
  272. },
  273. selection_box = {
  274. type = "fixed",
  275. fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
  276. },
  277. paramtype = "light",
  278. is_ground_content = false,
  279. groups = {choppy = 3, not_in_creative_inventory = 1},
  280. sounds = default.node_sound_wood_defaults(),
  281. on_timer = on_timer,
  282. on_construct = on_construct,
  283. on_rightclick = on_rightclick,
  284. can_dig = can_dig,
  285. allow_metadata_inventory_put = allow_metadata_inventory_put,
  286. allow_metadata_inventory_move = allow_metadata_inventory_move,
  287. on_metadata_inventory_put = on_metadata_inventory_put,
  288. on_metadata_inventory_take = on_metadata_inventory_take,
  289. on_punch = on_punch,
  290. })
  291. minetest.register_craft({
  292. output = "compost:wood_barrel_empty",
  293. recipe = {
  294. {"group:wood", "", "group:wood"},
  295. {"group:wood", "", "group:wood"},
  296. {"group:wood", "stairs:slab_wood", "group:wood"}
  297. }
  298. })