furnaces.lua 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. -- This code supplies an oven/stove. Basically it's just a copy of the default furnace with different textures.
  2. local S = minetest.get_translator("homedecor_common")
  3. local function swap_node(pos, name)
  4. local node = minetest.get_node(pos)
  5. if node.name == name then return end
  6. node.name = name
  7. minetest.swap_node(pos, node)
  8. end
  9. local function make_formspec(furnacedef, percent)
  10. local fire
  11. if percent and (percent > 0) then
  12. fire = ("%s^[lowpart:%d:%s"):format(
  13. furnacedef.fire_bg,
  14. (100-percent),
  15. furnacedef.fire_fg
  16. )
  17. else
  18. fire = "default_furnace_fire_bg.png"
  19. end
  20. local w = furnacedef.output_width
  21. local h = math.ceil(furnacedef.output_slots / furnacedef.output_width)
  22. return "size["..math.max(8, 6 + w)..",9]"..
  23. "image[2,2;1,1;"..fire.."]"..
  24. "list[current_name;fuel;2,3;1,1;]"..
  25. "list[current_name;src;2,1;1,1;]"..
  26. "list[current_name;dst;5,1;"..w..","..h..";]"..
  27. "list[current_player;main;0,5;8,4;]"..
  28. "listring[current_name;dst]"..
  29. "listring[current_player;main]"..
  30. "listring[current_name;src]"..
  31. "listring[current_player;main]"
  32. end
  33. --[[
  34. furnacedef = {
  35. description = "Oven",
  36. tiles = { ... },
  37. tiles_active = { ... },
  38. ^ +Y -Y +X -X +Z -Z
  39. tile_format = "oven_%s%s.png",
  40. ^ First '%s' replaced by one of "top", "bottom", "side", "front".
  41. ^ Second '%s' replaced by "" for inactive, and "_active" for active "front"
  42. ^ "side" is used for left, right and back.
  43. ^ tiles_active for front is set
  44. output_slots = 4,
  45. output_width = 2,
  46. cook_speed = 1,
  47. ^ Higher values cook stuff faster.
  48. extra_nodedef_fields = { ... },
  49. ^ Stuff here is copied verbatim into both active and inactive nodedefs
  50. ^ Useful for overriding drawtype, etc.
  51. }
  52. ]]
  53. local function make_tiles(tiles, fmt, active)
  54. if not fmt then return tiles end
  55. tiles = { }
  56. for i,side in ipairs{"top", "bottom", "side", "side", "side", "front"} do
  57. if active and (i == 6) then
  58. tiles[i] = fmt:format(side, "_active")
  59. else
  60. tiles[i] = fmt:format(side, "")
  61. end
  62. end
  63. return tiles
  64. end
  65. local furnace_can_dig = function(pos,player)
  66. local meta = minetest.get_meta(pos);
  67. local inv = meta:get_inventory()
  68. return inv:is_empty("fuel")
  69. and inv:is_empty("dst")
  70. and inv:is_empty("src")
  71. end
  72. function homedecor.register_furnace(name, furnacedef)
  73. furnacedef.fire_fg = furnacedef.fire_fg or "default_furnace_fire_fg.png"
  74. furnacedef.fire_bg = furnacedef.fire_bg or "default_furnace_fire_bg.png"
  75. furnacedef.output_slots = furnacedef.output_slots or 4
  76. furnacedef.output_width = furnacedef.output_width or 2
  77. furnacedef.cook_speed = furnacedef.cook_speed or 1
  78. local description = furnacedef.description or S("Furnace")
  79. local furnace_construct = function(pos)
  80. local meta = minetest.get_meta(pos)
  81. meta:set_string("formspec", make_formspec(furnacedef, 0))
  82. meta:set_string("infotext", description)
  83. local inv = meta:get_inventory()
  84. inv:set_size("fuel", 1)
  85. inv:set_size("src", 1)
  86. inv:set_size("dst", furnacedef.output_slots)
  87. end
  88. local furnace_allow_put = function(pos, listname, index, stack, player)
  89. local meta = minetest.get_meta(pos)
  90. local inv = meta:get_inventory()
  91. if listname == "fuel" then
  92. if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
  93. if inv:is_empty("src") then
  94. meta:set_string("infotext", S("@1 (empty)", description))
  95. end
  96. return stack:get_count()
  97. else
  98. return 0
  99. end
  100. elseif listname == "src" then
  101. return stack:get_count()
  102. elseif listname == "dst" then
  103. return 0
  104. end
  105. end
  106. local furnace_allow_move = function(pos, from_list, from_index, to_list, to_index, count, player)
  107. local meta = minetest.get_meta(pos)
  108. local inv = meta:get_inventory()
  109. local stack = inv:get_stack(from_list, from_index)
  110. if to_list == "fuel" then
  111. if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
  112. if inv:is_empty("src") then
  113. meta:set_string("infotext", S("@1 (empty)", description))
  114. end
  115. return count
  116. else
  117. return 0
  118. end
  119. elseif to_list == "src" then
  120. return count
  121. elseif to_list == "dst" then
  122. return 0
  123. end
  124. end
  125. local def = {
  126. description = description,
  127. tiles = make_tiles(furnacedef.tiles, furnacedef.tile_format, false),
  128. groups = furnacedef.groups or {cracky=2},
  129. sounds = furnacedef.sounds or default.node_sound_wood_defaults(),
  130. on_construct = furnace_construct,
  131. can_dig = furnace_can_dig,
  132. allow_metadata_inventory_put = furnace_allow_put,
  133. allow_metadata_inventory_move = furnace_allow_move,
  134. inventory = { lockable = true }
  135. }
  136. local def_active = {
  137. description = S("@1 (active)", description),
  138. tiles = make_tiles(furnacedef.tiles_active, furnacedef.tile_format, true),
  139. light_source = 8,
  140. drop = "homedecor:" .. name,
  141. groups = furnacedef.groups or {cracky=2, not_in_creative_inventory=1},
  142. sounds = furnacedef.sounds or default.node_sound_stone_defaults(),
  143. on_construct = furnace_construct,
  144. can_dig = furnace_can_dig,
  145. allow_metadata_inventory_put = furnace_allow_put,
  146. allow_metadata_inventory_move = furnace_allow_move,
  147. inventory = { lockable = true }
  148. }
  149. if furnacedef.extra_nodedef_fields then
  150. for k, v in pairs(furnacedef.extra_nodedef_fields) do
  151. def[k] = v
  152. def_active[k] = v
  153. end
  154. end
  155. local n_active = name.."_active"
  156. homedecor.register(name, def)
  157. homedecor.register(n_active, def_active)
  158. local nname, name_active = "homedecor:"..name, "homedecor:"..n_active
  159. minetest.register_abm({
  160. nodenames = {nname, name_active, nname.."_locked", name_active.."_locked"},
  161. label = "furnaces",
  162. interval = 1.0,
  163. chance = 1,
  164. action = function(pos, node, active_object_count, active_object_count_wider)
  165. local meta = minetest.get_meta(pos)
  166. for i, pname in ipairs({
  167. "fuel_totaltime",
  168. "fuel_time",
  169. "src_totaltime",
  170. "src_time"
  171. }) do
  172. if meta:get_string(pname) == "" then
  173. meta:set_float(pname, 0.0)
  174. end
  175. end
  176. local inv = meta:get_inventory()
  177. local srclist = inv:get_list("src")
  178. local cooked = nil
  179. local aftercooked
  180. if srclist then
  181. cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
  182. end
  183. local was_active = false
  184. if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
  185. was_active = true
  186. meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
  187. meta:set_float("src_time", meta:get_float("src_time") + furnacedef.cook_speed)
  188. if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
  189. -- check if there's room for output in "dst" list
  190. if inv:room_for_item("dst",cooked.item) then
  191. -- Put result in "dst" list
  192. inv:add_item("dst", cooked.item)
  193. -- take stuff from "src" list
  194. inv:set_stack("src", 1, aftercooked.items[1])
  195. end
  196. meta:set_string("src_time", 0)
  197. end
  198. end
  199. -- XXX: Quick patch, make it better in the future.
  200. local locked = node.name:find("_locked$") and "_locked" or ""
  201. local desc = minetest.registered_nodes[nname..locked].description
  202. if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
  203. local percent = math.floor(meta:get_float("fuel_time") /
  204. meta:get_float("fuel_totaltime") * 100)
  205. meta:set_string("infotext", S("@1 (active: @2%)", desc, percent))
  206. swap_node(pos,name_active..locked)
  207. meta:set_string("formspec", make_formspec(furnacedef, percent))
  208. return
  209. end
  210. local fuel = nil
  211. local afterfuel
  212. cooked = nil
  213. local fuellist = inv:get_list("fuel")
  214. srclist = inv:get_list("src")
  215. if srclist then
  216. cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
  217. end
  218. if fuellist then
  219. fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
  220. end
  221. if (not fuel) or (fuel.time <= 0) then
  222. meta:set_string("infotext", S("@1 (out of fuel)", desc))
  223. swap_node(pos, nname..locked)
  224. meta:set_string("formspec", make_formspec(furnacedef, 0))
  225. return
  226. end
  227. if cooked.item:is_empty() then
  228. if was_active then
  229. meta:set_string("infotext", S("@1 (empty)", desc))
  230. swap_node(pos, nname..locked)
  231. meta:set_string("formspec", make_formspec(furnacedef, 0))
  232. end
  233. return
  234. end
  235. if not inv:room_for_item("dst", cooked.item) then
  236. meta:set_string("infotext", S("@1 (output bins are full)", desc))
  237. swap_node(pos, nname..locked)
  238. meta:set_string("formspec", make_formspec(furnacedef, 0))
  239. return
  240. end
  241. meta:set_string("fuel_totaltime", fuel.time)
  242. meta:set_string("fuel_time", 0)
  243. inv:set_stack("fuel", 1, afterfuel.items[1])
  244. end,
  245. })
  246. end