local function update_timer (pos) local t = minetest.get_node_timer(pos) if not t:is_started() then t:start(1.0) end end local function create_item_entity(istack, cast, tpos) local vpos = vector.add(tpos, {x=0,y=0.5,z=0}) local e = minetest.add_entity(vpos, "multifurnace:table_item") e:set_rotation({x = 1.570796, y = 0, z = 0}) e:get_luaentity():set_item(istack:get_name()) e:get_luaentity():set_is_cast(cast) end local function set_item_entities(inv, pos) local vpos = vector.add(pos, {x=0,y=1,z=0}) local ents = minetest.get_objects_inside_radius(vpos, 1) local virtual = {} for _,object in pairs(ents) do if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "multifurnace:table_item" then table.insert(virtual, object) end end local cast = inv:get_stack("cast", 1) local item = inv:get_stack("item", 1) if #virtual >= 2 then for _,v in pairs(virtual) do local lent = v:get_luaentity() if lent:is_cast() then if cast:is_empty() then v:remove() else lent:set_item(cast:get_name()) end else if item:is_empty() then v:remove() else lent:set_item(item:get_name()) end end end elseif #virtual == 1 then local lent = virtual[1]:get_luaentity() if lent:is_cast() then if cast:is_empty() then virtual[1]:remove() else lent:set_item(cast:get_name()) end if not item:is_empty() then create_item_entity(item, false, pos) end else if item:is_empty() then virtual[1]:remove() else lent:set_item(item:get_name()) end if not cast:is_empty() then create_item_entity(cast, true, pos) end end else if not item:is_empty() then create_item_entity(item, false, pos) end if not cast:is_empty() then create_item_entity(cast, true, pos) end end end local function cast_amount (ctype) if not metal_caster.casts[ctype] then return nil end return metal_caster.spec.ingot * (metal_caster.casts[ctype].cost or 1) end local function on_timer(pos, elapsed) local refresh = false local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local cast = inv:get_stack("cast", 1) local item = inv:get_stack("item", 1) if cast:is_empty() or not item:is_empty() then return false end local liquid = meta:get_string("liquid") local liqc = meta:get_int("liquid_amount") local liqt = meta:get_int("liquid_total") -- TODO: cast creation local ctype = metal_caster.get_cast_for_name(cast:get_name()) local amount = cast_amount(ctype) if not ctype then meta:set_int("liquid_total", metal_caster.spec.ingot) elseif liqt ~= amount then meta:set_int("liquid_total", amount) end if liquid == "" or not ctype then return false end local liqt = fluidity.get_metal_for_fluid(liquid) if not amount then return false end local result = metal_caster.find_castable(liqt, ctype) if not result then return false end local solidify = meta:get_int("solidify") if liqc >= amount then if solidify < 3 then refresh = true meta:set_int("solidify", solidify + 1) else liquid = "" liqc = 0 item = ItemStack(result) refresh = false -- Set result meta:set_string("liquid", liquid) meta:set_int("liquid_amount", liqc) meta:set_int("solidify", 0) inv:set_stack("item", 1, item) set_item_entities(inv, pos) end end return refresh end minetest.register_node("multifurnace:casting_table", { description = "Casting Table", drawtype = "nodebox", paramtype1 = "light", node_box = { type = "fixed", fixed = { {-0.5000, -0.5000, -0.5000, -0.2500, 0.1875, -0.2500}, {0.2500, -0.5000, -0.5000, 0.5000, 0.1875, -0.2500}, {0.2500, -0.5000, 0.2500, 0.5000, 0.1875, 0.5000}, {-0.5000, -0.5000, 0.2500, -0.2500, 0.1875, 0.5000}, {-0.5000, 0.1875, -0.5000, 0.5000, 0.4375, 0.5000}, {-0.5000, 0.4375, -0.5000, 0.4375, 0.5000, -0.4375}, {-0.4375, 0.4375, 0.4375, 0.5000, 0.5000, 0.5000}, {-0.5000, 0.4375, -0.4375, -0.4375, 0.5000, 0.5000}, {0.4375, 0.4375, -0.5000, 0.5000, 0.5000, 0.4375} } }, tiles = {"multifurnace_table_top.png", "multifurnace_table_side.png"}, groups = { cracky = 1, multifurnace_accessory = 1 }, on_construct = function (pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() inv:set_size("cast", 1) inv:set_size("item", 1) end, on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) local i = itemstack:get_name() local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local cast = metal_caster.get_cast_for_name(i) if inv:get_stack("cast", 1):is_empty() and cast then inv:set_stack("cast", 1, itemstack:take_item(1)) set_item_entities(inv, pos) update_timer(pos) --elseif inv:get_stack("item", 1):is_empty() and not cast then -- inv:set_stack("item", 1, itemstack:take_item(1)) -- set_item_entities(inv, pos) end return itemstack end, on_punch = function(pos, node, puncher, pointed_thing) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local to_give = nil if not inv:get_stack("item", 1):is_empty() then to_give = inv:get_stack("item", 1) inv:set_list("item", {}) elseif not inv:get_stack("cast", 1):is_empty() then local liq = meta:get_int("liquid_amount") if liq > 0 then meta:set_int("liquid_amount", 0) meta:set_string("liquid", "") meta:set_int("solidify", 0) end to_give = inv:get_stack("cast", 1) inv:set_list("cast", {}) end if to_give and puncher then local inp = puncher:get_inventory() if inp:room_for_item("main", to_give) then inp:add_item("main", to_give) else minetest.item_drop(to_give, puncher, vector.add(pos, {x=0,y=1,z=0})) end set_item_entities(inv, pos) return false end return true end, can_dig = function(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() return inv:get_stack("item", 1):is_empty() and inv:get_stack("cast", 1):is_empty() end, on_timer = on_timer, node_io_can_put_liquid = function (pos, node, side) return true end, node_io_can_take_liquid = function (pos, node, side) return false end, node_io_accepts_millibuckets = function(pos, node, side) return true end, node_io_put_liquid = function(pos, node, side, putter, liquid, millibuckets) local meta = minetest.get_meta(pos) local liq = meta:get_string("liquid") local liqc = meta:get_int("liquid_amount") local liqt = meta:get_int("liquid_total") local add = millibuckets local leftovers = 0 if (liq ~= liquid and liq ~= "") or liqt == 0 then return millibuckets end if liqc == liqt then return millibuckets end if liqc + millibuckets > liqt then leftovers = liqc + millibuckets - liqt add = liqt - liqc end meta:set_string("liquid", liquid) meta:set_int("liquid_amount", liqc + add) update_timer(pos) return leftovers end, node_io_room_for_liquid = function(pos, node, side, liquid, millibuckets) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local liq = meta:get_string("liquid") local liqc = meta:get_int("liquid_amount") local liqt = meta:get_int("liquid_total") local add = millibuckets -- Don't allow adding fluid when there's an item or there's something solidifying if not inv:get_stack("item", 1):is_empty() or meta:get_int("solidify") > 0 then return 0 end if (liq ~= liquid and liq ~= "") or liqt == 0 then return 0 end if liqc == liqt then return 0 end if liqc + millibuckets > liqt then add = liqt - liqc end return add end, node_io_get_liquid_size = function (pos, node, side) return 1 end, node_io_get_liquid_name = function(pos, node, side, index) local meta = minetest.get_meta(pos) return meta:get_string("liquid") end, node_io_get_liquid_stack = function(pos, node, side, index) local meta = minetest.get_meta(pos) return ItemStack(meta:get_string("liquid") .. " " .. meta:get_int("liquid_amount")) end, }) minetest.register_entity("multifurnace:table_item", { initial_properties = { physical = false, collide_with_objects = false, visual = "item", visual_size = {x = 0.45, y = 0.45, z = 0.5}, textures = {}, pointable = false, static_save = false, }, item = "air", cast = false, set_item = function (self, itm) self.item = itm self.object:set_properties({textures = {self.item}}) end, is_cast = function (self) return self.cast end, set_is_cast = function (self, is) self.cast = is == true end }) minetest.register_lbm({ label = "Draw Casting Table entities", name = "multifurnace:casting_table_load", nodenames = {"multifurnace:casting_table"}, run_at_every_load = true, action = function (pos, node) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() set_item_entities(inv, pos) end })