diff --git a/mods/ITEMS/mcl_core/textures/crafting_inventory_furnace.png b/mods/ITEMS/mcl_core/textures/crafting_inventory_furnace.png deleted file mode 100644 index e80c3c9b69..0000000000 Binary files a/mods/ITEMS/mcl_core/textures/crafting_inventory_furnace.png and /dev/null differ diff --git a/mods/ITEMS/mcl_core/textures/crafting_inventory_furnace_on.png b/mods/ITEMS/mcl_core/textures/crafting_inventory_furnace_on.png deleted file mode 100644 index 80d3e26f4e..0000000000 Binary files a/mods/ITEMS/mcl_core/textures/crafting_inventory_furnace_on.png and /dev/null differ diff --git a/mods/ITEMS/mcl_furnaces/README.md b/mods/ITEMS/mcl_furnaces/README.md new file mode 100644 index 0000000000..7bdcae469a --- /dev/null +++ b/mods/ITEMS/mcl_furnaces/README.md @@ -0,0 +1,12 @@ +Furnaces for MineClone 2. +Heavily based on Minetest Game (default/furnace.lua). + +License of source code +---------------------- +LGPLv2.1 +Based on code from Minetest Game. +Modified by Wuzzy. + +License of media +---------------- +MIT License diff --git a/mods/ITEMS/mcl_furnaces/init.lua b/mods/ITEMS/mcl_furnaces/init.lua index a7a5eff91d..75d068aa9e 100644 --- a/mods/ITEMS/mcl_furnaces/init.lua +++ b/mods/ITEMS/mcl_furnaces/init.lua @@ -1,6 +1,33 @@ -local furnace_inactive_formspec = - "size[9,8.75]".. - "background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png^crafting_inventory_furnace.png]".. + +-- +-- Formspecs +-- + +local function active_formspec(fuel_percent, item_percent) + return "size[9,8.75]".. + "background[-0.19,-0.25;9.41,9.49;mcl_furnaces_formspec.png]".. + mcl_vars.inventory_header.. + "list[current_player;main;0,4.5;9,3;9]".. + "list[current_player;main;0,7.74;9,1;]".. + "list[current_name;src;2.75,0.5;1,1;]".. + "list[current_name;fuel;2.75,2.5;1,1;]".. + "list[current_name;dst;5.75,1.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:".. + (100-fuel_percent)..":default_furnace_fire_fg.png]".. + "image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[lowpart:".. + (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]".. + "image_button[8,0;1,1;craftguide_book.png;__mcl_craftguide;]".. + "tooltip[__mcl_craftguide;Show crafting recipes]".. + "listring[current_name;dst]".. + "listring[current_player;main]".. + "listring[current_name;src]".. + "listring[current_player;main]".. + "listring[current_name;fuel]".. + "listring[current_player;main]" +end + +local inactive_formspec = "size[9,8.75]".. + "background[-0.19,-0.25;9.41,9.49;mcl_furnaces_formspec.png]".. mcl_vars.inventory_header.. "list[current_player;main;0,4.5;9,3;9]".. "list[current_player;main;0,7.74;9,1;]".. @@ -8,6 +35,7 @@ local furnace_inactive_formspec = "list[current_name;fuel;2.75,2.5;1,1;]".. "list[current_name;dst;5.75,1.5;1,1;]".. "image[2.75,1.5;1,1;default_furnace_fire_bg.png]".. + "image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[transformR270]".. "image_button[8,0;1,1;craftguide_book.png;__mcl_craftguide;]".. "tooltip[__mcl_craftguide;Show crafting recipes]".. "listring[current_name;dst]".. @@ -23,23 +51,184 @@ local craftguide = function(pos, formname, fields, sender) end end +-- +-- Node callback functions that are the same for active and inactive furnace +-- + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + 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 + 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 function allow_metadata_inventory_move(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) + return allow_metadata_inventory_put(pos, to_list, to_index, stack, player) +end + +local function allow_metadata_inventory_take(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() +end + +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 furnace_node_timer(pos, elapsed) + -- + -- Inizialize metadata + -- + local meta = minetest.get_meta(pos) + local fuel_time = meta:get_float("fuel_time") or 0 + local src_time = meta:get_float("src_time") or 0 + local fuel_totaltime = meta:get_float("fuel_totaltime") or 0 + + local inv = meta:get_inventory() + local srclist, fuellist + + local cookable, cooked + local fuel + + local update = true + while update do + update = false + + srclist = inv:get_list("src") + fuellist = inv:get_list("fuel") + + -- + -- Cooking + -- + + -- Check if we have cookable content + local aftercooked + cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) + cookable = cooked.time ~= 0 + + -- Check if we have enough fuel to burn + if fuel_time < fuel_totaltime then + -- The furnace is currently active and has enough fuel + fuel_time = fuel_time + elapsed + -- If there is a cookable item then check if it is ready yet + if cookable then + src_time = src_time + elapsed + if src_time >= cooked.time then + -- Place result in dst list if possible + if inv:room_for_item("dst", cooked.item) then + inv:add_item("dst", cooked.item) + inv:set_stack("src", 1, aftercooked.items[1]) + src_time = src_time - cooked.time + update = true + end + end + end + else + -- Furnace ran out of fuel + if cookable then + -- We need to get new fuel + local afterfuel + fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist}) + + if fuel.time == 0 then + -- No valid fuel in fuel list + fuel_totaltime = 0 + src_time = 0 + else + -- Take fuel from fuel list + inv:set_stack("fuel", 1, afterfuel.items[1]) + update = true + fuel_totaltime = fuel.time + (fuel_time - fuel_totaltime) + src_time = src_time + elapsed + end + else + -- We don't need to get new fuel since there is no cookable item + fuel_totaltime = 0 + src_time = 0 + end + fuel_time = 0 + end + + elapsed = 0 + end + + if fuel and fuel_totaltime > fuel.time then + fuel_totaltime = fuel.time + end + if srclist[1]:is_empty() then + src_time = 0 + end + + -- + -- Update formspec and node + -- + local formspec = inactive_formspec + local item_state + local item_percent = 0 + if cookable then + item_percent = math.floor(src_time / cooked.time * 100) + end + + local result = false + + if fuel_totaltime ~= 0 then + local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100) + formspec = active_formspec(fuel_percent, item_percent) + swap_node(pos, "mcl_furnaces:furnace_active") + -- make sure timer restarts automatically + result = true + else + swap_node(pos, "mcl_furnaces:furnace") + -- stop timer on the inactive furnace + minetest.get_node_timer(pos):stop() + end + + -- + -- Set meta values + -- + meta:set_float("fuel_totaltime", fuel_totaltime) + meta:set_float("fuel_time", fuel_time) + meta:set_float("src_time", src_time) + meta:set_string("formspec", formspec) + + return result +end + minetest.register_node("mcl_furnaces:furnace", { description = "Furnace", - tiles = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png", - "default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"}, + tiles = { + "default_furnace_top.png", "default_furnace_bottom.png", + "default_furnace_side.png", "default_furnace_side.png", + "default_furnace_side.png", "default_furnace_front.png" + }, paramtype2 = "facedir", - is_ground_content = false, - stack_max = 64, groups = {cracky=2, container=4, deco_block=1}, + is_ground_content = false, sounds = mcl_sounds.node_sound_stone_defaults(), - on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec", furnace_inactive_formspec) - local inv = meta:get_inventory() - inv:set_size("fuel", 1) - inv:set_size("src", 1) - inv:set_size("dst", 1) - end, + + on_timer = furnace_node_timer, after_dig_node = function(pos, oldnode, oldmetadata, digger) local meta = minetest.get_meta(pos) local meta2 = meta @@ -54,58 +243,45 @@ minetest.register_node("mcl_furnaces:furnace", { end meta:from_table(meta2:to_table()) end, - allow_metadata_inventory_put = function(pos, listname, index, stack, player) + + on_construct = function(pos) local meta = minetest.get_meta(pos) + meta:set_string("formspec", inactive_formspec) local inv = meta:get_inventory() - if listname == "fuel" then - if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then - return stack:get_count() - else - return 0 - end - elseif listname == "src" then - return stack:get_count() - elseif listname == "dst" then - return 0 - end + inv:set_size('src', 1) + inv:set_size('fuel', 1) + inv:set_size('dst', 1) end, - allow_metadata_inventory_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 - return count - else - return 0 - end - elseif to_list == "src" then - return count - elseif to_list == "dst" then - return 0 - end + + on_metadata_inventory_move = function(pos) + minetest.get_node_timer(pos):start(1.0) end, + on_metadata_inventory_put = function(pos) + -- start timer function, it will sort out whether furnace can burn or not. + minetest.get_node_timer(pos):start(1.0) + end, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, on_receive_fields = craftguide, }) minetest.register_node("mcl_furnaces:furnace_active", { description = "Furnace", - tiles = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png", - "default_furnace_side.png", "default_furnace_side.png", "default_furnace_front_active.png"}, + tiles = { + "default_furnace_top.png", "default_furnace_bottom.png", + "default_furnace_side.png", "default_furnace_side.png", + "default_furnace_side.png", "default_furnace_front_active.png", + }, paramtype2 = "facedir", - is_ground_content = false, light_source = 13, drop = "mcl_furnaces:furnace", - groups = {cracky=2, container=4, not_in_creative_inventory=1}, + groups = {cracky=2, container=4, deco_block=1, not_in_creative_inventory=1}, + is_ground_content = false, sounds = mcl_sounds.node_sound_stone_defaults(), - on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec", furnace_inactive_formspec) - local inv = meta:get_inventory() - inv:set_size("fuel", 1) - inv:set_size("src", 1) - inv:set_size("dst", 1) - end, + on_timer = furnace_node_timer, + after_dig_node = function(pos, oldnode, oldmetadata, digger) local meta = minetest.get_meta(pos) local meta2 = meta @@ -120,153 +296,11 @@ minetest.register_node("mcl_furnaces:furnace_active", { end meta:from_table(meta2:to_table()) end, - allow_metadata_inventory_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 - return stack:get_count() - else - return 0 - end - elseif listname == "src" then - return stack:get_count() - elseif listname == "dst" then - return 0 - end - end, - allow_metadata_inventory_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 - return count - else - return 0 - end - elseif to_list == "src" then - return count - elseif to_list == "dst" then - return 0 - end - end, + + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, on_receive_fields = craftguide, }) -minetest.register_abm({ - nodenames = {"mcl_furnaces:furnace","mcl_furnaces:furnace_active"}, - interval = 1.0, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - local meta = minetest.get_meta(pos) - for i, name in ipairs({ - "fuel_totaltime", - "fuel_time", - "src_totaltime", - "src_time" - }) do - if meta:get_string(name) == "" then - meta:set_float(name, 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") + 1) - 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]) - else - print("Could not insert '"..cooked.item:to_string().."'") - end - meta:set_string("src_time", 0) - end - end - - 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) - minetest.swap_node(pos, { name = "mcl_furnaces:furnace_active", param = node.param, param2 = node.param2 }) - meta:set_string("formspec", - "size[9,8.75]".. - "background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png^crafting_inventory_furnace.png]".. - mcl_vars.inventory_header.. - "list[current_player;main;0,4.5;9,3;9]".. - "list[current_player;main;0,7.74;9,1;]".. - "list[current_name;src;2.75,0.5;1,1;]".. - "list[current_name;fuel;2.75,2.5;1,1;]".. - "list[current_name;dst;5.75,1.5;1,1;]".. - "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:".. - (100-percent)..":default_furnace_fire_fg.png]".. - "image_button[8,0;1,1;craftguide_book.png;__mcl_craftguide;]".. - "tooltip[__mcl_craftguide;Show crafting recipes]".. - "listring[current_name;dst]".. - "listring[current_player;main]".. - "listring[current_name;src]".. - "listring[current_player;main]".. - "listring[current_name;fuel]".. - "listring[current_player;main]") - return - end - - local fuel = nil - local afterfuel - local cooked = nil - local fuellist = inv:get_list("fuel") - local 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 fuel.time <= 0 then - minetest.swap_node(pos, { name = "mcl_furnaces:furnace", param = node.param, param2 = node.param2 }) - meta:set_string("formspec", furnace_inactive_formspec) - return - end - - if cooked.item:is_empty() then - if was_active then - minetest.swap_node(pos, { name = "mcl_furnaces:furnace", param = node.param, param2 = node.param2 }) - meta:set_string("formspec", furnace_inactive_formspec) - end - return - end - - meta:set_string("fuel_totaltime", fuel.time) - meta:set_string("fuel_time", 0) - - inv:set_stack("fuel", 1, afterfuel.items[1]) - end, -}) - -minetest.register_craft({ - output = 'mcl_furnaces:furnace', - recipe = { - {'mcl_core:cobble', 'mcl_core:cobble', 'mcl_core:cobble'}, - {'mcl_core:cobble', '', 'mcl_core:cobble'}, - {'mcl_core:cobble', 'mcl_core:cobble', 'mcl_core:cobble'}, - } -}) - diff --git a/mods/ITEMS/mcl_furnaces/textures/default_furnace_bg.png b/mods/ITEMS/mcl_furnaces/textures/default_furnace_bg.png deleted file mode 100644 index a538893296..0000000000 Binary files a/mods/ITEMS/mcl_furnaces/textures/default_furnace_bg.png and /dev/null differ diff --git a/mods/ITEMS/mcl_furnaces/textures/gui_furnace_arrow_bg.png b/mods/ITEMS/mcl_furnaces/textures/gui_furnace_arrow_bg.png new file mode 100644 index 0000000000..587685717c Binary files /dev/null and b/mods/ITEMS/mcl_furnaces/textures/gui_furnace_arrow_bg.png differ diff --git a/mods/ITEMS/mcl_furnaces/textures/gui_furnace_arrow_fg.png b/mods/ITEMS/mcl_furnaces/textures/gui_furnace_arrow_fg.png new file mode 100644 index 0000000000..7a9ec4e5ea Binary files /dev/null and b/mods/ITEMS/mcl_furnaces/textures/gui_furnace_arrow_fg.png differ diff --git a/mods/ITEMS/mcl_furnaces/textures/mcl_furnaces_formspec.png b/mods/ITEMS/mcl_furnaces/textures/mcl_furnaces_formspec.png new file mode 100644 index 0000000000..f8191ffd22 Binary files /dev/null and b/mods/ITEMS/mcl_furnaces/textures/mcl_furnaces_formspec.png differ