techage/iron_age/coalburner.lua
2019-09-14 19:49:33 +02:00

284 lines
7.8 KiB
Lua

--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Coalburner as heater for the Meltingpot
]]--
local S = techage.S
local COAL_BURN_TIME = 1200
local CYCLE_TIME = 5
local function get_node_lvm(pos)
local node = minetest.get_node_or_nil(pos)
if node then
return node
end
local vm = minetest.get_voxel_manip()
local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
local data = vm:get_data()
local param2_data = vm:get_param2_data()
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
local idx = area:indexp(pos)
node = {
name = minetest.get_name_from_content_id(data[idx]),
param2 = param2_data[idx]
}
return node
end
local function num_coal(pos)
local pos1 = {x=pos.x, y=pos.y+1, z=pos.z}
local pos2 = {x=pos.x, y=pos.y+32, z=pos.z}
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"techage:charcoal", "techage:charcoal_burn"})
return #nodes
end
local function num_cobble(pos, height)
local pos1 = {x=pos.x-1, y=pos.y+1, z=pos.z-1}
local pos2 = {x=pos.x+1, y=pos.y+height, z=pos.z+1}
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"default:cobble", "default:desert_cobble"})
return #nodes
end
local function num_air(pos)
local pos1 = {x=pos.x-1, y=pos.y, z=pos.z-1}
local pos2 = {x=pos.x+1, y=pos.y, z=pos.z+1}
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"air"})
return #nodes
end
local function start_burner(pos, height)
local pos1 = {x=pos.x-1, y=pos.y+1, z=pos.z-1}
local pos2 = {x=pos.x+1, y=pos.y+height, z=pos.z+1}
for _,p in ipairs(minetest.find_nodes_in_area(pos1, pos2, "techage:charcoal")) do
minetest.swap_node(p, {name = "techage:charcoal_burn"})
end
end
local function remove_coal(pos, height)
local pos1 = {x=pos.x-1, y=pos.y+1, z=pos.z-1}
local pos2 = {x=pos.x+1, y=pos.y+height, z=pos.z+1}
for _,p in ipairs(minetest.find_nodes_in_area(pos1, pos2, "techage:charcoal_burn")) do
minetest.remove_node(p)
end
end
local function remove_flame(pos, height)
local idx
pos = {x=pos.x, y=pos.y+height, z=pos.z}
for idx=height,1,-1 do
pos = {x=pos.x, y=pos.y+1, z=pos.z}
local node = get_node_lvm(pos)
if string.find(node.name, "techage:flame") then
minetest.remove_node(pos)
elseif node.name == "techage:meltingpot" then
techage.update_heat(pos)
end
end
end
local function calc_num_coal(height, burn_time)
local num = height
if burn_time < 0 then
local x = (COAL_BURN_TIME * 0.2) / height
num = math.max(height + math.floor(burn_time/x), 0)
end
return num
end
local function flame(pos, height, heat, first_time)
local idx
pos = {x=pos.x, y=pos.y+height, z=pos.z}
for idx=heat,1,-1 do
pos = {x=pos.x, y=pos.y+1, z=pos.z}
idx = math.min(idx, 12)
local node = get_node_lvm(pos)
if node.name == "techage:meltingpot_active" or node.name == "ignore" then
return
end
if node.name == "techage:meltingpot" then
if first_time then
techage.switch_to_active(pos)
else
techage.update_heat(pos)
end
return
end
minetest.add_node(pos, {name = "techage:flame"..math.min(idx,7)})
local meta = minetest.get_meta(pos)
meta:set_int("heat", idx)
end
end
local lRatio = {120, 110, 95, 75, 55, 28, 0}
local lColor = {"000080", "400040", "800000", "800000", "800000", "800000", "800000"}
for idx,ratio in ipairs(lRatio) do
local color = "techage_flame_animated.png^[colorize:#"..lColor[idx].."B0:"..ratio
minetest.register_node("techage:flame"..idx, {
tiles = {
{
name = color,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1
},
},
},
after_destruct = function(pos, oldnode)
pos.y = pos.y + 1
local node = get_node_lvm(pos)
if minetest.get_item_group(node.name, "techage_flame") > 0 then
minetest.remove_node(pos)
end
end,
drawtype = "glasslike",
use_texture_alpha = true,
inventory_image = "techage_flame.png",
paramtype = "light",
light_source = 13,
walkable = false,
buildable_to = true,
floodable = true,
sunlight_propagates = true,
damage_per_second = 4 + idx,
groups = {igniter = 2, dig_immediate = 3, techage_flame=1, not_in_creative_inventory=1},
drop = "",
})
end
minetest.register_node("techage:ash", {
description = S("Ash"),
tiles = {"techage_ash.png"},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-4/8, -4/8, -4/8, 4/8, -3/8, 4/8},
},
},
is_ground_content = false,
groups = {crumbly = 3, not_in_creative_inventory=1},
drop = "",
sounds = default.node_sound_defaults(),
})
function techage.start_burner(pos, playername)
local height = num_coal(pos)
if minetest.is_protected(
{x=pos.x, y=pos.y+height, z=pos.z},
playername) then
return
end
if num_cobble(pos, height) == height * 8 then
local meta = minetest.get_meta(pos)
--meta:set_int("ignite", minetest.get_gametime())
meta:set_int("burn_time", COAL_BURN_TIME)
meta:set_int("height", height)
start_burner(pos, height)
flame(pos, height, height, true)
local handle = minetest.sound_play("techage_gasflare", {
pos = {x=pos.x, y=pos.y+height, z=pos.z},
max_hear_distance = 20,
gain = height/12.0,
loop = true})
meta:set_int("handle", handle)
minetest.get_node_timer(pos):start(CYCLE_TIME)
end
end
function techage.keep_running_burner(pos)
local meta = minetest.get_meta(pos)
local height = meta:get_int("height")
remove_flame(pos, height)
local handle = meta:get_int("handle")
if handle then
minetest.sound_stop(handle)
meta:set_int("handle", 0)
end
local burn_time = meta:get_int("burn_time")
-- burner hole is open
if num_air(pos) == 1 then
meta:set_int("burn_time", burn_time - CYCLE_TIME)
-- tower intact
if num_cobble(pos, height) == height * 8 then
local num_coal = calc_num_coal(height, burn_time)
if num_coal > 0 then
if meta:get_int("paused") == 1 then
flame(pos, height, num_coal, true)
meta:set_int("paused", 0)
else
flame(pos, height, num_coal, false)
end
handle = minetest.sound_play("techage_gasflare", {
pos = {x=pos.x, y=pos.y+height, z=pos.z},
max_hear_distance = 32,
gain = num_coal/12.0,
loop = true})
meta:set_int("handle", handle)
else
minetest.swap_node(pos, {name="techage:ash"})
remove_coal(pos, height)
return false
end
else
minetest.swap_node(pos, {name="techage:ash"})
remove_coal(pos, height)
return false
end
else
meta:set_int("paused", 1)
end
return true
end
function techage.stop_burner(pos)
local meta = minetest.get_meta(pos)
local height = meta:get_int("height")
remove_flame(pos, height)
remove_coal(pos, height)
local handle = meta:get_int("handle")
minetest.sound_stop(handle)
meta:set_int("burn_time", 0)
end
local BurnerHelp = S("Coal Burner to heat the melting pot:@n"..
"- build cobble tower with a 3x3 footprint@n"..
"- more height means more flame heat@n"..
"- keep a hole open on one side@n"..
"- put a lighter in@n"..
"- fill the tower from the top with charcoal@n"..
"- ignite the lighter@n"..
"- place the pot in the flame, (one block above the tower)@n"..
"- to pause the burner, close the hole temporarily with e.g. dirt@n"..
"(see plan)")
local BurnerImages = {
{false, false, false, "default_cobble.png^techage_meltingpot.png", false},
{false, false, false, "techage_flame.png", false},
{false, false, "default_cobble.png", "techage_charcoal.png", "default_cobble.png"},
{false, false, "default_cobble.png", "techage_charcoal.png", "default_cobble.png"},
{false, false, "default_cobble.png", "techage_charcoal.png", "default_cobble.png"},
{false, false, "default_cobble.png", "techage_charcoal.png", "default_cobble.png"},
{false, false, false, "techage_lighter.png", "default_cobble.png"},
{false, false, "default_cobble.png", "default_cobble.png", "default_cobble.png"},
}
techage.register_entry_page("ta1", "burner", S("Coal Burner"), BurnerHelp, nil, BurnerImages)