X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=mods%2Futility%2Ffurnace.lua;h=5b235b96b5a3be7ea4f7b5d5c4f7da64a4246272;hb=e6c681a065465530bd513029432dce11e763cb4b;hp=875c373856d884ef55699f72457b8eeb4608d520;hpb=dc16f18f9c8312539f30bb413baa10db452b669d;p=Crafter.git diff --git a/mods/utility/furnace.lua b/mods/utility/furnace.lua index 875c373..5b235b9 100644 --- a/mods/utility/furnace.lua +++ b/mods/utility/furnace.lua @@ -1,806 +1,390 @@ ---[[ -Mechanic ideology - -spawn 3 entities - cook fuel output - -detect on x or z axis - -use recipe cook time - -then pass output to cooked entity - -when player hits entity then drop item towards player - -when cooking have fire and smoke on cooking item - -]]-- - ---furnace class -minetest.register_craftitem("utility:nothing", { - description = "Nothing", - inventory_image = "wood.png", -}) - local furnace = {} ---gap = 0.55 -local fuel_height = 0.75 -local cook_height = 1.3 -local output_height = 1.85 - ---furnace -function furnace.get_hotbar_bg(x,y) - local out = "" - for i=0,7,1 do - out = out .."image["..x+i..","..y..";1,1;gui_furnace_arrow_bg.png]" - end - return(out) + +function furnace.get_furnace_active_formspec(fuel_percent, item_percent) + return "size[9,8.75]".. + "background[-0.19,-0.25;9.41,9.49;gui_hb_bg.png]".. + "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]".. + "list[context;src;2.75,0.5;1,1;]".. + "list[context;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:".. + (fuel_percent)..":default_furnace_fire_fg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:".. + (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]".. + "list[context;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.5;9,1;]".. --hotbar + "list[current_player;main;0,6;9,3;9]".. --inventory + + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + "listring[context;fuel]".. + "listring[current_player;main]" + --furnace.get_hotbar_bg(0, 4.25) end -function furnace.get_inventory_drops(pos, inventory, drops) - local inv = minetest.get_meta(pos):get_inventory() - local n = #drops - for i = 1, inv:get_size(inventory) do - local stack = inv:get_stack(inventory, i) - if stack:get_count() > 0 then - drops[n+1] = stack:to_table() - n = n + 1 - end - end +function furnace.get_furnace_inactive_formspec() + return "size[9,8.75]".. + "background[-0.19,-0.25;9.41,9.49;gui_hb_bg.png]".. + "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]".. + "list[context;src;2.75,0.5;1,1;]".. + "list[context;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]".. + "list[context;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.5;9,1;]".. + "list[current_player;main;0,6;9,3;9]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + "listring[context;fuel]".. + "listring[current_player;main]" + --furnace.get_hotbar_bg(0, 4.25) end ---local aftercooked ---cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) ---cookable = cooked.time ~= 0 + -- --- Node definitions +-- Node callback functions that are the same for active and inactive furnace -- -local function furnace_setup(pos) - local obj = minetest.add_entity(vector.new(pos.x,pos.y+fuel_height,pos.z), "utility:fuel") - obj:get_luaentity().set_item(obj:get_luaentity(),"utility:nothing") - local obj = minetest.add_entity(vector.new(pos.x,pos.y+cook_height,pos.z), "utility:cook") - obj:get_luaentity().set_item(obj:get_luaentity(),"utility:nothing") - local obj = minetest.add_entity(vector.new(pos.x,pos.y+output_height,pos.z), "utility:output") - obj:get_luaentity().set_item(obj:get_luaentity(),"utility:nothing") +--[[ +local function can_dig(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 +]]-- -local function furnace_remove(pos) - for _,object in ipairs(minetest.get_objects_inside_radius(vector.new(pos.x,pos.y+fuel_height,pos.z), 0.1)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "utility:fuel" then - local pos = object:getpos() - local item = object:get_luaentity().itemstring - if item ~= "utility:nothing" then - local obj = minetest.add_item(pos,item) - obj:get_luaentity().collection_timer = 2 - end - object:remove() - end - end - for _,object in ipairs(minetest.get_objects_inside_radius(vector.new(pos.x,pos.y+cook_height,pos.z), 0.1)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "utility:cook" then - local pos = object:getpos() - local item = object:get_luaentity().itemstring - if item ~= "utility:nothing" then - local obj = minetest.add_item(pos,item) - obj:get_luaentity().collection_timer = 2 - end - object:remove() - end +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 end - for _,object in ipairs(minetest.get_objects_inside_radius(vector.new(pos.x,pos.y+output_height,pos.z), 0.1)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "utility:output" then - local pos = object:getpos() - local item = object:get_luaentity().itemstring - if item ~= "utility:nothing" then - local obj = minetest.add_item(pos,item) - obj:get_luaentity().collection_timer = 2 - end - object:remove() + 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", "Furnace is empty") + --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 -minetest.register_node("utility:furnace", { - description = "Furnace", - tiles = { - "furnace_top.png", "furnace_bottom.png", - "furnace_side.png", "furnace_side.png", - "furnace_side.png", "furnace_front.png" - }, - paramtype2 = "facedir", - groups = {stone=2}, - legacy_facedir_simple = true, - is_ground_content = false, - sounds = main.stoneSound(), - on_construct = function(pos) - furnace_setup(pos) - end, - on_destruct = function(pos) - furnace_remove(pos) - end, -}) - -minetest.register_craft({ - output = "utility:furnace", - recipe = { - {"main:stone", "main:stone", "main:stone"}, - {"main:stone", "", "main:stone"}, - {"main:stone", "main:stone", "main:stone"}, - } -}) - --------------------------------------------------------------------------------------------------- ---[[ - -minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) --check if cookable - -minetest.get_craft_result({method = "fuel", width = 1, items = fuellist}) --check if fuel - -space in between = 0.55 - -]]-- - - ---fuel entity -minetest.register_entity("utility:fuel", { - initial_properties = { - hp_max = 1, - physical = true, - collide_with_objects = false, - collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3}, - visual = "wielditem", - visual_size = {x = 0.6, y = 0.6}, - textures = {""}, - spritediv = {x = 1, y = 1}, - initial_sprite_basepos = {x = 0, y = 0}, - is_visible = false, - pointable = true, - }, +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 - itemstring = "", - count = 0, - cooking = false, - cook_timer = false, - fuel_timer = 0, - - set_item = function(self, item) - local stack = ItemStack(item or self.itemstring) - self.itemstring = stack:to_string() - --if self.itemstring == "" then - -- item not yet known - -- return - --end - - local count = stack:get_count() - self.count = count - - -- Backwards compatibility: old clients use the texture - -- to get the type of the item - local itemname = stack:is_known() and stack:get_name() or "unknown" - - local max_count = stack:get_stack_max() - local size = 0.25 - local coll_height = size * 0.75 - local def = minetest.registered_nodes[itemname] - --local glow = def and def.light_source - - self.object:set_properties({ - is_visible = true, - visual = "wielditem", - textures = {itemname}, - visual_size = {x = size, y = size}, - --collisionbox = {-size, -coll_height, -size, - -- size, coll_height, size}, - selectionbox = {-size, -size, -size, size, size, size}, - automatic_rotate = math.pi * 0.5 * 0.2 / size, - wield_item = self.itemstring, - glow = glow, - }) - 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 - get_staticdata = function(self) - return minetest.serialize({ - itemstring = self.itemstring, - count = self.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 - on_activate = function(self, staticdata, dtime_s) - if string.sub(staticdata, 1, string.len("return")) == "return" then - local data = minetest.deserialize(staticdata) - if data and type(data) == "table" then - self.itemstring = data.itemstring - self.count = data.count - end - else - self.itemstring = staticdata - end - self.object:set_armor_groups({immortal = 1}) - self.object:set_velocity({x = 0, y = 0, z = 0}) - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self:set_item() - end, - - on_rightclick = function(self, clicker) - - if not clicker or not clicker:is_player() then - return - end - - local stack = clicker:get_wielded_item() - - local item = stack:get_name() - local count = stack:get_count() - if stack:get_name() == "utility:nothing" then - count = 0 - end - - --shoot out existing item - if self.itemstring ~= item.." "..count and self.itemstring ~= "utility:nothing" then - local pos = self.object:getpos() - local pos2 = clicker:getpos() - pos2.y = pos2.y + 1.25 - local obj = minetest.add_item(pos,self.itemstring) - local dir = vector.subtract(pos2,pos) - vector.multiply(dir,5) - - if obj then - obj:setvelocity(vector.new(dir.x,dir.y+3.5,dir.z)) - obj:get_luaentity().collection_timer = 2 - else - print("ERROR FURNACE RELEASED NON ITEM") - end - end - - if (item == "" or item == "hand:player") then - self.set_item(self,"utility:nothing") - self.object:set_nametag_attributes({ - color = "red", - text = "", - }) - return - end - - self.set_item(self, item.." "..count) - - self.object:set_nametag_attributes({ - color = "red", - text = minetest.registered_items[item].description.." "..count, - }) - - stack = stack:clear() - clicker:set_wielded_item("") - end, - - on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir) - if not puncher or not puncher:is_player() then - return - end - - if self.itemstring == "utility:nothing" then - return - end - - local pos = self.object:getpos() - local pos2 = puncher:getpos() - pos2.y = pos2.y + 1.25 - - local obj = minetest.add_item(pos,self.itemstring) - local dir = vector.subtract(pos2,pos) - vector.multiply(dir,5) - - self.set_item(self,"utility:nothing") - self.object:set_nametag_attributes({ - color = "red", - text = "", - }) - - if obj then - obj:setvelocity(vector.new(dir.x,dir.y+3.5,dir.z)) - obj:get_luaentity().collection_timer = 2 - else - print("ERROR FURNACE RELEASED NON ITEM") +local function furnace_node_timer(pos, elapsed) + -- + -- Initialize 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 dst_full = false + + local cookable, cooked + local fuel + + local update = true + while elapsed > 0 and 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 + + local el = math.min(elapsed, fuel_totaltime - fuel_time) + if cookable then -- fuel lasts long enough, adjust el to cooking duration + el = math.min(el, cooked.time - src_time) end - end, - check_cook = function(self) - local pos = self.object:getpos() - --check the cook timer - for _,object in ipairs(minetest.get_objects_inside_radius(vector.new(pos.x,pos.y+0.55,pos.z), 0.1)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "utility:cook" then - local item = object:get_luaentity().itemstring - return(minetest.get_craft_result({method = "cooking", width = 1, items = {ItemStack(item)}}).time) - end - end - end, - - cook_item = function(self) - local pos = self.object:getpos() - for _,object in ipairs(minetest.get_objects_inside_radius(vector.new(pos.x,pos.y+0.55,pos.z), 0.1)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "utility:cook" then - local item = ItemStack(object:get_luaentity().itemstring) - if not item then - return - end - local count = object:get_luaentity().count - local output = minetest.get_craft_result({method = "cooking", width = 1, items = {ItemStack(item)}}).item - local outputitem = output:get_name() - local outputcount = output:get_count() - - - local itemname = item:get_name() - - count = count - 1 - - object:get_luaentity().count = count - - local pos = self.object:getpos() - - --add to output - for _,object2 in ipairs(minetest.get_objects_inside_radius(vector.new(pos.x,pos.y+1.10,pos.z), 0.1)) do - if not object2:is_player() and object2:get_luaentity() and object2:get_luaentity().name == "utility:output" then - local goal_item = ItemStack(object2:get_luaentity().itemstring) - local goal_item_name = goal_item:get_name() - local goal_item_count = goal_item:get_count() - - --cancel out if player took item - if outputitem == "" then - return - end - - --add item to output or throw existing item out if not matched - if goal_item_name ~= outputitem and goal_item_name ~= "utility:nothing" then - local pos2 = object2:get_pos() - local obj = minetest.add_item(pos2,object2:get_luaentity().itemstring) - local dir = vector.new(math.random(-3,3),math.random(3,6),math.random(-3,3)) - --dir = vector.multiply(dir,2) - - if obj then - obj:setvelocity(vector.new(dir.x,dir.y,dir.z)) - obj:get_luaentity().collection_timer = 2 - else - print("ERROR FURNACE RELEASED NON ITEM") - end - object2:get_luaentity().count = 0 - end - - object2:get_luaentity().count = object2:get_luaentity().count + outputcount - object2:get_luaentity().set_item(object2:get_luaentity(), outputitem.." "..object2:get_luaentity().count) - object2:set_nametag_attributes({ - color = "blue", - text = outputitem.." "..object2:get_luaentity().count, - }) - + -- 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 + el + -- If there is a cookable item then check if it is ready yet + if cookable then + src_time = src_time + el + 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 + else + dst_full = true end - end - - --update count and nametag - if object:get_luaentity().count == 0 then - object:get_luaentity().set_item(object:get_luaentity(), "utility:nothing") - object:set_nametag_attributes({ - color = "blue", - text = "", - }) else - object:get_luaentity().set_item(object:get_luaentity(), itemname.." "..count) - object:set_nametag_attributes({ - color = "blue", - text = itemname.." "..count, - }) + -- Item could not be cooked: probably missing fuel + update = true end end - end - end, - - spawn_particles = function(self,time) - --print("time:"..time) - local pos = self.object:getpos() - minetest.add_particlespawner({ - amount = math.floor(100*time), - time = time, - minpos = vector.new(pos.x-0.3,pos.y-0.3,pos.z-0.3), - maxpos = vector.new(pos.x+0.3,pos.y+0.3,pos.z+0.3), - minvel = {x=0, y=0.2, z=0}, - maxvel = {x=0, y=0.7, z=0}, - minacc = {x=0, y=0, z=0}, - maxacc = {x=0, y=0, z=0}, - minexptime = 1.1, - maxexptime = 1.5, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = true, - texture = "flame.png", - }) - - - minetest.add_particlespawner({ - amount = math.floor(50*time), - time = time, - minpos = vector.new(pos.x-0.3,pos.y+0.3,pos.z-0.3), - maxpos = vector.new(pos.x+0.3,pos.y+0.6,pos.z+0.3), - minvel = {x=0, y=0.2, z=0}, - maxvel = {x=0, y=0.7, z=0}, - minacc = {x=0, y=0, z=0}, - maxacc = {x=0, y=0, z=0}, - minexptime = 1.1, - maxexptime = 1.5, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "smoke.png", - }) - end, - - - - --check if item is in the input then cook if so - on_step = function(self, dtime) - if self.cooking == true then - self.cooking_timer = self.cooking_timer - dtime - if self.cooking_timer < 0 then - self.cooking_timer = 0 - self.cook_item(self) - self.cooking = false - end - end - - --check to start cooking countdown - if self.cooking == false then - local stack = ItemStack(self.itemstring) - local fuel = minetest.get_craft_result({method = "fuel", width = 1, items = {stack}}).time - if fuel ~= 0 then - local cookie = self.check_cook(self) - if cookie ~= 0 then - --print("starting timer") - self.spawn_particles(self,fuel) - self.cooking_timer = cookie - self.cooking = true - --set up the fuel timer - if self.fuel_timer == 0 then - self.fuel_timer = fuel + 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]) + -- Put replacements in dst list or drop them on the furnace. + local replacements = fuel.replacements + if replacements[1] then + local leftover = inv:add_item("dst", replacements[1]) + if not leftover:is_empty() then + local above = vector.new(pos.x, pos.y + 1, pos.z) + local drop_pos = minetest.find_node_near(above, 1, {"air"}) or above + minetest.item_drop(replacements[1], nil, drop_pos) + end end + update = true + fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time) end - end - end - - --deplete fuel - if self.fuel_timer >= 0 then - self.fuel_timer = self.fuel_timer - dtime - --print(self.fuel_timer) - elseif self.fuel_timer < 0 then - if ItemStack(self.itemstring):get_name() == "utility:nothing" then - return - end - if self.cooking == false then - return - end - self.count = self.count - 1 - - local count = self.count - local itemname = ItemStack(self.itemstring):get_name() - - if self.count == 0 then - self.set_item(self, "utility:nothing") - self.object:set_nametag_attributes({ - color = "red", - text = "", - }) else - self.set_item(self, itemname.." "..count) - self.object:set_nametag_attributes({ - color = "red", - text = itemname.." "..count, - }) - end - - if self.count == 0 then - return - end - - --reset timer - if self.cooking == true then - --print("resetting timer") - local time = minetest.get_craft_result({method = "fuel", width = 1, items = {ItemStack(self.itemstring)}}).time - self.fuel_timer = time + -- 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 - end, -}) - ----------------------------------------------------------------------------- ---cook entity -minetest.register_entity("utility:cook", { - initial_properties = { - hp_max = 1, - physical = true, - collide_with_objects = false, - collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3}, - visual = "wielditem", - visual_size = {x = 0.6, y = 0.6}, - textures = {""}, - spritediv = {x = 1, y = 1}, - initial_sprite_basepos = {x = 0, y = 0}, - is_visible = false, - pointable = true, - }, - - itemstring = "", - count = 0, - set_item = function(self, item) - local stack = ItemStack(item or self.itemstring) - self.itemstring = stack:to_string() - --if self.itemstring == "" then - -- item not yet known - -- return - --end - - local count = stack:get_count() - if stack:get_name() == "utility:nothing" then - count = 0 - end - self.count = count - - -- Backwards compatibility: old clients use the texture - -- to get the type of the item - local itemname = stack:is_known() and stack:get_name() or "unknown" - - local max_count = stack:get_stack_max() - local size = 0.25 - local coll_height = size * 0.75 - local def = minetest.registered_nodes[itemname] - --local glow = def and def.light_source - - self.object:set_properties({ - is_visible = true, - visual = "wielditem", - textures = {itemname}, - visual_size = {x = size, y = size}, - --collisionbox = {-size, -coll_height, -size, - -- size, coll_height, size}, - selectionbox = {-size, -size, -size, size, size, size}, - automatic_rotate = math.pi * 0.5 * 0.2 / size, - wield_item = self.itemstring, - glow = glow, - }) - end, + elapsed = elapsed - el + end - get_staticdata = function(self) - return minetest.serialize({ - itemstring = self.itemstring, - count = self.count, - }) - end, + if fuel and fuel_totaltime > fuel.time then + fuel_totaltime = fuel.time + end + if srclist and srclist[1]:is_empty() then + src_time = 0 + end - on_activate = function(self, staticdata, dtime_s) - if string.sub(staticdata, 1, string.len("return")) == "return" then - local data = minetest.deserialize(staticdata) - if data and type(data) == "table" then - self.itemstring = data.itemstring - self.count = data.count - end + -- + -- Update formspec, infotext and node + -- + local formspec + local item_state + local item_percent = 0 + if cookable then + item_percent = math.floor(src_time / cooked.time * 100) + if dst_full then + item_state = ("100% (output full)") else - self.itemstring = staticdata - end - self.object:set_armor_groups({immortal = 1}) - self.object:set_velocity({x = 0, y = 0, z = 0}) - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self:set_item() - end, - - on_rightclick = function(self, clicker) - - if not clicker or not clicker:is_player() then - return + item_state = (item_percent) end - - local stack = clicker:get_wielded_item() - - local item = stack:get_name() - local count = stack:get_count() - - --shoot out existing item - if self.itemstring ~= item.." "..count and self.itemstring ~= "utility:nothing" then - local pos = self.object:getpos() - local pos2 = clicker:getpos() - pos2.y = pos2.y + 1.25 - local obj = minetest.add_item(pos,self.itemstring) - local dir = vector.subtract(pos2,pos) - vector.multiply(dir,5) - - if obj then - obj:setvelocity(vector.new(dir.x,dir.y+3.5,dir.z)) - obj:get_luaentity().collection_timer = 2 - else - print("ERROR FURNACE RELEASED NON ITEM") - end - end - - if (item == "" or item == "hand:player") then - self.set_item(self,"utility:nothing") - self.object:set_nametag_attributes({ - color = "blue", - text = "", - }) - return - end - - self.set_item(self, item.." "..count) - - self.object:set_nametag_attributes({ - color = "blue", - text = minetest.registered_items[item].description.." "..count, - }) - - stack = stack:clear() - clicker:set_wielded_item("") - end, - - on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir) - if not puncher or not puncher:is_player() then - return + else + if srclist and not srclist[1]:is_empty() then + item_state = ("Not cookable") + else + item_state = ("Empty") end - - if self.itemstring == "utility:nothing" then - return + end + + local fuel_state = ("Empty") + local active = false + local result = false + + if fuel_totaltime ~= 0 then + active = true + local fuel_percent = 100 - math.floor(fuel_time / fuel_totaltime * 100) + fuel_state = (fuel_percent) + formspec = furnace.get_furnace_active_formspec(fuel_percent, item_percent) + swap_node(pos, "utility:furnace_active") + -- make sure timer restarts automatically + result = true + else + if fuellist and not fuellist[1]:is_empty() then + fuel_state = (0) end - - local pos = self.object:getpos() - local pos2 = puncher:getpos() - pos2.y = pos2.y + 1.25 - - local obj = minetest.add_item(pos,self.itemstring) - local dir = vector.subtract(pos2,pos) - vector.multiply(dir,5) - - self.set_item(self,"utility:nothing") - self.object:set_nametag_attributes({ - color = "blue", - text = "", - }) - - if obj then - obj:setvelocity(vector.new(dir.x,dir.y+3.5,dir.z)) - obj:get_luaentity().collection_timer = 2 - else - print("ERROR FURNACE RELEASED NON ITEM") + formspec = furnace.get_furnace_inactive_formspec() + swap_node(pos, "utility:furnace") + -- stop timer on the inactive furnace + minetest.get_node_timer(pos):stop() + end + + + --[[ + local infotext + if active then + infotext = ("Furnace active") + else + infotext = ("Furnace inactive") + end + infotext = infotext .. "\n" .. "Item:"..item_state.. "Fuel:"..fuel_state + ]]-- + -- + -- 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) + --meta:set_string("infotext", infotext) + + return result +end +--throw all items in furnace out on destroy +local function destroy_furnace(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local lists = inv:get_lists() + for listname,_ in pairs(lists) do + local size = inv:get_size(listname) + for i = 1,size do + local stack = inv:get_stack(listname, i) + minetest.add_item(pos, stack) end - end, + end +end +-- +-- Node definitions +-- - on_step = function(self, dtime) - --set glow if cooking - --local glow = def and def.light_source - end, -}) ----------------------------------------------------------------------------- ---ouput entity -minetest.register_entity("utility:output", { - initial_properties = { - hp_max = 1, - physical = true, - collide_with_objects = false, - collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3}, - visual = "wielditem", - visual_size = {x = 0.6, y = 0.6}, - textures = {""}, - spritediv = {x = 1, y = 1}, - initial_sprite_basepos = {x = 0, y = 0}, - is_visible = false, - pointable = true, +minetest.register_node("utility:furnace", { + description = ("Furnace"), + tiles = { + "furnace_top.png", "furnace_bottom.png", + "furnace_side.png", "furnace_side.png", + "furnace_side.png", "furnace_front.png" }, + paramtype2 = "facedir", + groups = {stone=2}, + legacy_facedir_simple = true, + is_ground_content = false, + sounds = main.stoneSound(), - itemstring = "", - count = 0, + --can_dig = can_dig, - set_item = function(self, item) - local stack = ItemStack(item or self.itemstring) - self.itemstring = stack:to_string() - --if self.itemstring == "" then - -- item not yet known - -- return - --end - - local count = stack:get_count() - if stack:get_name() == "utility:nothing" then - count = 0 - end - self.count = count - - -- Backwards compatibility: old clients use the texture - -- to get the type of the item - local itemname = stack:is_known() and stack:get_name() or "unknown" - - local max_count = stack:get_stack_max() - local size = 0.25 - local coll_height = size * 0.75 - local def = minetest.registered_nodes[itemname] - --local glow = def and def.light_source - - self.object:set_properties({ - is_visible = true, - visual = "wielditem", - textures = {itemname}, - visual_size = {x = size, y = size}, - --collisionbox = {-size, -coll_height, -size, - -- size, coll_height, size}, - selectionbox = {-size, -size, -size, size, size, size}, - automatic_rotate = math.pi * 0.5 * 0.2 / size, - wield_item = self.itemstring, - glow = glow, - }) - end, + on_timer = furnace_node_timer, - get_staticdata = function(self) - return minetest.serialize({ - itemstring = self.itemstring, - count = self.count, - }) + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size('src', 1) + inv:set_size('fuel', 1) + inv:set_size('dst', 4) + furnace_node_timer(pos, 0) end, - on_activate = function(self, staticdata, dtime_s) - if string.sub(staticdata, 1, string.len("return")) == "return" then - local data = minetest.deserialize(staticdata) - if data and type(data) == "table" then - self.itemstring = data.itemstring - self.count = data.count - end - else - self.itemstring = staticdata + on_metadata_inventory_move = function(pos) + local timer = minetest.get_node_timer(pos) + if timer:is_started() == false then + timer:start(1.0) end - self.object:set_armor_groups({immortal = 1}) - self.object:set_velocity({x = 0, y = 0, z = 0}) - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self:set_item() end, - - on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir) - if not puncher or not puncher:is_player() then - return - end - - if self.itemstring == "utility:nothing" then - return - end - - self.count = 0 - - local pos = self.object:getpos() - local pos2 = puncher:getpos() - pos2.y = pos2.y + 1.25 - - local obj = minetest.add_item(pos,self.itemstring) - local dir = vector.subtract(pos2,pos) - vector.multiply(dir,5) - - self.set_item(self,"utility:nothing") - self.object:set_nametag_attributes({ - color = "blue", - text = "", - }) - - if obj then - obj:setvelocity(vector.new(dir.x,dir.y+3.5,dir.z)) - obj:get_luaentity().collection_timer = 2 - else - print("ERROR FURNACE RELEASED NON ITEM") + on_metadata_inventory_put = function(pos) + -- start timer function, it will sort out whether furnace can burn or not. + local timer = minetest.get_node_timer(pos) + if timer:is_started() == false then + timer:start(1.0) end end, + --[[ + on_blast = function(pos) + local drops = {} + furnace.get_inventory_drops(pos, "src", drops) + furnace.get_inventory_drops(pos, "fuel", drops) + furnace.get_inventory_drops(pos, "dst", drops) + drops[#drops+1] = "utility:furnace" + minetest.remove_node(pos) + return drops + end, + ]]-- + on_destruct = function(pos) + destroy_furnace(pos) + 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, +}) +minetest.register_node("utility:furnace_active", { + description = ("Furnace"), + tiles = { + "furnace_top.png", "furnace_bottom.png", + "furnace_side.png", "furnace_side.png", + "furnace_side.png", + { + image = "furnace_front_active.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.5 + }, + } + }, + paramtype2 = "facedir", + light_source = 8, + drop = "utility:furnace", + groups = {stone=2}, + legacy_facedir_simple = true, + is_ground_content = false, + sounds = main.stoneSound(), + on_timer = furnace_node_timer, + + --can_dig = can_dig, - on_step = function(self, dtime) - --set glow if cooking - --local glow = def and def.light_source + 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_destruct = function(pos) + destroy_furnace(pos) end, }) - minetest.register_craft({ output = "utility:furnace", recipe = { - {"main:cobble", "main:cobble", "main:cobble"}, - {"main:cobble", "", "main:cobble"}, - {"main:cobble", "main:cobble", "main:cobble"}, - }, + {"group:stone", "group:stone", "group:stone"}, + {"group:stone", "", "group:stone"}, + {"group:stone", "group:stone", "group:stone"}, + } })