From b79f21f8f323023a27f699d2724de7cd8e1febe7 Mon Sep 17 00:00:00 2001 From: Desour Date: Thu, 8 Apr 2021 18:24:31 +0200 Subject: [PATCH] Add transistors --- mesecons_transistors/init.lua | 499 ++++++++++++++++++ mesecons_transistors/mod.conf | 2 + .../mesecons_transistors_basepattern.png | Bin 0 -> 5285 bytes .../mesecons_transistors_nc_closed.png | Bin 0 -> 5500 bytes .../textures/mesecons_transistors_nc_open.png | Bin 0 -> 5563 bytes .../mesecons_transistors_no_closed.png | Bin 0 -> 5581 bytes .../textures/mesecons_transistors_no_open.png | Bin 0 -> 5514 bytes .../mesecons_transistors_switcher_mask.png | Bin 0 -> 4835 bytes .../mesecons_transistors_wire_mask.png | Bin 0 -> 4696 bytes 9 files changed, 501 insertions(+) create mode 100644 mesecons_transistors/init.lua create mode 100644 mesecons_transistors/mod.conf create mode 100644 mesecons_transistors/textures/mesecons_transistors_basepattern.png create mode 100644 mesecons_transistors/textures/mesecons_transistors_nc_closed.png create mode 100644 mesecons_transistors/textures/mesecons_transistors_nc_open.png create mode 100644 mesecons_transistors/textures/mesecons_transistors_no_closed.png create mode 100644 mesecons_transistors/textures/mesecons_transistors_no_open.png create mode 100644 mesecons_transistors/textures/mesecons_transistors_switcher_mask.png create mode 100644 mesecons_transistors/textures/mesecons_transistors_wire_mask.png diff --git a/mesecons_transistors/init.lua b/mesecons_transistors/init.lua new file mode 100644 index 0000000..76273c5 --- /dev/null +++ b/mesecons_transistors/init.lua @@ -0,0 +1,499 @@ +local node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, + }, +} + +local function rotate_rules(node, rules) + for rotations = 0, node.param2 - 1 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local function get_switcher_inputrules(node) + return rotate_rules(node, {{x = 0, y = 0, z = -1}, {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}}) +end + +local function get_conductorrules(node) + return rotate_rules(node, {{x = 1, y = 0, z = 0}, {x = -1, y = 0, z = 0}}) +end + +local function get_dir_to_switcher(node) + return rotate_rules(node, {{x = 0, y = 0, z = -1}})[1] +end + +local function get_dir_to_switched(node) + return rotate_rules(node, {{x = 0, y = 0, z = 1}})[1] +end + +local is_transistor_node = { + ["mesecons_transistors:normally_open_contact_open"] = true, + ["mesecons_transistors:normally_open_contact_closed_off" ] = true, + ["mesecons_transistors:normally_open_contact_closed_on" ] = true, + ["mesecons_transistors:normally_closed_contact_open" ] = true, + ["mesecons_transistors:normally_closed_contact_closed_off"] = true, + ["mesecons_transistors:normally_closed_contact_closed_on"] = true, +} + +local function handle_overheat(pos, node) + local conductor_pos = vector.add(pos, get_dir_to_switched(node)) + local conductor_node = mesecon.get_node_force(conductor_pos) + + if not conductor_node or conductor_node.param2 ~= node.param2 or + not is_transistor_node[conductor_node.name] then + minetest.remove_node(pos) + mesecon.on_dignode(pos, node) + return + end + + minetest.remove_node(pos) + minetest.remove_node(conductor_pos) + + mesecon.on_dignode(pos, node) + mesecon.on_dignode(conductor_pos, conductor_node) + + minetest.add_item(conductor_pos, minetest.registered_nodes[conductor_node.name].drop) +end + +local function switcher_on(pos, node) + if mesecon.do_overheat(pos) then + handle_overheat(pos, node) + return + end + + node.name = "mesecons_transistors:switcher_on" + minetest.swap_node(pos, node) + + local dir = get_dir_to_switched(node) + local switched_pos = vector.add(pos, dir) + local switched_node = mesecon.get_node_force(switched_pos) + if not switched_node then + return + end + local old_switched_node = {name = switched_node.name, param1 = switched_node.param1, + param2 = switched_node.param2} + + if switched_node.name == "mesecons_transistors:normally_open_contact_open" then + switched_node.name = "mesecons_transistors:normally_open_contact_closed_off" + elseif switched_node.name == "mesecons_transistors:normally_closed_contact_closed_off" or + switched_node.name == "mesecons_transistors:normally_closed_contact_closed_on" then + switched_node.name = "mesecons_transistors:normally_closed_contact_open" + else + minetest.log("info", "invalid mesecons_transistors:swicher was triggered at " + .. minetest.pos_to_string(pos) .. ", node at front is " .. switched_node.name) + return + end + if old_switched_node.param2 ~= node.param2 then + minetest.log("info", "invalid mesecons_transistors:swicher was triggered at " + .. minetest.pos_to_string(pos) .. ", node at front is from another switcher") + return + end + + minetest.swap_node(switched_pos, switched_node) + mesecon.on_dignode(switched_pos, old_switched_node) + mesecon.on_placenode(switched_pos, switched_node) +end + +local function switcher_off(pos, node) + if mesecon.do_overheat(pos) then + handle_overheat(pos, node) + return + end + + node.name = "mesecons_transistors:switcher_off" + minetest.swap_node(pos, node) + + local dir = get_dir_to_switched(node) + local switched_pos = vector.add(pos, dir) + local switched_node = mesecon.get_node_force(switched_pos) + if not switched_node then + return + end + local old_switched_node = {name = switched_node.name, param1 = switched_node.param1, + param2 = switched_node.param2} + + if switched_node.name == "mesecons_transistors:normally_open_contact_closed_off" or + switched_node.name == "mesecons_transistors:normally_open_contact_closed_on" then + switched_node.name = "mesecons_transistors:normally_open_contact_open" + elseif switched_node.name == "mesecons_transistors:normally_closed_contact_open" then + switched_node.name = "mesecons_transistors:normally_closed_contact_closed_off" + else + minetest.log("info", "invalid mesecons_transistors:swicher was triggered at " + .. minetest.pos_to_string(pos) .. ", node at front is " .. switched_node.name) + return + end + if old_switched_node.param2 ~= node.param2 then + minetest.log("info", "invalid mesecons_transistors:swicher was triggered at " + .. minetest.pos_to_string(pos) .. ", node at front is from another switcher") + return + end + + minetest.swap_node(switched_pos, switched_node) + mesecon.on_dignode(switched_pos, old_switched_node) + mesecon.on_placenode(switched_pos, switched_node) +end + +local function do_nothing() + -- nothing +end + +-- returns a fuction for on_place +-- does pretty much the same as minetest.item_place, but also places the switcher +local function get_on_place_callback(is_nc) + return function(itemstack, placer, pointed_thing) + -- Call on_rightclick if the pointed node defines it + if pointed_thing.type == "node" and placer and + not placer:get_player_control().sneak then + local n = minetest.get_node(pointed_thing.under) + local nn = n.name + if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then + return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, n, + placer, itemstack, pointed_thing) or itemstack + end + end + + if pointed_thing.type ~= "node" then + return itemstack + end + + local nodename = is_nc and "mesecons_transistors:normally_closed_contact_closed_off" or + "mesecons_transistors:normally_open_contact_open" + + local under = pointed_thing.under + local oldnode_under = minetest.get_node_or_nil(under) + local above = pointed_thing.above + local oldnode_above = minetest.get_node_or_nil(above) + local playername = placer and placer:get_player_name() or "" + local log = playername ~= "" and minetest.log or do_nothing + + if not oldnode_under or not oldnode_above then + log("info", playername .. " tried to place" + .. " node in unloaded position " .. minetest.pos_to_string(above)) + return itemstack + end + + local olddef_under = minetest.registered_nodes[oldnode_under.name] + olddef_under = olddef_under or minetest.nodedef_default + local olddef_above = minetest.registered_nodes[oldnode_above.name] + olddef_above = olddef_above or minetest.nodedef_default + + if not olddef_above.buildable_to and not olddef_under.buildable_to then + log("info", playername .. " tried to place node in invalid position " .. + minetest.pos_to_string(above) .. ", replacing " .. + oldnode_above.name) + return itemstack + end + + -- Place above pointed node + local place_to = vector.new(above) + local oldnode = oldnode_above + + -- If node under is buildable_to, place into it instead (eg. snow) + if olddef_under.buildable_to then + log("info", "node under is buildable to") + place_to = vector.new(under) + oldnode = oldnode_under + end + + local newnode = {name = nodename, param1 = 0, param2 = 0} + + -- Calculate direction + local placer_pos = placer and placer:get_pos() + if placer_pos then + local dir = vector.subtract(above, placer_pos) + newnode.param2 = minetest.dir_to_facedir(dir) + log("info", "facedir: " .. newnode.param2) + end + + -- pos for switcher + local switcher_dir = get_dir_to_switcher(newnode) + local switcher_pos = vector.add(place_to, switcher_dir) + + local switcher_name = "mesecons_transistors:switcher_off" + local switcher_node = {name = switcher_name, param1 = 0, param2 = newnode.param2} + local switcher_pointed_thing = {type = "node", above = vector.add(above, switcher_dir), + under = vector.add(under, switcher_dir)} + + -- check if switcher pos is loaded and buildable to + local switcher_oldnode = minetest.get_node_or_nil(switcher_pos) + if not oldnode_under or not oldnode_above then + log("info", playername .. " tried to place node in unloaded position " .. + minetest.pos_to_string(switcher_pos)) + return itemstack + end + local switcher_oldnode_def = minetest.registered_nodes[switcher_oldnode.name] + switcher_oldnode_def = switcher_oldnode_def or minetest.nodedef_default + if not switcher_oldnode_def.buildable_to then + log("info", playername .. " tried to place node in invalid position " .. + minetest.pos_to_string(switcher_pos) .. ", replacing " .. + switcher_oldnode.name) + return itemstack + end + + -- check protection + if minetest.is_protected(place_to, playername) then + log("action", playername .. " tried to place " .. nodename .. + " at protected position " .. minetest.pos_to_string(place_to)) + minetest.record_protection_violation(place_to, playername) + return itemstack + end + if minetest.is_protected(switcher_pos, playername) then + log("action", playername .. " tried to place " .. switcher_name .. + " at protected position " .. minetest.pos_to_string(switcher_pos)) + minetest.record_protection_violation(switcher_pos, playername) + return itemstack + end + + log("action", playername .. " places node " .. nodename .. " at " .. + minetest.pos_to_string(place_to)) + + -- Add nodes and update + minetest.set_node(place_to, newnode) + minetest.set_node(switcher_pos, switcher_node) + + -- Play sound if it was done by a player + if playername ~= "" then + local sounds = default.node_sound_stone_defaults() + minetest.sound_play(sounds.place, { + pos = place_to, + exclude_player = playername, + }, true) + end + + local take_item = true + + -- Run script hook + for _, callback in ipairs(core.registered_on_placenodes) do + -- Deepcopy pos, node and pointed_thing because callback can modify them + local place_to_copy = vector.new(place_to) + local newnode_copy = {name = newnode.name, param1 = newnode.param1, param2 = newnode.param2} + local oldnode_copy = {name = oldnode.name, param1 = oldnode.param1, param2 = oldnode.param2} + local pointed_thing_copy = {type = "node", above = vector.new(above), under = vector.new(under)} + if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then + take_item = false + end + end + for _, callback in ipairs(core.registered_on_placenodes) do + -- Deepcopy pos, node and pointed_thing because callback can modify them + local place_to_copy = vector.new(switcher_pos) + local newnode_copy = {name = switcher_node.name, param1 = switcher_node.param1, param2 = switcher_node.param2} + local oldnode_copy = {name = switcher_oldnode.name, param1 = switcher_oldnode.param1, param2 = switcher_oldnode.param2} + local pointed_thing_copy = {type = "node", above = vector.new(switcher_pointed_thing.above), + under = vector.new(switcher_pointed_thing.under)} + if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then + take_item = false + end + end + + if take_item then + itemstack:take_item() + end + return itemstack + end +end + +local function transistor_after_dig_node(pos, oldnode, _, _) + local switcher_pos = vector.add(pos, get_dir_to_switcher(oldnode)) + local old_switcher_node = mesecon.get_node_force(switcher_pos) + if not old_switcher_node or old_switcher_node.param2 ~= oldnode.param2 or + (old_switcher_node.name ~= "mesecons_transistors:switcher_off" and + old_switcher_node.name ~= "mesecons_transistors:switcher_on") then + return + end + minetest.remove_node(switcher_pos) + mesecon.do_cooldown(switcher_pos) + mesecon.on_dignode(pos, old_switcher_node) +end + +local function switcher_on_dig(pos, node, digger) + local conductor_pos = vector.add(pos, get_dir_to_switched(node)) + local conductor_node = mesecon.get_node_force(conductor_pos) + if not conductor_node or conductor_node.param2 ~= node.param2 or + not is_transistor_node[conductor_node.name] then + return false + end + return minetest.node_dig(conductor_pos, conductor_node, digger) +end + +local function generate_tiles(is_nc, is_closed, is_on) + local tiles = { + "jeija_microcontroller_bottom.png^mesecons_transistors_basepattern.png".. + "^(mesecons_wire_off.png^[mask:mesecons_transistors_wire_mask.png)".. + "^mesecons_transistors_no_open.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png^jeija_gate_side_output_off.png", + "jeija_microcontroller_bottom.png^jeija_gate_side_output_off.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png^jeija_gate_side_output_off.png", + } + + -- conductor wire + local is_on_str = is_on and "on" or "off" + tiles[1] = tiles[1] .. "^(mesecons_wire_" .. is_on_str .. + ".png^[mask:mesecons_transistors_wire_mask.png)" + tiles[3] = tiles[3] .. "^jeija_gate_side_output_" .. is_on_str .. ".png" + tiles[4] = tiles[4] .. "^jeija_gate_side_output_" .. is_on_str .. ".png" + + -- effector wire and closed/opened stuff + tiles[1] = tiles[1] .. "^mesecons_transistors_" .. (is_nc and "nc" or "no") + .. "_" .. (is_closed and "closed" or "open") .. ".png" + tiles[6] = tiles[6] .. "^jeija_gate_side_output_" .. + (is_nc == is_closed and "off" or "on") .. ".png" + + return tiles +end + +mesecon.register_node("mesecons_transistors:switcher", { + description = "You hacker you!", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + node_box = node_box, + sounds = default.node_sound_stone_defaults(), + groups = {dig_immediate = 2, not_in_creative_inventory = 1, overheat = 1}, + drop = "", + on_dig = switcher_on_dig, + on_rotate = false, +}, { + tiles = { + "jeija_microcontroller_bottom.png".. + "^(mesecons_wire_off.png^[mask:mesecons_transistors_switcher_mask.png)", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png^jeija_gate_side_output_off.png", + "jeija_microcontroller_bottom.png", + }, + mesecons = {effector = { + rules = get_switcher_inputrules, + action_on = switcher_on, + }}, +}, { + tiles = { + "jeija_microcontroller_bottom.png".. + "^(mesecons_wire_on.png^[mask:mesecons_transistors_switcher_mask.png)", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_bottom.png^jeija_gate_side_output_on.png", + "jeija_microcontroller_bottom.png", + }, + mesecons = {effector = { + rules = get_switcher_inputrules, + action_off = switcher_off, + }} +}) + +minetest.register_node("mesecons_transistors:normally_open_contact_open", { + description = "N/O contact", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + node_box = node_box, + node_placement_prediction = "", + sounds = default.node_sound_stone_defaults(), + groups = {dig_immediate = 2}, + tiles = generate_tiles(false, false, false), + mesecons = {receptor = { -- pseudo-receptor to keep wires connected + state = mesecon.state.off, + rules = get_conductorrules, + }}, + on_place = get_on_place_callback(false), + after_dig_node = transistor_after_dig_node, + on_rotate = false, + on_blast = mesecon.on_blastnode, +}) + +mesecon.register_node("mesecons_transistors:normally_open_contact_closed", { + description = "N/O contact (You hacker you!)", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + drop = "mesecons_transistors:normally_open_contact_open", + node_box = node_box, + sounds = default.node_sound_stone_defaults(), + groups = {dig_immediate = 2, not_in_creative_inventory = 1}, + after_dig_node = transistor_after_dig_node, + on_rotate = false, +}, { + tiles = generate_tiles(false, true, false), + mesecons = {conductor = { + state = mesecon.state.off, + onstate = "mesecons_transistors:normally_open_contact_closed_on", + rules = get_conductorrules, + }}, +}, { + tiles = generate_tiles(false, true, true), + mesecons = {conductor = { + state = mesecon.state.on, + offstate = "mesecons_transistors:normally_open_contact_closed_off", + rules = get_conductorrules, + }}, +}) + +minetest.register_node("mesecons_transistors:normally_closed_contact_open", { + description = "N/C contact (You hacker you!)", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + drop = "mesecons_transistors:normally_closed_contact_closed_off", + node_box = node_box, + sounds = default.node_sound_stone_defaults(), + groups = {dig_immediate = 2, not_in_creative_inventory = 1}, + tiles = generate_tiles(true, false, false), + mesecons = {receptor = { -- pseudo-receptor to keep wires connected + state = mesecon.state.off, + rules = get_conductorrules, + }}, + after_dig_node = transistor_after_dig_node, + on_rotate = false, + on_blast = mesecon.on_blastnode, +}) + +mesecon.register_node("mesecons_transistors:normally_closed_contact_closed", { + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + drop = "mesecons_transistors:normally_closed_contact_closed_off", + node_box = node_box, + sounds = default.node_sound_stone_defaults(), + after_dig_node = transistor_after_dig_node, + on_rotate = false, +}, { + description = "N/C contact", + node_placement_prediction = "", + groups = {dig_immediate = 2}, + tiles = generate_tiles(true, true, false), + mesecons = {conductor = { + state = mesecon.state.off, + onstate = "mesecons_transistors:normally_closed_contact_closed_on", + rules = get_conductorrules, + }}, + on_place = get_on_place_callback(true), +}, { + description = "N/C contact (You hacker you!)", + groups = {dig_immediate = 2, not_in_creative_inventory = 1}, + tiles = generate_tiles(true, true, true), + mesecons = {conductor = { + state = mesecon.state.on, + offstate = "mesecons_transistors:normally_closed_contact_closed_off", + rules = get_conductorrules, + }}, +}) + +mesecon.register_mvps_stopper("mesecons_transistors:switcher_on") +mesecon.register_mvps_stopper("mesecons_transistors:switcher_off") +mesecon.register_mvps_stopper("mesecons_transistors:normally_open_contact_open") +mesecon.register_mvps_stopper("mesecons_transistors:normally_open_contact_closed_off") +mesecon.register_mvps_stopper("mesecons_transistors:normally_open_contact_closed_on") +mesecon.register_mvps_stopper("mesecons_transistors:normally_closed_contact_open") +mesecon.register_mvps_stopper("mesecons_transistors:normally_closed_contact_closed_off") +mesecon.register_mvps_stopper("mesecons_transistors:normally_closed_contact_closed_on") diff --git a/mesecons_transistors/mod.conf b/mesecons_transistors/mod.conf new file mode 100644 index 0000000..255dd81 --- /dev/null +++ b/mesecons_transistors/mod.conf @@ -0,0 +1,2 @@ +name = mesecons_transistors +depends = mesecons, default, mesecons_gates, mesecons_mvps diff --git a/mesecons_transistors/textures/mesecons_transistors_basepattern.png b/mesecons_transistors/textures/mesecons_transistors_basepattern.png new file mode 100644 index 0000000000000000000000000000000000000000..601a8eecf134d3a2c976bc71628a1105d1072161 GIT binary patch literal 5285 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 literal 0 HcmV?d00001 diff --git a/mesecons_transistors/textures/mesecons_transistors_no_closed.png b/mesecons_transistors/textures/mesecons_transistors_no_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..52eaa17bfd8e72db25eea0a8054d2f19b6770a07 GIT binary patch literal 5581 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 Hid_C*7L<3kfNTH8bOgL^7xZDDw47D=pH4^w}r zsG4@(tEr= zd$aw>!ga1Kuh&*jkJ@GUqi?69%eL9+i`QrQwvKn26ItahNyp2VHQc4lh=`Z`8-=9@AO z?2Wa57y23EWy`$xI5nZ>i#~VfZpW*8BmNRTPj2iImWwj#h3!v~_JmXBW8Y@9=@-_A zc2BqEq%7;cvnTuh;uk8KP5Fp37e@TKS;*NHve7wwrrTtxvgZ7S1A=A2#qS0&#GiKey)p4y*U+vnR?j2|-Z#F~Aaf3&8TPMo^$hyV3YmR= zPt4z#)}*c7kw&H+t=$^rxy$p4*;x|%U?$8~6-GQ?yyS7{9I4;NOkQVXeVX^H zo6kdDb-6`AxyFuw%7sS03)iV9!#$9i= zOo?hK_3a@Omyv}%4Rf+Nb@}3Srv%^FDdy~XCEeGPZh5X*?!9t-!=|gRo7`SFC60W3 z<-p^{1c#`m%C|FFuRG6`)+1|1UQUVhb%_gjwQ<({FCazkj-uZv(@7+&WTi+X2@;9k zodi(-S?e-|f!F6wEsy&7D}RqM3ddD9sss^^%X_ET)QK( zGp5>g#fm8xFFuL+W4g9*goAMJ)}!ZgDdHRn>F%A5{km&SaMgvjmvwh5ejkyMV-DqB zE17{T$$b=m$k>z6)7`l@VZFCPsyj?R9On)i)?_7UOyS~S0j5z=QMpEjQ%x!@Xj~+c zm$ylaVzIb^BEzGVY9Z8l=_*7~%7xI^Y%wC%itrd^V4@BWOAL`>iLn@84tdY9_c93p zfeJUE6q71WtrwVtkcC$O?g=vuqF5k?SRoWHmQX|*9Zq3USyTk}Hz^Ys&>VY;mrkw_ zg!;`Jpa4%oD8^vW3TQN=(MUBisTy50jn3!uX$XVHV88$Y>sPA{s0mi6BW7Qlq92oTy9_ZxBKdn5VppPo))$2kF)N0TqBAG!v?&(WwYcrJ@b>&>Q>{0Lef= zf9s)_g8ohm#r2wa9ftcS;A(^GPzpIV=&y~}#aYskV>CPtR{^LVtV;i2$$%iSWYB|< zAX=%?TD*YRA0Q1%#e1e)Bq%$-S;6BLv0s39;7BE1G#R5MK7Egp1D-of1?f8aFg5f=UjkSZo%HOQ&;S z9$z7YSsWf0MiG>tVj^4?i-9ZTh=ody3Fc{ZDimy|QiVq2G_5+?GC>F~@R0-wAqKS{ zYOzS-P=f+E2%%u5I^OgiDpjiRFat`cN$1eHJO-c5=J8nwpTT$!T8!)Tpb`mAIznZz zEHlKm2tYDGSd^$!Kwz4A2WmbH zU)BHAe+1%`mMIFwQnmsV>t95VCg5_*Lcp(o3X4J2(KtBY0|oWYuKc^r;-FlV!Q#Mt zI>v%oI0J)G1)T}Y7<3+!PFHYwvi`&e+4UNQ!HDW`pJPi8onL&O&Qr=B$g|p3d5>o2?7K{Zu=7C`g#<6N-s*Qt#1IZe(wmwi~jsza0 NApa0Qv+s%x{{@2*_1gdd literal 0 HcmV?d00001