--[[ 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) 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 end --local aftercooked --cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) --cookable = cooked.time ~= 0 -- -- Node definitions -- 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") 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) 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) end object:remove() end 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) end object:remove() end 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, }, 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, get_staticdata = function(self) return minetest.serialize({ itemstring = self.itemstring, count = self.count, }) 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)) 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)) else print("ERROR FURNACE RELEASED NON ITEM") 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)) 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, }) 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, }) end end end end, spawn_particles = function(self,time) --print("time:"..time) local pos = self.object:getpos() minetest.add_particlespawner({ amount = math.floor(10*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.5, z=0}, minacc = {x=0, y=0, z=0}, maxacc = {x=0, y=0, z=0}, minexptime = 1.1, maxexptime = 1.3, minsize = 1, maxsize = 2, collisiondetection = false, vertical = true, texture = "flame.png", }) minetest.add_particlespawner({ amount = math.floor(10*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 end 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 end 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, get_staticdata = function(self) return minetest.serialize({ itemstring = self.itemstring, count = self.count, }) 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() --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)) 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 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 = "blue", text = "", }) if obj then obj:setvelocity(vector.new(dir.x,dir.y+3.5,dir.z)) else print("ERROR FURNACE RELEASED NON ITEM") end end, 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, }, 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, get_staticdata = function(self) return minetest.serialize({ itemstring = self.itemstring, count = self.count, }) 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_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)) else print("ERROR FURNACE RELEASED NON ITEM") end end, on_step = function(self, dtime) --set glow if cooking --local glow = def and def.light_source end, }) minetest.register_craft({ output = "utility:furnace", recipe = { {"main:cobble", "main:cobble", "main:cobble"}, {"main:cobble", "", "main:cobble"}, {"main:cobble", "main:cobble", "main:cobble"}, }, })