furnaces.lua 8.4 KB

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