Vanessa Ezekowitz
2017-04-11 a3a959ab5e98308dabb81e920967bb52d19109a7
commit | author | age
ee0765 1
338f3b 2 local digilines_path = minetest.get_modpath("digilines")
D 3
be2f30 4 local S = technic.getter
a3a959 5 local tube_entry = "^pipeworks_tube_connection_metallic.png"
ee0765 6
7244f8 7 local fs_helpers = pipeworks.fs_helpers
VE 8
354ee6 9 technic.register_power_tool("technic:battery", 10000)
1b7fa3 10 technic.register_power_tool("technic:red_energy_crystal", 50000)
BM 11 technic.register_power_tool("technic:green_energy_crystal", 150000)
12 technic.register_power_tool("technic:blue_energy_crystal", 450000)
354ee6 13
S 14 minetest.register_craft({
15     output = 'technic:battery',
16     recipe = {
17         {'group:wood', 'default:copper_ingot', 'group:wood'},
18         {'group:wood', 'moreores:tin_ingot',   'group:wood'},
19         {'group:wood', 'default:copper_ingot', 'group:wood'},
20     }
21 })
22
23 minetest.register_tool("technic:battery", {
24     description = S("RE Battery"),
25     inventory_image = "technic_battery.png",
99fd5d 26     wear_represents = "technic_RE_charge",
00d7c9 27     on_refill = technic.refill_RE_charge,
354ee6 28     tool_capabilities = {
S 29         charge = 0,
30         max_drop_level = 0,
31         groupcaps = {
32             fleshy = {times={}, uses=10000, maxlevel=0}
33         }
34     }
35 })
36
6a0807 37 local tube = {
N 38     insert_object = function(pos, node, stack, direction)
39         if direction.y == 0 then
40             return stack
41         end
42         local meta = minetest.get_meta(pos)
43         local inv = meta:get_inventory()
44         if direction.y > 0 then
45             return inv:add_item("src", stack)
46         else
47             return inv:add_item("dst", stack)
48         end
49     end,
50     can_insert = function(pos, node, stack, direction)
51         if direction.y == 0 then
52             return false
53         end
54         local meta = minetest.get_meta(pos)
55         local inv = meta:get_inventory()
56         if direction.y > 0 then
7244f8 57             if meta:get_int("split_src_stacks") == 1 then
VE 58                 stack = stack:peek_item(1)
59             end
60             return inv:room_for_item("src", stack)
6a0807 61         else
7244f8 62             if meta:get_int("split_dst_stacks") == 1 then
VE 63                 stack = stack:peek_item(1)
64             end
65             return inv:room_for_item("dst", stack)
6a0807 66         end
N 67     end,
68     connect_sides = {left=1, right=1, back=1, top=1, bottom=1},
69 }
7244f8 70
VE 71 local function add_on_off_buttons(meta, ltier, charge_percent)
72     local formspec = ""
73     if ltier == "mv" or ltier == "hv" then
74         formspec = "image[1,1;1,2;technic_power_meter_bg.png"
75             .."^[lowpart:"..charge_percent
76             ..":technic_power_meter_fg.png]"..
77             fs_helpers.cycling_button(
78                 meta,
79                 "image_button[3,2.0;1,0.6",
80                 "split_src_stacks",
81                 {
82                     {text="", texture="pipeworks_button_off.png", addopts="false;false;pipeworks_button_interm.png"},
83                     {text="", texture="pipeworks_button_on.png",  addopts="false;false;pipeworks_button_interm.png"}
84                 }
85             ).."label[3.9,2.01;Allow splitting incoming 'charge' stacks from tubes]"..
86             fs_helpers.cycling_button(
87                 meta,
88                 "image_button[3,2.5;1,0.6",
89                 "split_dst_stacks",
90                 {
91                     {text="", texture="pipeworks_button_off.png", addopts="false;false;pipeworks_button_interm.png"},
92                     {text="", texture="pipeworks_button_on.png",  addopts="false;false;pipeworks_button_interm.png"}
93                 }
94             ).."label[3.9,2.51;Allow splitting incoming 'discharge' stacks]"
95     end
96     return formspec
97 end
354ee6 98
ee0765 99 function technic.register_battery_box(data)
S 100     local tier = data.tier
101     local ltier = string.lower(tier)
be2f30 102
76a8ac 103     local formspec =
338f3b 104         "size[8,9]"..
be2f30 105         "image[1,1;1,2;technic_power_meter_bg.png]"..
338f3b 106         "list[context;src;3,1;1,1;]"..
be2f30 107         "image[4,1;1,1;technic_battery_reload.png]"..
338f3b 108         "list[context;dst;5,1;1,1;]"..
be2f30 109         "label[0,0;"..S("%s Battery Box"):format(tier).."]"..
S 110         "label[3,0;"..S("Charge").."]"..
111         "label[5,0;"..S("Discharge").."]"..
112         "label[1,3;"..S("Power level").."]"..
d732c8 113         "list[current_player;main;0,5;8,4;]"..
338f3b 114         "listring[context;dst]"..
d732c8 115         "listring[current_player;main]"..
338f3b 116         "listring[context;src]"..
d732c8 117         "listring[current_player;main]"
7244f8 118
338f3b 119     if digilines_path then
D 120         formspec = formspec.."button[0.6,3.7;2,1;edit_channel;edit Channel]"
121     end
d732c8 122
6a0807 123     if data.upgrade then
N 124         formspec = formspec..
338f3b 125             "list[context;upgrade1;3.5,3;1,1;]"..
D 126             "list[context;upgrade2;4.5,3;1,1;]"..
d732c8 127             "label[3.5,4;"..S("Upgrade Slots").."]"..
338f3b 128             "listring[context;upgrade1]"..
d732c8 129             "listring[current_player;main]"..
338f3b 130             "listring[context;upgrade2]"..
d732c8 131             "listring[current_player;main]"
6a0807 132     end
ee0765 133
563a4c 134     local run = function(pos, node)
N 135         local meta           = minetest.get_meta(pos)
136         local eu_input       = meta:get_int(tier.."_EU_input")
137         local current_charge = meta:get_int("internal_EU_charge")
138
139         local EU_upgrade, tube_upgrade = 0, 0
140         if data.upgrade then
141             EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
142         end
143         local max_charge = data.max_charge * (1 + EU_upgrade / 10)
338f3b 144
563a4c 145         -- Charge/discharge the battery with the input EUs
N 146         if eu_input >= 0 then
147             current_charge = math.min(current_charge + eu_input, max_charge)
148         else
149             current_charge = math.max(current_charge + eu_input, 0)
150         end
151
152         -- Charging/discharging tools here
153         local tool_full, tool_empty
154         current_charge, tool_full = technic.charge_tools(meta,
155                 current_charge, data.charge_step)
156         current_charge, tool_empty = technic.discharge_tools(meta,
157                 current_charge, data.discharge_step,
158                 max_charge)
338f3b 159
563a4c 160         if data.tube then
N 161             local inv = meta:get_inventory()
162             technic.handle_machine_pipeworks(pos, tube_upgrade,
163             function(pos, x_velocity, z_velocity)
164                 if tool_full and not inv:is_empty("src") then
165                     technic.send_items(pos, x_velocity, z_velocity, "src")
166                 elseif tool_empty and not inv:is_empty("dst") then
167                     technic.send_items(pos, x_velocity, z_velocity, "dst")
168                 end
169             end)
170         end
171
172         -- We allow batteries to charge on less than the demand
173         meta:set_int(tier.."_EU_demand",
174                 math.min(data.charge_rate, max_charge - current_charge))
175         meta:set_int(tier.."_EU_supply",
176                 math.min(data.discharge_rate, current_charge))
177             meta:set_int("internal_EU_charge", current_charge)
178
179         -- Select node textures
180         local charge_count = math.ceil((current_charge / max_charge) * 8)
181         charge_count = math.min(charge_count, 8)
182         charge_count = math.max(charge_count, 0)
183         local last_count = meta:get_float("last_side_shown")
184         if charge_count ~= last_count then
185             technic.swap_node(pos,"technic:"..ltier.."_battery_box"..charge_count)
186             meta:set_float("last_side_shown", charge_count)
187         end
188
189         local charge_percent = math.floor(current_charge / max_charge * 100)
7244f8 190         meta:set_string("formspec", formspec..add_on_off_buttons(meta, ltier, charge_percent))
4b1798 191         local infotext = S("@1 Battery Box: @2/@3", tier,
85a984 192                 technic.pretty_num(current_charge), technic.pretty_num(max_charge))
563a4c 193         if eu_input == 0 then
N 194             infotext = S("%s Idle"):format(infotext)
195         end
196         meta:set_string("infotext", infotext)
197     end
338f3b 198
ee0765 199     for i = 0, 8 do
83c649 200         local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
S 201                 technic_machine=1, ["technic_"..ltier]=1}
ee0765 202         if i ~= 0 then
S 203             groups.not_in_creative_inventory = 1
204         end
338f3b 205
6a0807 206         if data.tube then
N 207             groups.tubedevice = 1
208             groups.tubedevice_receiver = 1
209         end
338f3b 210
a3a959 211         local tentry = tube_entry
VE 212         if ltier == "lv" then
213             tentry = ""
214         end
215
ee0765 216         minetest.register_node("technic:"..ltier.."_battery_box"..i, {
be2f30 217             description = S("%s Battery Box"):format(tier),
338f3b 218             tiles = {
a3a959 219                 "technic_"..ltier.."_battery_box_top.png"..tentry,
VE 220                 "technic_"..ltier.."_battery_box_bottom.png"..tentry,
338f3b 221                 "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png",
D 222                 "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png",
223                 "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png",
224                 "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png"},
ee0765 225             groups = groups,
83c649 226             connect_sides = {"bottom"},
6a0807 227             tube = data.tube and tube or nil,
N 228             paramtype2 = "facedir",
ee0765 229             sounds = default.node_sound_wood_defaults(),
S 230             drop = "technic:"..ltier.."_battery_box0",
231             on_construct = function(pos)
232                 local meta = minetest.get_meta(pos)
7244f8 233                 local EU_upgrade, tube_upgrade = 0, 0
VE 234                 if data.upgrade then
235                     EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
236                 end
237                 local max_charge = data.max_charge * (1 + EU_upgrade / 10)
238                 local charge = meta:get_int("internal_EU_charge")
239                 local cpercent = math.floor(charge / max_charge * 100)
ee0765 240                 local inv = meta:get_inventory()
S 241                 local node = minetest.get_node(pos)
76a8ac 242                 meta:set_string("infotext", S("%s Battery Box"):format(tier))
7244f8 243                 meta:set_string("formspec", formspec..add_on_off_buttons(meta, ltier, cpercent))
338f3b 244                 meta:set_string("channel", ltier.."_battery_box"..minetest.pos_to_string(pos))
76a8ac 245                 meta:set_int(tier.."_EU_demand", 0)
S 246                 meta:set_int(tier.."_EU_supply", 0)
247                 meta:set_int(tier.."_EU_input",  0)
ee0765 248                 meta:set_float("internal_EU_charge", 0)
S 249                 inv:set_size("src", 1)
250                 inv:set_size("dst", 1)
6a0807 251                 inv:set_size("upgrade1", 1)
N 252                 inv:set_size("upgrade2", 1)
ee0765 253             end,
0809dd 254             can_dig = technic.machine_can_dig,
S 255             allow_metadata_inventory_put = technic.machine_inventory_put,
256             allow_metadata_inventory_take = technic.machine_inventory_take,
257             allow_metadata_inventory_move = technic.machine_inventory_move,
563a4c 258             technic_run = run,
011397 259             after_place_node = data.tube and pipeworks.after_place,
338f3b 260             after_dig_node = technic.machine_after_dig_node,
D 261             on_receive_fields = function(pos, formname, fields, sender)
3f8478 262                 local meta = minetest.get_meta(pos)
7244f8 263                 local nodename = minetest.get_node(pos).name
VE 264                 if fields.edit_channel then
265                     minetest.show_formspec(sender:get_player_name(),
338f3b 266                         "technic:battery_box_edit_channel"..minetest.pos_to_string(pos),
D 267                         "field[channel;Digiline Channel;"..meta:get_string("channel").."]")
7244f8 268                 elseif fields["fs_helpers_cycling:0:split_src_stacks"]
VE 269                   or   fields["fs_helpers_cycling:0:split_dst_stacks"]
270                   or   fields["fs_helpers_cycling:1:split_src_stacks"]
271                   or   fields["fs_helpers_cycling:1:split_dst_stacks"] then
272                     local meta = minetest.get_meta(pos)
273                     if not pipeworks.may_configure(pos, sender) then return end
274                     fs_helpers.on_receive_fields(pos, fields)
275                     local EU_upgrade, tube_upgrade = 0, 0
276                     if data.upgrade then
277                         EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
278                     end
279                     local max_charge = data.max_charge * (1 + EU_upgrade / 10)
280                     local charge = meta:get_int("internal_EU_charge")
281                     local cpercent = math.floor(charge / max_charge * 100)
282                     meta:set_string("formspec", formspec..add_on_off_buttons(meta, ltier, cpercent))
283                 end
338f3b 284             end,
D 285             digiline = {
286                 receptor = {action = function() end},
287                 effector = {
288                     action = function(pos, node, channel, msg)
289                         if msg ~= "GET" and msg ~= "get" then
290                             return
291                         end
292                         local meta = minetest.get_meta(pos)
293                         if channel ~= meta:get_string("channel") then
294                             return
295                         end
296                         local inv = meta:get_inventory()
297                         digilines.receptor_send(pos, digilines.rules.default, channel, {
298                             demand = meta:get_int(tier.."_EU_demand"),
299                             supply = meta:get_int(tier.."_EU_supply"),
300                             input  = meta:get_int(tier.."_EU_input"),
301                             charge = meta:get_int("internal_EU_charge"),
302                             max_charge = data.max_charge * (1 + technic.handle_machine_upgrades(meta) / 10),
303                             src      = inv:get_stack("src", 1):to_table(),
304                             dst      = inv:get_stack("dst", 1):to_table(),
305                             upgrade1 = inv:get_stack("upgrade1", 1):to_table(),
306                             upgrade2 = inv:get_stack("upgrade2", 1):to_table()
307                         })
308                     end
309                 },
310             },
ee0765 311         })
S 312     end
313
314     -- Register as a battery type
315     -- Battery type machines function as power reservoirs and can both receive and give back power
316     for i = 0, 8 do
317         technic.register_machine(tier, "technic:"..ltier.."_battery_box"..i, technic.battery)
318     end
319
320 end -- End registration
321
338f3b 322 minetest.register_on_player_receive_fields(
D 323     function(player, formname, fields)
324         if formname:sub(1, 32) ~= "technic:battery_box_edit_channel" or
325                 not fields.channel then
326             return
327         end
328         local pos = minetest.string_to_pos(formname:sub(33))
329         local plname = player:get_player_name()
330         if minetest.is_protected(pos, plname) then
331             minetest.record_protection_violation(pos, plname)
332             return
333         end
334         local meta = minetest.get_meta(pos)
335         meta:set_string("channel", fields.channel)
336     end
337 )
ee0765 338
eac484 339 function technic.charge_tools(meta, batt_charge, charge_step)
ee0765 340     local inv = meta:get_inventory()
eac484 341     if inv:is_empty("src") then
6a0807 342         return batt_charge, false
ee0765 343     end
5382a8 344     local src_stack = inv:get_stack("src", 1)
eac484 345
5382a8 346     local tool_name = src_stack:get_name()
S 347     if not technic.power_tools[tool_name] then
6a0807 348         return batt_charge, false
eac484 349     end
S 350     -- Set meta data for the tool if it didn't do it itself
5382a8 351     local src_meta = minetest.deserialize(src_stack:get_metadata()) or {}
eac484 352     if not src_meta.charge then
S 353         src_meta.charge = 0
354     end
355     -- Do the charging
5382a8 356     local item_max_charge = technic.power_tools[tool_name]
eac484 357     local tool_charge     = src_meta.charge
6a0807 358     if tool_charge >= item_max_charge then
N 359         return batt_charge, true
360     elseif batt_charge <= 0 then
361         return batt_charge, false
eac484 362     end
S 363     charge_step = math.min(charge_step, batt_charge)
364     charge_step = math.min(charge_step, item_max_charge - tool_charge)
365     tool_charge = tool_charge + charge_step
366     batt_charge = batt_charge - charge_step
5382a8 367     technic.set_RE_wear(src_stack, tool_charge, item_max_charge)
eac484 368     src_meta.charge = tool_charge
5382a8 369     src_stack:set_metadata(minetest.serialize(src_meta))
S 370     inv:set_stack("src", 1, src_stack)
6a0807 371     return batt_charge, (tool_charge == item_max_charge)
ee0765 372 end
S 373
374
eac484 375 function technic.discharge_tools(meta, batt_charge, charge_step, max_charge)
ee0765 376     local inv = meta:get_inventory()
eac484 377     if inv:is_empty("dst") then
6a0807 378         return batt_charge, false
ee0765 379     end
eac484 380     srcstack = inv:get_stack("dst", 1)
S 381     local toolname = srcstack:get_name()
382     if technic.power_tools[toolname] == nil then
6a0807 383         return batt_charge, false
eac484 384     end
S 385     -- Set meta data for the tool if it didn't do it itself :-(
5cf765 386     local src_meta = minetest.deserialize(srcstack:get_metadata())
eac484 387     src_meta = src_meta or {}
S 388     if not src_meta.charge then
389         src_meta.charge = 0
390     end
391
392     -- Do the discharging
393     local item_max_charge = technic.power_tools[toolname]
394     local tool_charge     = src_meta.charge
6a0807 395     if tool_charge <= 0 then
N 396         return batt_charge, true
397     elseif batt_charge >= max_charge then
398         return batt_charge, false
eac484 399     end
S 400     charge_step = math.min(charge_step, max_charge - batt_charge)
401     charge_step = math.min(charge_step, tool_charge)
402     tool_charge = tool_charge - charge_step
403     batt_charge = batt_charge + charge_step
404     technic.set_RE_wear(srcstack, tool_charge, item_max_charge)
405     src_meta.charge = tool_charge
5cf765 406     srcstack:set_metadata(minetest.serialize(src_meta))
eac484 407     inv:set_stack("dst", 1, srcstack)
6a0807 408     return batt_charge, (tool_charge == 0)
ee0765 409 end
S 410