123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- if not minetest.global_exists("bat2") then bat2 = {} end
- if not minetest.global_exists("bat2_lv") then bat2_lv = {} end
- if not minetest.global_exists("bat2_mv") then bat2_mv = {} end
- if not minetest.global_exists("bat2_hv") then bat2_hv = {} end
- -- Localize for performance.
- local math_floor = math.floor
- for k, v in ipairs({
- {tier="lv", up="LV", name="LV", buffer=tech.battery_lv.buffer},
- {tier="mv", up="MV", name="MV", buffer=tech.battery_mv.buffer},
- {tier="hv", up="HV", name="HV", buffer=tech.battery_hv.buffer},
- }) do
- -- Which function table are we operating on?
- local functable = _G["bat2_" .. v.tier]
- functable.do_battery_decay =
- function(meta)
- local timeout = false
- local time0 = meta:get_int("decay")
- local time1 = os.time()
- if time1 > (time0 + 60*60*24*3) then
- -- Note: we do not add 72 hours to the decay timeout unless a battery cell
- -- actually decays. This means that if we don't decay a battery after 72
- -- hours, we'll try again every hour after that until we do.
- meta:set_int("decay", (time0 + 60*60*24*3+60*60))
- timeout = true
- end
- -- The battery is considered "full" (and 'stressed') when over 90% usage.
- local maxstorage = false
- local chg, max = functable.get_energy_status(meta)
- if (chg / max) > 0.9 then
- maxstorage = true
- end
- -- Decay happens slowly while the battery bank is holding the max amount
- -- of energy. This sort of simulates batteries becoming weaker over time
- -- and needing replacing.
- if timeout and maxstorage and math.random(1, 20) == 1 then
- local inv = meta:get_inventory()
- local size = inv:get_size("batteries")
- local idx = math.random(1, size)
- local stack = inv:get_stack("batteries", idx)
- if stack:get_name() == "battery:battery" then
- inv:set_stack("batteries", idx, ItemStack("battery:battery_broken"))
- -- Update decay timeout value.
- meta:set_int("decay", time1)
- end
- end
- end
- functable.on_energy_put =
- function(pos, energy)
- --minetest.chat_send_all("# Server: Got " .. energy .. " energy!")
- local meta = minetest.get_meta(pos)
- local chg, max = functable.get_energy_status(meta)
- local canfit = max - chg
- local toput = energy
- if toput > canfit then
- toput = canfit
- end
- local total = chg + toput
- meta:set_int("energy", total)
- energy = energy - toput
- if toput > 0 then
- functable.trigger_update(pos)
- end
- return energy
- end
- functable.on_energy_get =
- function(pos, energy)
- local meta = minetest.get_meta(pos)
- local have = meta:get_int("energy")
- if have < energy then
- meta:set_int("energy", 0)
- if have > 0 then
- functable.trigger_update(pos)
- end
- return have
- end
- have = have - energy
- meta:set_int("energy", have)
- if energy > 0 then
- functable.trigger_update(pos)
- end
- return energy
- end
- functable.compose_infotext =
- function(pos)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- local chg, max = functable.get_energy_status(meta)
- local size = inv:get_size("batteries")
- local cnt = functable.get_battery_count(inv)
- local infotext = v.up .. " Battery Array\n" ..
- "Internal Battery Units: " .. cnt .. "/" .. size .. "\n" ..
- "Energy: " .. chg .. "/" .. max .. " EUs\n"
- if max > 0 then
- local percent = math_floor(chg / max * 100)
- infotext = infotext .. "Charge: " .. percent .. "%"
- else
- infotext = infotext .. "Charge: 0%"
- end
- meta:set_string("infotext", infotext)
- end
- functable.compose_formspec =
- function(pos)
- local meta = minetest.get_meta(pos)
- local chg, max = functable.get_energy_status(meta)
- local charge_desc = v.name .. " Charge Status: " ..
- chg .. "/" .. max .. " EUs"
- local formspec =
- "size[8,8.5]" ..
- default.formspec.get_form_colors() ..
- default.formspec.get_form_image() ..
- default.formspec.get_slot_colors() ..
- "label[0,0;" .. minetest.formspec_escape(charge_desc) .. "]" ..
- "label[0,0.5;NRAIB (Non-Redundant Array of Independant Batteries)]" ..
- "item_image[7,0;1,1;battery:battery]" ..
- "list[context;batteries;0,1;8,2;]" ..
- "list[current_player;main;0,4.25;8,1;]" ..
- "list[current_player;main;0,5.5;8,3;8]" ..
- "listring[context;batteries]"..
- "listring[current_player;main]"..
- default.get_hotbar_bg(0, 4.25)
- meta:set_string("formspec", formspec)
- end
- functable.update_charge_visual =
- function(pos)
- local meta = minetest.get_meta(pos)
- local chg, max = functable.get_energy_status(meta)
- local name = "bat2:bt0_" .. v.tier
- if max > 0 then -- Avoid divide-by-zero.
- local percent = math_floor((chg / max) * 100)
- local sz = math.ceil(100 / 12)
- for i = 0, 12, 1 do
- if percent <= sz*i then
- name = "bat2:bt" .. i .. "_" .. v.tier
- break
- end
- end
- end
- machines.swap_node(pos, name)
- end
- functable.on_punch =
- function(pos, node, puncher, pointed_thing)
- functable.trigger_update(pos)
- functable.privatize(minetest.get_meta(pos))
- end
- functable.can_dig =
- function(pos, player)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- return inv:is_empty("batteries")
- end
- functable.allow_metadata_inventory_put =
- function(pos, listname, index, stack, player)
- local NBATT = "battery:battery"
- local pname = player:get_player_name()
- if minetest.test_protection(pos, pname) then
- return 0
- end
- if stack:get_name() == NBATT then
- return stack:get_count()
- end
- return 0
- end
- functable.allow_metadata_inventory_move =
- function(pos, from_list, from_index, to_list, to_index, count, player)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- local stack = inv:get_stack(from_list, from_index)
- return functable.allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
- end
- functable.allow_metadata_inventory_take =
- function(pos, listname, index, stack, player)
- local pname = player:get_player_name()
- if minetest.test_protection(pos, pname) then
- return 0
- end
- return stack:get_count()
- end
- functable.get_battery_count =
- function(inv)
- local batteries = inv:get_list("batteries")
- local count = 0
- for k, v in ipairs(batteries) do
- if v:get_name() == "battery:battery" then
- -- Only 1 battery allowed per stack.
- count = count + 1
- end
- end
- return count
- end
- functable.update_maximum_charge =
- function(meta)
- local count = functable.get_battery_count(meta:get_inventory())
- local max
- if v.tier == "lv" then
- max = count * v.buffer
- elseif v.tier == "mv" then
- max = count * v.buffer
- elseif v.tier == "hv" then
- max = count * v.buffer
- end
- local chg = meta:get_int("energy")
- -- Ensure charge isn't over max. This can happen if user removed a battery.
- if chg > max then
- meta:set_int("energy", max)
- end
- meta:set_int("max", max)
- end
- functable.on_timer =
- function(pos, elapsed)
- local meta = minetest.get_meta(pos)
- local current_amount = meta:get_int("energy")
- local old_eu_amount = meta:get_int("old_eu")
- -- Todo: here, we can respond to changes in EU amount since last update.
- meta:set_int("old_eu", current_amount)
- -- Needed in case the operator removes or adds a battery.
- -- Also, EUs can be added/drained from batteries without going through a distributer.
- functable.do_battery_decay(meta)
- functable.update_maximum_charge(meta)
- functable.update_charge_visual(pos)
- functable.compose_infotext(pos)
- functable.compose_formspec(pos)
- -- Run timer again, to expire in 1 hour.
- -- If the machine needs an update sooner, the timer will be restarted with
- -- a quicker timeout.
- local timer = minetest.get_node_timer(pos)
- timer:start(60*60)
- end
- functable.on_blast =
- function(pos)
- local drops = {}
- default.get_inventory_drops(pos, "batteries", drops)
- drops[#drops+1] = "bat2:bt0_" .. v.tier
- minetest.remove_node(pos)
- return drops
- end
- functable.on_construct =
- function(pos)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- inv:set_size("batteries", 8*2)
- functable.update_maximum_charge(meta)
- functable.compose_infotext(pos)
- functable.compose_formspec(pos)
- meta:set_string("nodename", "DUMMY")
- meta:set_string("owner", "DUMMY")
- meta:set_int("energy", 0)
- meta:set_int("old_eu", 0)
- meta:set_int("max", 0)
- functable.privatize(meta)
- end
- functable.privatize =
- function(meta)
- meta:mark_as_private({
- "nodename",
- "owner",
- "energy",
- "old_eu",
- "max",
- "decay",
- })
- end
- functable.on_destruct =
- function(pos)
- local meta = minetest.get_meta(pos)
- net2.clear_caches(pos, meta:get_string("owner"), v.tier)
- nodestore.del_node(pos)
- end
- functable.after_place_node =
- function(pos, placer, itemstack, pointed_thing)
- local meta = minetest.get_meta(pos)
- local owner = placer:get_player_name()
- meta:set_string("nodename", minetest.get_node(pos).name)
- meta:set_string("owner", owner)
- net2.clear_caches(pos, owner, v.tier)
- nodestore.add_node(pos)
- end
- functable.on_metadata_inventory_move =
- function(pos)
- functable.trigger_update(pos)
- end
- functable.on_metadata_inventory_put =
- function(pos)
- functable.trigger_update(pos)
- end
- functable.on_metadata_inventory_take =
- function(pos)
- functable.trigger_update(pos)
- end
- functable.trigger_update =
- function(pos)
- -- Restart timer without new timeout even if already running.
- local timer = minetest.get_node_timer(pos)
- timer:start(1.0)
- end
- -- Read the current & max charge of the battery, but do not trigger any update.
- -- Function shall be used internally ONLY.
- functable.get_energy_status =
- function(meta)
- local chg = meta:get_int("energy")
- local max = meta:get_int("max")
- return chg, max
- end
- end
- if not bat2.run_once then
- local nodebox = {
- {0, 0, 0, 5, 16, 5},
- {11, 0, 0, 16, 16, 5},
- {0, 0, 11, 5, 16, 16},
- {11, 0, 11, 16, 16, 16},
- {1, 1, 1, 15, 15, 15},
- {0, 0, 0, 16, 1, 16},
- {0, 15, 0, 16, 16, 16},
- }
- local selectbox = {
- {0, 0, 0, 16, 16, 16},
- }
- utility.transform_nodebox(nodebox)
- utility.transform_nodebox(selectbox)
- for k, v in ipairs({
- {tier="lv", title="LV"},
- {tier="mv", title="MV"},
- {tier="hv", title="HV"},
- }) do
- -- Register 13 nodes for each tier; each node has a different texture set to show the charge level.
- for i = 0, 12, 1 do
- -- Which function table are we operating on?
- local functable = _G["bat2_" .. v.tier]
- minetest.register_node(":bat2:bt" .. i .. "_" .. v.tier, {
- drawtype = "nodebox",
- description = v.title .. " Battery Box",
- tiles = {
- "technic_" .. v.tier .. "_battery_box_top.png",
- "technic_" .. v.tier .. "_battery_box_bottom.png",
- "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
- "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
- "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
- "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
- },
- groups = utility.dig_groups("machine"),
- paramtype = "light",
- paramtype2 = "facedir",
- is_ground_content = false,
- sounds = default.node_sound_metal_defaults(),
- drop = "bat2:bt0_" .. v.tier,
- node_box = {
- type = "fixed",
- fixed = nodebox,
- },
- selection_box = {
- type = "fixed",
- fixed = selectbox,
- },
- on_energy_put = function(...)
- return functable.on_energy_put(...) end,
- on_energy_get = function(...)
- return functable.on_energy_get(...) end,
- on_punch = function(...)
- return functable.on_punch(...) end,
- can_dig = function(...)
- return functable.can_dig(...) end,
- on_timer = function(...)
- return functable.on_timer(...) end,
- on_construct = function(...)
- return functable.on_construct(...) end,
- on_destruct = function(...)
- return functable.on_destruct(...) end,
- after_place_node = function(...)
- return functable.after_place_node(...) end,
- on_metadata_inventory_move = function(...)
- return functable.on_metadata_inventory_move(...) end,
- on_metadata_inventory_put = function(...)
- return functable.on_metadata_inventory_put(...) end,
- on_metadata_inventory_take = function(...)
- return functable.on_metadata_inventory_take(...) end,
- on_blast = function(...)
- return functable.on_blast(...) end,
- on_rotate = function(...)
- return screwdriver.rotate_simple(...) end,
- allow_metadata_inventory_put = function(...)
- return functable.allow_metadata_inventory_put(...) end,
- allow_metadata_inventory_move = function(...)
- return functable.allow_metadata_inventory_move(...) end,
- allow_metadata_inventory_take = function(...)
- return functable.allow_metadata_inventory_take(...) end,
- })
- end
- end
- local c = "bat2:core"
- local f = battery.modpath .. "/bat2.lua"
- reload.register_file(c, f, false)
- bat2.run_once = true
- end
|