basic_machines/technic_power.lua

452 lines
15 KiB
Lua

local machines_timer=5
-- BATTERY
local battery_update_meta = function(pos)
local meta = minetest.get_meta(pos);
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local capacity = meta:get_float("capacity");
local maxpower = meta:get_float("maxpower");
local energy = math.ceil(10*meta:get_float("energy"))/10;
local form =
"size[8,6.5]" .. -- width, height
"label[0,0;FUEL] ".."label[6,0;UPGRADE] "..
"label[1,0;ENERGY ".. energy .."/ ".. capacity..", maximum power output ".. maxpower .."]"..
"label[1,1;UPGRADE LEVEL ".. meta:get_int("upgrade") .. " (mese and diamond block)]"..
"list["..list_name..";fuel;0.,0.5;1,1;]".. "list["..list_name..";upgrade;6.,0.5;2,1;]" ..
"list[current_player;main;0,2.5;8,4;]"..
"button[4.5,0.35;1.5,1;OK;REFRESH]";
meta:set_string("formspec", form);
end
--[power crystal name] = energy provided
basic_machines.energy_crystals = {
["basic_machines:power_cell"]=1,
["basic_machines:power_block"]=11,
["basic_machines:power_rod"]=100,
}
battery_recharge = function(pos)
local meta = minetest.get_meta(pos);
local energy = meta:get_float("energy");
local capacity = meta:get_float("capacity");
local inv = meta:get_inventory();
local stack = inv:get_stack("fuel", 1); local item = stack:get_name();
local crystal = false;
local add_energy=0;
add_energy = basic_machines.energy_crystals[item] or 0;
if add_energy>0 then
crystal = true;
if energy+add_energy<=capacity then
stack:take_item(1);
inv:set_stack("fuel", 1, stack)
else
meta:set_string("infotext", "recharge problem: capacity " .. capacity .. ", needed " .. energy+add_energy)
end
else -- try do determine caloric value
local fuellist = inv:get_list("fuel");if not fuellist then return energy end
local fueladd, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
if fueladd.time > 0 then
add_energy = fueladd.time/40;
if energy+add_energy<=capacity then
inv:set_stack("fuel", 1, afterfuel.items[1]);
end
end
end
if add_energy>0 then
if energy+add_energy<=capacity then
energy=energy+add_energy
meta:set_float("energy",energy);
meta:set_string("infotext", "(R) energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
--TODO2: add entity power status display
minetest.sound_play("electric_zap", {pos=pos,gain=0.03,max_hear_distance = 8,})
end
end
return energy; -- new battery energy level
end
battery_upgrade = function(pos)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory();
local count1,count2;count1=0;count2=0;
local stack,item,count;
for i=1,2 do
stack = inv:get_stack("upgrade", i);item = stack:get_name();count= stack:get_count();
if item == "default:mese" then
count1=count1+count
elseif item == "default:diamondblock" then
count2=count2+count
end
end
if count1<count2 then count =count1 else count=count2 end
meta:set_int("upgrade",count);
-- adjust capacity
local capacity = 10+20*count;
local maxpower = capacity*0.1;
capacity = math.ceil(capacity*10)/10;
local energy = 0;
meta:set_float("capacity",capacity)
meta:set_float("maxpower",maxpower)
meta:set_float("energy",0)
meta:set_string("infotext", "energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
end
local machines_activate_furnace = minetest.registered_nodes["default:furnace"].on_metadata_inventory_put; -- this function will activate furnace
minetest.register_node("basic_machines:battery", {
description = "battery - stores energy, generates energy from fuel, can power nearby machines, or accelerate/run furnace above it. Its upgradeable.",
tiles = {"basic_machine_outlet.png","basic_machine_side.png","basic_machine_battery.png"},
groups = {oddly_breakable_by_hand=2,mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext","battery - stores energy, generates energy from fuel, can power nearby machines, or accelerate/run furnace above it when activated by keypad");
meta:set_string("owner",placer:get_player_name());
local inv = meta:get_inventory();inv:set_size("fuel", 1*1); -- place to put crystals
inv:set_size("upgrade", 2*1);
meta:set_int("upgrade",0); -- upgrade level determines energy storage capacity and max energy output
meta:set_float("capacity",10);meta:set_float("maxpower",1);
meta:set_float("energy",0);
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end -- machines_TTL prevents infinite recursion
local meta = minetest.get_meta(pos);
local energy = meta:get_float("energy");
local capacity = meta:get_float("capacity");
-- try to power furnace on top of it
if energy>=1 then -- need at least 1 energy
pos.y=pos.y+1; local node = minetest.get_node(pos).name;
if node== "default:furnace" or node=="default:furnace_active" then
local fmeta = minetest.get_meta(pos);
local fuel_totaltime = fmeta:get_float("fuel_totaltime") or 0;
local fuel_time = fmeta:get_float("fuel_time") or 0;
local t0 = meta:get_int("ftime"); -- furnace time
local t1 = minetest.get_gametime();
if t1-t0<machines_timer then return end -- to prevent too quick furnace acceleration
meta:set_int("ftime",t1);
if fuel_time>4 then -- twice as fast cooking
local src_time = fmeta:get_float("src_time") or 0
fmeta:set_float("src_time",src_time+5);
end
if fuel_time>40 or fuel_totaltime == 0 then -- must burn for at least 40 secs or furnace out of fuel
fmeta:set_float("fuel_totaltime",60);fmeta:set_float("fuel_time",0) -- add 60 second burn time to furnace
energy=energy-1; -- use up one energy
meta:set_float("energy",energy);
-- make furnace start if not already started
if node~="default:furnace_active" then machines_activate_furnace(pos) end
-- update energy display
meta:set_string("infotext", "energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
end
if energy>=1 then -- no need to recharge yet, will still work next time
return
else
local infotext = meta:get_string("infotext");
local new_infotext = "furnace needs at least 1 energy";
if new_infotext~=infotext then -- dont update unnecesarilly
meta:set_string("infotext", new_infotext);
pos.y=pos.y-1; -- so that it points to battery again!
end
end
else
pos.y=pos.y-1;
end
end
-- try to recharge by converting inserted fuel/power cells into energy
if energy<capacity then -- not full, try to recharge
battery_recharge(pos);
end
end
}},
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
battery_update_meta(pos);
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then return end
local meta = minetest.get_meta(pos);
battery_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname=="fuel" then
battery_recharge(pos);
battery_update_meta(pos);
elseif listname == "upgrade" then
battery_upgrade(pos);
battery_update_meta(pos);
end
return stack:get_count();
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
if listname == "upgrade" then
battery_upgrade(pos);
battery_update_meta(pos);
end
return stack:get_count();
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
can_dig = function(pos)
local meta = minetest.get_meta(pos);
if meta:get_int("upgrade")~=0 then return false else return true end
end
})
-- GENERATOR
local generator_update_meta = function(pos)
local meta = minetest.get_meta(pos);
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local form =
"size[8,6.5]" .. -- width, height
"label[0,0;POWER CRYSTALS] ".."label[6,0;UPGRADE] "..
"label[1,1;UPGRADE LEVEL ".. meta:get_int("upgrade") .. " (gold and diamond block)]"..
"list["..list_name..";fuel;0.,0.5;1,1;]".. "list["..list_name..";upgrade;6.,0.5;2,1;]" ..
"list[current_player;main;0,2.5;8,4;]"..
"button[4.5,0.35;1.5,1;OK;REFRESH]";
meta:set_string("formspec", form);
end
generator_upgrade = function(pos)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory();
local count1,count2;count1=0;count2=0;
local stack,item,count;
for i=1,2 do
stack = inv:get_stack("upgrade", i);item = stack:get_name();count= stack:get_count();
if item == "default:goldblock" then
count1=count1+count
elseif item == "default:diamondblock" then
count2=count2+count
end
end
if count1<count2 then count =count1 else count=count2 end
meta:set_int("upgrade",count);
end
minetest.register_node("basic_machines:generator", {
description = "Generator - very expensive, generates power crystals that provide power. Its upgradeable.",
tiles = {"basic_machine_side.png","basic_machine_side.png","basic_machine_generator.png"},
groups = {oddly_breakable_by_hand=2,mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext","generator - generates power crystals that provide power. Upgrade with up to 99 gold/diamond blocks.");
meta:set_string("owner",placer:get_player_name());
local inv = meta:get_inventory();
inv:set_size("fuel", 1*1); -- here generated power crystals are placed
inv:set_size("upgrade", 2*1);
meta:set_int("upgrade",0); -- upgrade level determines quality of produced crystals
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
generator_update_meta(pos);
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then return end
local meta = minetest.get_meta(pos);
generator_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname == "upgrade" then
generator_upgrade(pos);
generator_update_meta(pos);
end
return stack:get_count();
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
if listname == "upgrade" then
generator_upgrade(pos);
generator_update_meta(pos);
end
return stack:get_count();
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
can_dig = function(pos)
local meta = minetest.get_meta(pos);
if meta:get_int("upgrade")~=0 then return false else return true end
end
})
minetest.register_abm({
nodenames = {"basic_machines:generator"},
neighbors = {""},
interval = 20,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.get_meta(pos);
local upgrade = meta:get_int("upgrade");
local inv = meta:get_inventory();
local stack = inv:get_stack("fuel", 1);
local crystal, text;
if upgrade >= 99 then
crystal = "basic_machines:power_rod"
text = "upgrade level 99: generating power rod";
elseif upgrade >=20 then
crystal ="basic_machines:power_block"
text = "upgrade level 20: generating power block";
else
crystal ="basic_machines:power_cell"
text = "upgrade level 0: generating power cell";
end
local morecrystal = ItemStack(crystal)
stack:add_item(morecrystal);
inv:set_stack("fuel", 1, stack)
meta:set_string("infotext",text)
end
})
-- API for power distribution
function basic_machines.check_power(pos, power_draw) -- mover checks power source - battery
--minetest.chat_send_all(" battery: check_power " .. minetest.pos_to_string(pos) .. " " .. power_draw)
if minetest.get_node(pos).name ~= "basic_machines:battery"
then return 0
end
local meta = minetest.get_meta(pos);
local energy = meta:get_float("energy");
local capacity = meta:get_float("capacity");
local maxpower = meta:get_float("maxpower");
if power_draw>maxpower then
meta:set_string("infotext", "Power draw required : " .. power_draw .. " maximum power output " .. maxpower .. ". Please upgrade battery")
return 0;
end
if power_draw>energy then
energy = battery_recharge(pos); -- try recharge battery and continue operation immidiately
end
energy = energy-power_draw;
if energy<0 then
meta:set_string("infotext", "used fuel provides too little power for current power draw ".. power_draw);
return 0
end -- recharge wasnt enough, needs to be repeated manually, return 0 power available
meta:set_float("energy", energy);
-- update energy display
meta:set_string("infotext", "energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
return power_draw;
end
------------------------
-- CRAFTS
------------------------
minetest.register_craft({
output = "basic_machines:battery",
recipe = {
{"","default:steel_ingot",""},
{"default:steel_ingot","default:mese","default:steel_ingot"},
{"","default:diamond",""},
}
})
minetest.register_craft({
output = "basic_machines:generator",
recipe = {
{"","",""},
{"default:diamondblock","basic_machines:battery","default:diamondblock"},
{"default:diamondblock","default:diamondblock","default:diamondblock"}
}
})
minetest.register_craftitem("basic_machines:power_cell", {
description = "Power cell - provides 1 power",
inventory_image = "power_cell.png",
stack_max = 25
})
minetest.register_craftitem("basic_machines:power_block", {
description = "Power block - provides 11 power",
inventory_image = "power_block.png",
stack_max = 25
})
minetest.register_craftitem("basic_machines:power_rod", {
description = "Power rod - provides 100 power",
inventory_image = "power_rod.png",
stack_max = 25
})