123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- local coal = minetest.registered_aliases["coal"]
- local COAL_HEAT = 10
- local KILN_TIMER_LENGTH = 0.2
- local update_infotext =
- dofile(minetest.get_modpath("kilns") .. "/infotext.lua")
- --the act of smelting
- ------------------------------------------------------------------------
- --consumes coal and increases heat if heat is <= 0,
- --returns new heat, fuel is passed as a reference so it's not returned
- local function refuel_if_necessary(heat, fuel)
- if heat <= 0 and not fuel:is_empty()
- then
- heat = COAL_HEAT
- fuel:take_item()
- end
- return heat
- end
- --looks up a smelting recipe for an input itemstack and returns
- --the result or false if there is no recipe for the item stack.
- local function get_smelt_result(input_stack)
- local input = {method = "cooking", items = {input_stack}}
- local result = minetest.get_craft_result(input)
- if not result.item:is_empty()
- then
- return result
- else
- return false
- end
- end
- local chimney_particle_prototype =
- {
- amount = 20 * KILN_TIMER_LENGTH,
- time = KILN_TIMER_LENGTH,
- minvel = {x = -0.2, y = 0.2, z = -0.2},
- maxvel = {x = 0.2, y = 1, z = 0.2},
- minexptime = 3,
- maxexptime = 5,
- minsize = 1,
- maxsize = 3,
- }
- local function spawn_chimney_particles(pos)
- pos.y = pos.y + 0.5
- local smokedef_white = {}
- local smokedef_black = {}
- for k, v in pairs(chimney_particle_prototype)
- do
- smokedef_white[k] = v
- smokedef_black[k] = v
- end
- smokedef_white.minpos = pos
- smokedef_white.maxpos = pos
- smokedef_black.minpos = pos
- smokedef_black.maxpos = pos
- smokedef_white.texture = "smoke_puff_white.png"
- smokedef_black.texture = "smoke_puff_black.png"
- minetest.add_particlespawner(smokedef_white)
- minetest.add_particlespawner(smokedef_black)
- end
- local smoke_puff_particle_prototype =
- {
- amount = 30,
- time = 0.05,
- minvel = {x = -1, y = 0.2, z = -1},
- maxvel = {x = 1, y = 0.5, z = 1},
- minexptime = 0.3,
- maxexptime = 1,
- minsize = 1,
- maxsize = 3,
- }
- local function spawn_smoke_puff_particles(pos)
- pos.y = pos.y + 0.5
- local smokedef_white = {}
- local smokedef_black = {}
- for k, v in pairs(smoke_puff_particle_prototype)
- do
- smokedef_white[k] = v
- smokedef_black[k] = v
- end
- smokedef_white.minpos = pos
- smokedef_white.maxpos = pos
- smokedef_black.minpos = pos
- smokedef_black.maxpos = pos
- smokedef_white.texture = "smoke_puff_white.png"
- smokedef_black.texture = "smoke_puff_black.png"
- minetest.add_particlespawner(smokedef_white)
- minetest.add_particlespawner(smokedef_black)
- end
- local function on_timer(pos, elapsed)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- local heat = meta:get_float("heat") - elapsed
- local progress = meta:get_float("progress") - elapsed
- --the smelting result possibly won't fit if the recipe is changed
- --inbetween sessions but I don't care enough to fix it.
- local fuel = inv:get_stack("fuel", 1)
- local input = inv:get_stack("in", 1)
- local output = inv:get_stack("out", 1)
- --should smelt
- if not input:is_empty()
- then
- heat = refuel_if_necessary(heat, fuel)
- if heat > 0
- then
- progress = progress + 2 * elapsed
- local recipe = get_smelt_result(input)
- if recipe and progress >= recipe.time --done one item
- then
- spawn_smoke_puff_particles(pos)
- progress = 0
- local rest = output:add_item(recipe.item)
- local consume = input:take_item()
- --if output stack is full, undo smelting
- if not rest:is_empty()
- then
- input:add_item(consume)
- end
- end
- end
- end
- --write back possibly changed values
- local fuel = inv:set_stack("fuel", 1, fuel)
- local input = inv:set_stack("in", 1, input)
- local output = inv:set_stack("out", 1, output)
- meta:set_float("heat", heat)
- meta:set_float("progress", progress)
- local continue = heat > 0 or progress > 0
- update_infotext(meta, continue)
- if not continue
- then
- local node = minetest.get_node(pos)
- local n =
- {
- name = "kilns:kiln_off",
- param1 = node.param1,
- param2 = node.param2
- }
- minetest.swap_node(pos, n)
- else
- spawn_chimney_particles(pos)
- end
- return continue
- end
- --player interaction with kiln inventory
- ------------------------------------------------------------------------
- --returning items from the kiln's inventory
- -----------------------------------------------------
- local function kiln_get_return_stack(kiln_inv)
- local priority_order = {"out", "in", "fuel",}
- for i, list in ipairs(priority_order)
- do
- local itemstack = kiln_inv:get_stack(list, 1)
- if not itemstack:is_empty()
- then
- return itemstack, list
- end
- end
- end
- local function kiln_item_return_wholestack(kiln_inv, player_inv)
- local stack, retlist = kiln_get_return_stack(kiln_inv)
- if not stack
- then
- --Empty
- return
- end
- local overflow = player_inv:add_item("main", stack)
- kiln_inv:set_stack(retlist, 1, overflow)
- end
- local function kiln_item_return_single(kiln_inv, player_inv)
- local stack, retlist = kiln_get_return_stack(kiln_inv)
- if not stack
- then
- --Empty
- return
- end
- local overflow = player_inv:add_item("main", stack:take_item(1))
- stack:add_item(overflow)
- kiln_inv:set_stack(retlist, 1, stack)
- end
- --punch to return
- local function on_punch(pos, node, puncher, pointed_thing)
- if not puncher
- then
- return true
- end
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- local wholestack = puncher:get_player_control().aux1
- local puncherinv = puncher:get_inventory()
- if wholestack
- then
- kiln_item_return_wholestack(inv, puncherinv)
- else
- kiln_item_return_single(inv, puncherinv)
- end
- update_infotext(meta, false)
- return true
- end
- --add items to the kiln inventory
- -----------------------------------------------------
- local function start_timer_if_needed(pos, inv)
- local timer = minetest.get_node_timer(pos)
- if timer:is_started()
- then
- --already smelting
- return
- end
- local input = inv:get_stack("in", 1)
- if input:is_empty()
- then
- return
- end
- local fuel = inv:get_stack("fuel", 1)
- if fuel:is_empty()
- then
- return
- end
- --we now know that input and fuel are not empty and that the kiln
- --is not burning already, so we can start smelting
- timer:start(KILN_TIMER_LENGTH)
- return true
- end
- local function can_put(to_put, input_stack, output_stack)
- local smelt_result = get_smelt_result(to_put)
- if not smelt_result
- then
- return false
- end
- return (input_stack:is_empty() or
- to_put:get_name() == input_stack:get_name()) and
- (output_stack:is_empty() or
- smelt_result.item:get_name() == output_stack:get_name())
- end
- local function kiln_item_add(kiln_inv, itemstack, amount)
- local rest
- if itemstack:get_name() == coal
- then
- local coalstack = kiln_inv:get_stack("fuel", 1)
- rest = coalstack:add_item(itemstack:take_item(amount))
- kiln_inv:set_stack("fuel", 1, coalstack)
- else
- local to_smelt = kiln_inv:get_stack("in", 1)
- local smelted = kiln_inv:get_stack("out", 1)
- if can_put(itemstack, to_smelt, smelted)
- then
- rest = to_smelt:add_item(itemstack:take_item(amount))
- kiln_inv:set_stack("in", 1, to_smelt)
- end
- end
- itemstack:add_item(ItemStack(rest))
- end
- local function kiln_item_add_single(kiln_inv, itemstack)
- kiln_item_add(kiln_inv, itemstack, 1)
- end
- local function kiln_item_add_wholestack(kiln_inv, itemstack)
- local stack_size = itemstack:get_count()
- kiln_item_add(kiln_inv, itemstack, stack_size)
- end
- --add stuff to the kiln with rightclick
- local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- local wholestack = clicker:get_player_control().aux1
- if wholestack
- then
- kiln_item_add_wholestack(inv, itemstack)
- else
- kiln_item_add_single(inv, itemstack)
- end
- local switch_to_burning = start_timer_if_needed(pos, inv)
- if switch_to_burning
- then
- local n =
- {
- name = "kilns:kiln_on",
- param1 = node.param1,
- param2 = node.param2
- }
- minetest.swap_node(pos, n)
- end
- update_infotext(meta, false)
- return itemstack
- end
- --initialize metadata
- ------------------------------------------------------------------------
- local function on_construct(pos)
- local meta = minetest.get_meta(pos)
- meta:set_float("heat", 0)
- meta:set_float("progress", 0)
- meta:mark_as_private({"heat", "progress"})
- local inv = meta:get_inventory()
- inv:set_size("fuel", 1)
- inv:set_size("in", 1)
- inv:set_size("out", 1)
- update_infotext(meta, false)
- end
- return on_timer, on_punch, on_rightclick, on_construct
|