summaryrefslogtreecommitdiff
path: root/homedecor_common/furnaces.lua
diff options
context:
space:
mode:
Diffstat (limited to 'homedecor_common/furnaces.lua')
-rw-r--r--homedecor_common/furnaces.lua283
1 files changed, 283 insertions, 0 deletions
diff --git a/homedecor_common/furnaces.lua b/homedecor_common/furnaces.lua
new file mode 100644
index 0000000..d628273
--- /dev/null
+++ b/homedecor_common/furnaces.lua
@@ -0,0 +1,283 @@
+-- This code supplies an oven/stove. Basically it's just a copy of the default furnace with different textures.
+
+local S = homedecor.gettext
+
+local function swap_node(pos, name)
+ local node = minetest.get_node(pos)
+ if node.name == name then return end
+ node.name = name
+ minetest.swap_node(pos, node)
+end
+
+local function make_formspec(furnacedef, percent)
+ local fire
+
+ if percent and (percent > 0) then
+ fire = ("%s^[lowpart:%d:%s"):format(
+ furnacedef.fire_bg,
+ (100-percent),
+ furnacedef.fire_fg
+ )
+ else
+ fire = "default_furnace_fire_bg.png"
+ end
+
+ local w = furnacedef.output_width
+ local h = math.ceil(furnacedef.output_slots / furnacedef.output_width)
+
+ return "size["..math.max(8, 6 + w)..",9]"..
+ "image[2,2;1,1;"..fire.."]"..
+ "list[current_name;fuel;2,3;1,1;]"..
+ "list[current_name;src;2,1;1,1;]"..
+ "list[current_name;dst;5,1;"..w..","..h..";]"..
+ "list[current_player;main;0,5;8,4;]"..
+ "listring[current_name;dst]"..
+ "listring[current_player;main]"..
+ "listring[current_name;src]"..
+ "listring[current_player;main]"
+end
+
+--[[
+furnacedef = {
+ description = "Oven",
+ tiles = { ... },
+ tiles_active = { ... },
+ ^ +Y -Y +X -X +Z -Z
+ tile_format = "oven_%s%s.png",
+ ^ First '%s' replaced by one of "top", "bottom", "side", "front".
+ ^ Second '%s' replaced by "" for inactive, and "_active" for active "front"
+ ^ "side" is used for left, right and back.
+ ^ tiles_active for front is set
+ output_slots = 4,
+ output_width = 2,
+ cook_speed = 1,
+ ^ Higher values cook stuff faster.
+ extra_nodedef_fields = { ... },
+ ^ Stuff here is copied verbatim into both active and inactive nodedefs
+ ^ Useful for overriding drawtype, etc.
+}
+]]
+
+local function make_tiles(tiles, fmt, active)
+ if not fmt then return tiles end
+ tiles = { }
+ for i,side in ipairs{"top", "bottom", "side", "side", "side", "front"} do
+ if active and (i == 6) then
+ tiles[i] = fmt:format(side, "_active")
+ else
+ tiles[i] = fmt:format(side, "")
+ end
+ end
+ return tiles
+end
+
+local furnace_can_dig = function(pos,player)
+ local meta = minetest.get_meta(pos);
+ local inv = meta:get_inventory()
+ return inv:is_empty("fuel")
+ and inv:is_empty("dst")
+ and inv:is_empty("src")
+end
+
+function homedecor.register_furnace(name, furnacedef)
+ furnacedef.fire_fg = furnacedef.fire_bg or "default_furnace_fire_fg.png"
+ furnacedef.fire_bg = furnacedef.fire_bg or "default_furnace_fire_bg.png"
+
+ furnacedef.output_slots = furnacedef.output_slots or 4
+ furnacedef.output_width = furnacedef.output_width or 2
+
+ furnacedef.cook_speed = furnacedef.cook_speed or 1
+
+ local description = furnacedef.description or S("Furnace")
+
+ local furnace_construct = function(pos)
+ local meta = minetest.get_meta(pos)
+ meta:set_string("formspec", make_formspec(furnacedef, 0))
+ meta:set_string("infotext", description)
+ local inv = meta:get_inventory()
+ inv:set_size("fuel", 1)
+ inv:set_size("src", 1)
+ inv:set_size("dst", furnacedef.output_slots)
+ end
+
+ local furnace_allow_put = function(pos, listname, index, stack, player)
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ if listname == "fuel" then
+ if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
+ if inv:is_empty("src") then
+ meta:set_string("infotext", S("@1 (empty)", description))
+ end
+ return stack:get_count()
+ else
+ return 0
+ end
+ elseif listname == "src" then
+ return stack:get_count()
+ elseif listname == "dst" then
+ return 0
+ end
+ end
+ local furnace_allow_move = function(pos, from_list, from_index, to_list, to_index, count, player)
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ local stack = inv:get_stack(from_list, from_index)
+ if to_list == "fuel" then
+ if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
+ if inv:is_empty("src") then
+ meta:set_string("infotext", S("@1 (empty)", description))
+ end
+ return count
+ else
+ return 0
+ end
+ elseif to_list == "src" then
+ return count
+ elseif to_list == "dst" then
+ return 0
+ end
+ end
+
+ local def = {
+ description = description,
+ tiles = make_tiles(furnacedef.tiles, furnacedef.tile_format, false),
+ groups = furnacedef.groups or {cracky=2},
+ sounds = furnacedef.sounds or default.node_sound_wood_defaults(),
+ on_construct = furnace_construct,
+ can_dig = furnace_can_dig,
+ allow_metadata_inventory_put = furnace_allow_put,
+ allow_metadata_inventory_move = furnace_allow_move,
+ inventory = { lockable = true }
+ }
+
+ local def_active = {
+ description = S("@1 (active)", description),
+ tiles = make_tiles(furnacedef.tiles_active, furnacedef.tile_format, true),
+ light_source = 8,
+ drop = "homedecor:" .. name,
+ groups = furnacedef.groups or {cracky=2, not_in_creative_inventory=1},
+ sounds = furnacedef.sounds or default.node_sound_stone_defaults(),
+ on_construct = furnace_construct,
+ can_dig = furnace_can_dig,
+ allow_metadata_inventory_put = furnace_allow_put,
+ allow_metadata_inventory_move = furnace_allow_move,
+ inventory = { lockable = true }
+ }
+
+ if furnacedef.extra_nodedef_fields then
+ for k, v in pairs(furnacedef.extra_nodedef_fields) do
+ def[k] = v
+ def_active[k] = v
+ end
+ end
+
+ local n_active = name.."_active"
+
+ homedecor.register(name, def)
+ homedecor.register(n_active, def_active)
+
+ local nname, name_active = "homedecor:"..name, "homedecor:"..n_active
+
+ minetest.register_abm({
+ nodenames = {nname, name_active, nname.."_locked", name_active.."_locked"},
+ label = "furnaces",
+ interval = 1.0,
+ chance = 1,
+ action = function(pos, node, active_object_count, active_object_count_wider)
+ local meta = minetest.get_meta(pos)
+ for i, pname in ipairs({
+ "fuel_totaltime",
+ "fuel_time",
+ "src_totaltime",
+ "src_time"
+ }) do
+ if meta:get_string(pname) == "" then
+ meta:set_float(pname, 0.0)
+ end
+ end
+
+ local inv = meta:get_inventory()
+
+ local srclist = inv:get_list("src")
+ local cooked = nil
+ local aftercooked
+
+ if srclist then
+ cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
+ end
+
+ local was_active = false
+
+ if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
+ was_active = true
+ meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
+ meta:set_float("src_time", meta:get_float("src_time") + furnacedef.cook_speed)
+ if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
+ -- check if there's room for output in "dst" list
+ if inv:room_for_item("dst",cooked.item) then
+ -- Put result in "dst" list
+ inv:add_item("dst", cooked.item)
+ -- take stuff from "src" list
+ inv:set_stack("src", 1, aftercooked.items[1])
+ end
+ meta:set_string("src_time", 0)
+ end
+ end
+
+ -- XXX: Quick patch, make it better in the future.
+ local locked = node.name:find("_locked$") and "_locked" or ""
+ local desc = minetest.registered_nodes[nname..locked].description
+
+ if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
+ local percent = math.floor(meta:get_float("fuel_time") /
+ meta:get_float("fuel_totaltime") * 100)
+ meta:set_string("infotext", S("@1 (active: @2%)", desc, percent))
+ swap_node(pos,name_active..locked)
+ meta:set_string("formspec", make_formspec(furnacedef, percent))
+ return
+ end
+
+ local fuel = nil
+ local afterfuel
+ cooked = nil
+ local fuellist = inv:get_list("fuel")
+ srclist = inv:get_list("src")
+
+ if srclist then
+ cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
+ end
+ if fuellist then
+ fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
+ end
+
+ if (not fuel) or (fuel.time <= 0) then
+ meta:set_string("infotext", S("@1 (out of fuel)", desc))
+ swap_node(pos, nname..locked)
+ meta:set_string("formspec", make_formspec(furnacedef, 0))
+ return
+ end
+
+ if cooked.item:is_empty() then
+ if was_active then
+ meta:set_string("infotext", S("@1 (empty)", desc))
+ swap_node(pos, nname..locked)
+ meta:set_string("formspec", make_formspec(furnacedef, 0))
+ end
+ return
+ end
+
+ if not inv:room_for_item("dst", cooked.item) then
+ meta:set_string("infotext", S("@1 (output bins are full)", desc))
+ swap_node(pos, nname..locked)
+ meta:set_string("formspec", make_formspec(furnacedef, 0))
+ return
+ end
+
+ meta:set_string("fuel_totaltime", fuel.time)
+ meta:set_string("fuel_time", 0)
+
+ inv:set_stack("fuel", 1, afterfuel.items[1])
+ end,
+ })
+
+end