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