From c4e381687dd4b1d5e249a7d2482af00feec3f109 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sat, 6 Feb 2021 17:20:45 +0100 Subject: [PATCH] Add TA4 recycle machine --- basic_machines/recycler.lua | 347 +++++++++++++++++++++++++++++ basis/recipe_lib.lua | 16 +- doc/items.lua | 2 + doc/manual_DE.lua | 15 ++ doc/manual_EN.lua | 16 ++ manuals/manual_ta4_DE.md | 14 ++ manuals/manual_ta4_EN.md | 16 ++ manuals/toc_DE.md | 3 +- manuals/toc_EN.md | 3 +- power/node_api.lua | 2 +- textures/techage_appl_recycler.png | Bin 0 -> 2013 bytes 11 files changed, 429 insertions(+), 5 deletions(-) create mode 100644 basic_machines/recycler.lua create mode 100644 textures/techage_appl_recycler.png diff --git a/basic_machines/recycler.lua b/basic_machines/recycler.lua new file mode 100644 index 0000000..5ede924 --- /dev/null +++ b/basic_machines/recycler.lua @@ -0,0 +1,347 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Recycler, recycling techage machines + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +-- Consumer Related Data +local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end + +local STANDBY_TICKS = 3 +local COUNTDOWN_TICKS = 4 +local CYCLE_TIME = 8 + +local Recipes = {} + +local SpecialItems = { + ["techage:sieved_gravel"] = "default:sand", + ["basic_materials:heating_element"] = "default:copper_ingot", + ["techage:ta4_wlanchip"] = "", + ["techage:basalt_cobble"] = "default:sand", + ["default:stone"] = "techage:sieved_gravel", + ["default:wood"] = "default:stick 5", + ["basic_materials:concrete_block"] = "techage:sieved_gravel", + ["dye:green"] = "", + ["dye:red"] = "", + ["dye:white"] = "", + ["dye:blue"] = "", + ["dye:brown"] = "", + ["dye:cyan"] = "", + ["dye:yellow"] = "", + ["dye:grey"] = "", + ["dye:orange"] = "", + ["dye:black"] = "", + ["techage:basalt_glass_thin"] = "", + ["group:stone"] = "techage:sieved_gravel", + ["basic_materials:plastic_sheet"] = "", + ["group:wood"] = "default:stick 5", + ["techage:basalt_glass"] = "", + ["default:junglewood"] = "default:stick 5", + ["techage:ta4_silicon_wafer"] = "", + ["default:cobble"] = "techage:sieved_gravel", + ["default:pick_diamond"] = "default:stick", + ["techage:hammer_steel"] = "default:stick", + ["default:paper"] = "", + ["stairs:slab_basalt_glass2"] = "", + ["techage:basalt_stone"] = "techage:sieved_gravel", + ["techage:ta4_ramchip"] = "", + ["protector:chest"] = "default:chest", + ["techage:ta4_rotor_blade"] = "", + ["techage:ta4_carbon_fiber"] = "", +} + +local function formspec(self, pos, nvm) + return "size[8,8]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;src;0,0;3,3;]".. + --"item_image[0,0;1,1;default:cobble]".. + "image[0,0;1,1;techage_form_mask.png]".. + "image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]".. + "image[3.5,1;1,1;techage_form_arrow.png]".. + "image_button[3.5,2;1,1;"..self:get_state_button_image(nvm)..";state_button;]".. + "tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]".. + "list[context;dst;5,0;3,3;]".. + --"item_image[5,0;1,1;default:gravel]".. + "image[5,0;1,1;techage_form_mask.png]".. + "list[current_player;main;0,4;8,4;]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4) +end + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + if listname == "src" then + CRD(pos).State:start_if_standby(pos) + end + return stack:get_count() +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + local inv = M(pos):get_inventory() + local stack = inv:get_stack(from_list, from_index) + return allow_metadata_inventory_put(pos, to_list, to_index, stack, player) +end + +local function allow_metadata_inventory_take(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() +end + +local function cook_reverse(stack, inv, idx, recipe) + -- check space + for _,item in ipairs(recipe.items) do + if not inv:room_for_item("dst", stack) then + return false + end + end + -- take item + inv:remove_item("src", ItemStack(recipe.output)) + -- add items + for _,item in ipairs(recipe.items) do + inv:add_item("dst", item) + end + return true +end + +local function get_recipe(stack) + local name = stack:get_name() + local recipe = Recipes[name] + print("get_recipe", name, dump(recipe)) + if recipe then + print("get_recipe", stack:get_count(), ItemStack(recipe.output):get_count()) + if stack:get_count() >= ItemStack(recipe.output):get_count() then + return recipe + end + end +end + +local function recycling(pos, crd, nvm, inv) + for idx,stack in ipairs(inv:get_list("src")) do + local recipe = not stack:is_empty() and get_recipe(stack) + if recipe then + if cook_reverse(stack, inv, idx, recipe) then + crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS) + else + crd.State:blocked(pos, nvm) + end + return + end + end + crd.State:idle(pos, nvm) +end + +local function keep_running(pos, elapsed) + local nvm = techage.get_nvm(pos) + local crd = CRD(pos) + local inv = M(pos):get_inventory() + recycling(pos, crd, nvm, inv) +end + +local function on_receive_fields(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + local nvm = techage.get_nvm(pos) + CRD(pos).State:state_button_event(pos, nvm, fields) +end + +local function can_dig(pos, player) + if minetest.is_protected(pos, player:get_player_name()) then + return false + end + local inv = M(pos):get_inventory() + return inv:is_empty("dst") and inv:is_empty("src") +end + + +local tiles = {} +-- '#' will be replaced by the stage number +-- '{power}' will be replaced by the power PNG +tiles.pas = { + -- up, down, right, left, back, front + "techage_appl_grinder.png^[colorize:@@000000:100^techage_frame_ta#_top.png", + --"techage_appl_grinder.png^techage_frame_ta#_top.png^[multiply:#FF0000", + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png", + "techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png", +} +tiles.act = { + -- up, down, right, left, back, front + { + image = "techage_appl_grinder4.png^[colorize:@@000000:100^techage_frame4_ta#_top.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 1.0, + }, + }, + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png", + "techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png", +} + +local tubing = { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + if meta:get_int("pull_dir") == in_dir then + local inv = M(pos):get_inventory() + return techage.get_items(pos, inv, "dst", num) + end + end, + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + if meta:get_int("push_dir") == in_dir or in_dir == 5 then + local inv = M(pos):get_inventory() + --CRD(pos).State:start_if_standby(pos) -- would need power! + return techage.put_items(inv, "src", stack) + end + end, + on_unpull_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + if meta:get_int("pull_dir") == in_dir then + local inv = M(pos):get_inventory() + return techage.put_items(inv, "dst", stack) + end + end, + on_recv_message = function(pos, src, topic, payload) + return CRD(pos).State:on_receive_message(pos, topic, payload) + end, +} + +local _, _, node_name_ta4 = + techage.register_consumer("recycler", S("Recycler"), tiles, { + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, 8/16, -6/16}, + {-8/16, -8/16, 6/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, -8/16, -6/16, 8/16, 8/16}, + { 6/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + {-6/16, -8/16, -6/16, 6/16, 6/16, 6/16}, + }, + }, + selection_box = { + type = "fixed", + fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + }, + cycle_time = CYCLE_TIME, + standby_ticks = STANDBY_TICKS, + formspec = formspec, + tubing = tubing, + after_place_node = function(pos, placer) + local inv = M(pos):get_inventory() + inv:set_size('src', 9) + inv:set_size('dst', 9) + end, + can_dig = can_dig, + node_timer = keep_running, + on_receive_fields = on_receive_fields, + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, + groups = {choppy=2, cracky=2, crumbly=2}, + sounds = default.node_sound_wood_defaults(), + num_items = {0,0,0,1}, + power_consumption = {0,0,0,16}, + }, + {false, false, false, true}) -- TA4 only + +minetest.register_craft({ + output = node_name_ta4, + recipe = { + {"", "default:mese_crystal", ""}, + {"", "techage:ta4_grinder_pas", ""}, + {"", "techage:ta4_wlanchip", ""}, + }, +}) + +------------------------------------------------------------------------------- +-- Prepare recipes +------------------------------------------------------------------------------- +-- Nodes from mods that can be recycled +local ModNames = { + techage = true, + hyperloop = true, +} + +local function get_item_list(inputs) + local lst = {} + for _,input in pairs(inputs or {}) do + if SpecialItems[input] then + input = SpecialItems[input] + end + if input and input ~= "" then + if minetest.registered_nodes[input] or minetest.registered_items[input] then + table.insert(lst, input) + end + end + end + return lst +end + +local function get_special_recipe(name) + if SpecialItems[name] then + return { + output = name, + items = {SpecialItems[name]} + } + end +end + +local function collect_recipes() + local add = function(name, ndef) + local _, _, mod, _ = string.find(name, "([%w_]+):([%w_]+)") + local recipe = get_special_recipe(name) or + techage.recipes.get_recipe(name) or + minetest.get_craft_recipe(name) + local items = get_item_list(recipe.items) + + if ModNames[mod] + and ndef.groups.not_in_creative_inventory ~= 1 + and not ndef.tool_capabilities + and recipe.output + and next(items) then + local s = table.concat(items, ", ") + print(string.format("%-36s {%s}", recipe.output, s)) + Recipes[name] = {output = recipe.output, items = items} + end + end + + for name, ndef in pairs(minetest.registered_nodes) do + add(name, ndef) + end + for name, ndef in pairs(minetest.registered_items) do + add(name, ndef) + end +end + +minetest.after(2, collect_recipes) diff --git a/basis/recipe_lib.lua b/basis/recipe_lib.lua index 2ad28b4..46f2dd0 100644 --- a/basis/recipe_lib.lua +++ b/basis/recipe_lib.lua @@ -15,7 +15,8 @@ local S = techage.S local M = minetest.get_meta -local Recipes = {} -- {rtype = {ouput = {....},...}} +local Recipes = {} -- {rtype = {ouput = {....},...}} +local NormalizedRecipes = {} -- {output = "", items = {...}} local range = techage.in_range @@ -63,12 +64,13 @@ function techage.recipes.add(rtype, recipe) Recipes[rtype] = {} end - local name, num + local name, num, output local item = {input = {}} for idx = 1,4 do local inp = recipe.input[idx] or "" name, num = unpack(string.split(inp, " ")) item.input[idx] = {name = name or "", num = tonumber(num) or 0} + name2 = name end if recipe.waste then name, num = unpack(string.split(recipe.waste, " ")) @@ -80,6 +82,7 @@ function techage.recipes.add(rtype, recipe) item.output = {name = name or "", num = tonumber(num) or 0} item.catalyst = recipe.catalyst Recipes[rtype][#Recipes[rtype]+1] = item + output = name if minetest.global_exists("unified_inventory") then unified_inventory.register_craft({ @@ -88,6 +91,10 @@ function techage.recipes.add(rtype, recipe) type = rtype, }) end + NormalizedRecipes[output] = { + output = recipe.output, + items = recipe.input, + } end function techage.recipes.formspec(x, y, rtype, nvm) @@ -126,3 +133,8 @@ function techage.recipes.on_receive_fields(pos, formname, fields, player) end end end + +function techage.recipes.get_recipe(name) + return NormalizedRecipes[name] +end + \ No newline at end of file diff --git a/doc/items.lua b/doc/items.lua index 0a3db3e..acf28f2 100644 --- a/doc/items.lua +++ b/doc/items.lua @@ -176,6 +176,8 @@ techage.Items = { ta4_electronicfab = "techage:ta4_electronic_fab_pas", ta4_injector = "techage:ta4_injector_pas", ta4_liquid_filter = "techage_ta4_filter.png", + ta4_recycler = "techage:ta4_recycler_pas", + --ta4_ "", } diff --git a/doc/manual_DE.lua b/doc/manual_DE.lua index 5f227e2..6d0e458 100644 --- a/doc/manual_DE.lua +++ b/doc/manual_DE.lua @@ -194,6 +194,7 @@ techage.manual_DE.aTitel = { "3,TA4 Steinbrecher / Quarry", "3,TA4 Elektronikfabrik / Electronic Fab", "3,TA4 Injektor / Injector", + "3,TA4 Recycler", } techage.manual_DE.aText = { @@ -1580,6 +1581,18 @@ techage.manual_DE.aText = { "\n".. "\n".. "\n", + "Der Recycler ist eine Maschine\\, die alle Techage Rezepte rückwärts abarbeitet\\, also Maschinen und Blöcke wieder in die Bestandteile zerlegen kann. Die Maschine kann so ziemlich alle Techage und Hyperloop Blöcke zerlegen.\n".. + "Aber nicht alle Materialen lassen sich recyclen:\n".. + "\n".. + " - Holz wird zu Sticks\n".. + " - Stein wird zu Sand oder Kies\n".. + " - Halbleiter/Chips können nicht recycelt werden\n".. + " - Werkzeuge können nicht recycelt werden\n".. + "\n".. + "Die Verarbeitungsleistung beträgt ein Item alle 8 s. Der Block benötigt hierfür 16 ku Strom.\n".. + "\n".. + "\n".. + "\n", } techage.manual_DE.aItemName = { @@ -1776,6 +1789,7 @@ techage.manual_DE.aItemName = { "ta4_quarry", "ta4_electronicfab", "ta4_injector", + "ta4_recycler", } techage.manual_DE.aPlanTable = { @@ -1972,5 +1986,6 @@ techage.manual_DE.aPlanTable = { "", "", "", + "", } diff --git a/doc/manual_EN.lua b/doc/manual_EN.lua index 24ebe63..d2a05ec 100644 --- a/doc/manual_EN.lua +++ b/doc/manual_EN.lua @@ -193,6 +193,7 @@ techage.manual_EN.aTitel = { "3,TA4 Quarry", "3,TA4 Electronic Fab", "3,TA4 Injector", + "3,TA4 recycler", } techage.manual_EN.aText = { @@ -1562,6 +1563,19 @@ techage.manual_EN.aText = { "\n".. "\n".. "\n", + "The recycler is a machine that processes all Techage recipes backwards\\, i.e. it can dismantle machines and blocks back into their components. \n".. + "\n".. + "The machine can disassemble pretty much any Techage and Hyperloop blocks. But not all materials can be recycled:\n".. + "\n".. + " - Wood turns into sticks\n".. + " - Stone turns into sand or gravel\n".. + " - Semiconductors / chips cannot be recycled\n".. + " - Tools cannot be recycled\n".. + "\n".. + "The processing power is one item every 8 s. The block requires 16 ku of electricity for this.\n".. + "\n".. + " \n".. + "\n", } techage.manual_EN.aItemName = { @@ -1757,6 +1771,7 @@ techage.manual_EN.aItemName = { "ta4_quarry", "ta4_electronicfab", "ta4_injector", + "ta4_recycler", } techage.manual_EN.aPlanTable = { @@ -1952,5 +1967,6 @@ techage.manual_EN.aPlanTable = { "", "", "", + "", } diff --git a/manuals/manual_ta4_DE.md b/manuals/manual_ta4_DE.md index 377bbd8..cbb9fb9 100644 --- a/manuals/manual_ta4_DE.md +++ b/manuals/manual_ta4_DE.md @@ -658,3 +658,17 @@ Beim Weitergeben wird in der Zielmaschine pro Item nur eine Position im Inventar Die Verarbeitungsleistung beträgt bis zu 8 Items alle 3 Sekunden. [ta4_injector|image] + +### TA4 Recycler + +Der Recycler ist eine Maschine, die alle Techage Rezepte rückwärts abarbeitet, also Maschinen und Blöcke wieder in die Bestandteile zerlegen kann. Die Maschine kann so ziemlich alle Techage und Hyperloop Blöcke zerlegen. +Aber nicht alle Materialen lassen sich recyclen: + +- Holz wird zu Sticks +- Stein wird zu Sand oder Kies +- Halbleiter/Chips können nicht recycelt werden +- Werkzeuge können nicht recycelt werden + +Die Verarbeitungsleistung beträgt ein Item alle 8 s. Der Block benötigt hierfür 16 ku Strom. + +[ta4_recycler|image] \ No newline at end of file diff --git a/manuals/manual_ta4_EN.md b/manuals/manual_ta4_EN.md index 6024efa..e58e030 100644 --- a/manuals/manual_ta4_EN.md +++ b/manuals/manual_ta4_EN.md @@ -659,3 +659,19 @@ When passing on, only one position in the inventory is used in the target machin The processing power is up to 8 items every 3 seconds. [ta4_injector|image] + +### TA4 recycler + +The recycler is a machine that processes all Techage recipes backwards, i.e. it can dismantle machines and blocks back into their components. + +The machine can disassemble pretty much any Techage and Hyperloop blocks. But not all materials can be recycled: + +- Wood turns into sticks +- Stone turns into sand or gravel +- Semiconductors / chips cannot be recycled +- Tools cannot be recycled + +The processing power is one item every 8 s. The block requires 16 ku of electricity for this. + +[ta4_recycler|image] + diff --git a/manuals/toc_DE.md b/manuals/toc_DE.md index 43ebff9..55e2323 100644 --- a/manuals/toc_DE.md +++ b/manuals/toc_DE.md @@ -192,4 +192,5 @@ - [TA4 Mühle / Grinder](./manual_ta4_DE.md#ta4-mühle--grinder) - [TA4 Steinbrecher / Quarry](./manual_ta4_DE.md#ta4-steinbrecher--quarry) - [TA4 Elektronikfabrik / Electronic Fab](./manual_ta4_DE.md#ta4-elektronikfabrik--electronic-fab) - - [TA4 Injektor / Injector](./manual_ta4_DE.md#ta4-injektor--injector) \ No newline at end of file + - [TA4 Injektor / Injector](./manual_ta4_DE.md#ta4-injektor--injector) + - [TA4 Recycler](./manual_ta4_DE.md#ta4-recycler) \ No newline at end of file diff --git a/manuals/toc_EN.md b/manuals/toc_EN.md index 645f2b1..655e62d 100644 --- a/manuals/toc_EN.md +++ b/manuals/toc_EN.md @@ -191,4 +191,5 @@ - [TA4 Grinder](./manual_ta4_EN.md#ta4-grinder) - [TA4 Quarry](./manual_ta4_EN.md#ta4-quarry) - [TA4 Electronic Fab](./manual_ta4_EN.md#ta4-electronic-fab) - - [TA4 Injector](./manual_ta4_EN.md#ta4-injector) \ No newline at end of file + - [TA4 Injector](./manual_ta4_EN.md#ta4-injector) + - [TA4 recycler](./manual_ta4_EN.md#ta4-recycler) \ No newline at end of file diff --git a/power/node_api.lua b/power/node_api.lua index 1c4cc39..9cd912a 100644 --- a/power/node_api.lua +++ b/power/node_api.lua @@ -248,7 +248,7 @@ function techage.power.needed_power(pos, Cable, outdir) local nvm = techage.get_nvm(pos) local def = nvm[Cable.tube_type] -- power related data - if def and def["cstate"] ~= STOPPED then + if def and def["cstate"] and def["cstate"] ~= STOPPED then if def["calive"] >= 0 then sum = sum + (net.nominal or def.curr_power or 0) end diff --git a/textures/techage_appl_recycler.png b/textures/techage_appl_recycler.png new file mode 100644 index 0000000000000000000000000000000000000000..9be40e7a795c5274d04e62a81903c1454777ae8f GIT binary patch literal 2013 zcmV<32O{{1P)EX>4Tx04R}tkv&MmKpe$i(@I4uB6bjQ$WUEuK~%(1t5Adrp;lsuRLwF{ ziMW`_u8P4|2ne7bV~EPk)aN8A3D5C$47y*L2K(lV!-^aGyJOTXAz?IhaR~x|0C+YRJ z7C8d?wtmpj1VlP(*wBl&3xg#z$?M&FbL25y0#HMh6cK29HiGeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00p&4L_t(|+U=WrY!pQt$3N2pg9yag?a-7P>g0SwWS~;R6(F2)<9wrVvJ%{O8>Al2870<^yWsZrb}A|=dM6+?HPtZ!ii(O-g2CW);8|dB6wx41 z2MC}YSRA?`rF4{lGiT03*8rzbT3RZC!Qckq1(RLw12zFy1N#9l(5RGp1*mbFh=dZL zlmb{{Veu!l{9@pSu=cxvJ^K6m%gG7e2E1-T{xx7hkHv?hTq$+sWkJBMUAq8QSm^Q< zkfBw+H;e`HwPsz^vheGqF@d_ey2pS=EOgleEHxqbCQzl6`VM#ym<8kkr;XP{1VHdNhwc+E(!|^JAv6|tPEJ@WK!g)6O>XSrQ9fl7^BUh zC4$&KU~SJvkH@nY_$|g1yMd1{X(p(Yx(ji$zCA$5X)8cr?OJ6ga0t(##lg`w9vQHkFi=%mv;Dmg)9yd&u1c+^s`m z2%~^&ddSrSHJY$Hfp>sRAh)`@x-2s@(-r}u=h2wo?~l0~)VsX7`XPG5Q6a?5e!u@h z=uHbD286DyqQ1VKojZ39Gz?><_7@&~>ugww2EoN>n)z;RI zw5bFKO_*8;w*d2+o0}7E0&{doGlL_*RlssPHky%<@w2WKm`+7DZ{F-lGy%7olxqVX z03Oz1E#2xwlP6C`2oV5|nd~yGv$OMwL=#YBQf?X0D5b2@@%o${8_3Jc>i}{rbQzoI zL}&|;A7i3}z?x8oroWrahCE=jl(GR}$dDlbp99;0Cru1-Jkc6(7N`IYM3I@Lx4Cu@ zs`hl-W0{gL};H5+yNX?O5Gme{ujVr;GPKg4gec` zJ|Btp0RVpiWx!nEUj4CxVL&$m0)fB)T_OW`T7M$d1C~Z0zyRjk*%jI{0XM0vc=??_eH>-B!B(^b0> zWv0b$>wu|#zyEwv5TFk@vgs;*8a9U54-}h}T>-3j>TJNVvq354iOR~#*$oX1%XO+e zCW`n^5wgn#db2Z1H<#z>EB vf12v&a0ze;a0ze;a0ze;a0ze;=(qR}bM~=Ix|d@200000NkvXXu0mjfdAOfA literal 0 HcmV?d00001