From bd749ec4d41e90fc5b9d0217f09892082ab5e256 Mon Sep 17 00:00:00 2001 From: Jeija Date: Sun, 13 Jan 2013 00:18:25 +0100 Subject: [PATCH] Add luacontroller, a microcontroller that you can code in lua. It still misses some functionality such as a persistent memory and a timer, but that is subject to change. The code runs in a sandbox. Speaking long term this will hopefully replace the old controller. --- mesecons_luacontroller/depends.txt | 1 + mesecons_luacontroller/init.lua | 303 ++++++++++++++++++ .../textures/jeija_close_window.png | Bin 0 -> 7701 bytes .../textures/jeija_luacontroller_LED_A.png | Bin 0 -> 3541 bytes .../textures/jeija_luacontroller_LED_B.png | Bin 0 -> 3537 bytes .../textures/jeija_luacontroller_LED_C.png | Bin 0 -> 3537 bytes .../textures/jeija_luacontroller_LED_D.png | Bin 0 -> 3537 bytes .../textures/jeija_luacontroller_top.png | Bin 0 -> 11913 bytes 8 files changed, 304 insertions(+) create mode 100644 mesecons_luacontroller/depends.txt create mode 100644 mesecons_luacontroller/init.lua create mode 100644 mesecons_textures/textures/jeija_close_window.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_A.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_B.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_C.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_D.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_top.png diff --git a/mesecons_luacontroller/depends.txt b/mesecons_luacontroller/depends.txt new file mode 100644 index 0000000..acaa924 --- /dev/null +++ b/mesecons_luacontroller/depends.txt @@ -0,0 +1 @@ +mesecons diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua new file mode 100644 index 0000000..e3aa6fd --- /dev/null +++ b/mesecons_luacontroller/init.lua @@ -0,0 +1,303 @@ +-- Reference +-- ports = get_real_portstates(pos): gets if inputs are powered from outside +-- newport = merge_portstates(state1, state2): just does result = state1 or state2 for every port +-- action_setports(pos, ports, vports): activates/deactivates the mesecons according to the portstates (helper for action) +-- action(pos, ports): Applies new portstates to a luacontroller at pos +-- update(pos): updates the controller at pos by executing the code +-- reset_meta (pos, code, errmsg): performs a software-reset, installs new code and prints error messages +-- reset (pos): performs a hardware reset, turns off all ports +-- +-- The Sandbox +-- The whole code of the controller runs in a sandbox, +-- a very restricted environment. +-- However, as this does not prevent you from using e.g. loops, +-- we need to check for these prohibited commands first. +-- Actually the only way to damage the server is to +-- use too much memory from the sandbox. +-- You can add more functions to the environment +-- (see where local env is defined) +-- Something nice to play is is appending minetest.env to it. + +local BASENAME = "mesecons_luacontroller:luacontroller" + +local rules = {} +rules.a = {x = -1, y = 0, z = 0} +rules.b = {x = 0, y = 0, z = 1} +rules.c = {x = 1, y = 0, z = 0} +rules.d = {x = 0, y = 0, z = -1} + +local get_real_portstates = function(pos) -- determine if ports are powered (by itself or from outside) + ports = { + a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.a), pos), + b = mesecon:is_power_on(mesecon:addPosRule(pos, rules.b)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.b), pos), + c = mesecon:is_power_on(mesecon:addPosRule(pos, rules.c)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.c), pos), + d = mesecon:is_power_on(mesecon:addPosRule(pos, rules.d)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.d), pos), + } + return ports +end + +local merge_portstates = function (ports, vports) + local npo = {a=false, b=false, c=false, d=false} + npo.a = vports.a or ports.a + npo.b = vports.b or ports.b + npo.c = vports.c or ports.c + npo.d = vports.d or ports.d + return npo +end + +local action_setports = function (pos, ports, vports) + if vports.a ~= ports.a then + if ports.a then mesecon:receptor_on(pos, {rules.a}) + else mesecon:receptor_off(pos, {rules.a}) end + end + if vports.b ~= ports.b then + if ports.b then mesecon:receptor_on(pos, {rules.b}) + else mesecon:receptor_off(pos, {rules.b}) end + end + if vports.c ~= ports.c then + if ports.c then mesecon:receptor_on(pos, {rules.c}) + else mesecon:receptor_off(pos, {rules.c}) end + end + if vports.d ~= ports.d then + if ports.d then mesecon:receptor_on(pos, {rules.d}) + else mesecon:receptor_off(pos, {rules.d}) end + end +end + +local action = function (pos, ports) + local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates; + local name = BASENAME + ..tonumber(ports.d and 1 or 0) + ..tonumber(ports.c and 1 or 0) + ..tonumber(ports.b and 1 or 0) + ..tonumber(ports.a and 1 or 0) + mesecon:swap_node(pos, name) + + action_setports (pos, ports, vports) +end + +-- Overheat Stuff +local heat = function (meta) -- warm up + h = meta:get_int("heat") + if h ~= nil then + meta:set_int("heat", h + 1) + end +end + +local cool = function (meta) -- cool down after a while + h = meta:get_int("heat") + if h ~= nil then + meta:set_int("heat", h - 1) + end +end + +local overheat = function (meta) -- determine if too hot + h = meta:get_int("heat") + if h == nil then return true end -- if nil then overheat + if h > 30 then + return true + else + return false + end +end + +local overheat_off = function(pos) + rules = mesecon:get_rules("mesecons_microcontroller:microcontroller1111") + mesecon:receptor_off(pos, rules) +end + +local update = function (pos) + local meta = minetest.env:get_meta(pos) + code = meta:get_string("code") + + -- Clean code + local prohibited = {"while", "for", "repeat", "until"} + for _, p in ipairs(prohibited) do + if string.find(code, p) then + return "Prohibited command: "..p + end + end + + -- Gather variables for the environment + local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates + vports = {a = vports.a, b = vports.b, c = vports.c, d = vports.d} + local rports = get_real_portstates(pos) + + local env = { print = print, + selfpos = pos, + dump = dump, + pin = merge_portstates(vports, rports), + port = vports} + + -- Create Sandbox + if code:byte(1) == 27 then + return "You Hacker You! Don't use binary code!" + end + local f, msg = loadstring(code) + if not f then return msg end + setfenv(f, env) + success, msg = pcall(f) + + -- Overheat protection + heat(meta) + minetest.after(0.5, cool, meta) + if overheat(meta) then + minetest.env:remove_node(pos) + minetest.after(0.2, overheat_off, pos) -- wait for pending operations + minetest.env:add_item(pos, BASENAME.."0000") + return + end + + -- Actually set the ports + if not success then + return msg + else + action(pos, env.port) + end +end + +local reset_meta = function(pos, code, errmsg) + local meta = minetest.env:get_meta(pos) + code = code or ""; + errmsg = errmsg or ""; + errmsg = string.gsub(errmsg, "%[", "(") -- would otherwise + errmsg = string.gsub(errmsg, "%]", ")") -- corrupt formspec + meta:set_string("code", code) + meta:set_string("formspec", "size[10,8]".. + "textarea[0.2,0.4;10.2,5;code;Code:;"..code.."]".. + "button[3.5,7.5;2,0;program;Program]".. + "image_button_exit[9.62,-0.35;0.7,0.7;jeija_close_window.png;exit;]".. + "label[0.1,4.5;"..errmsg.."]") + meta:set_int("heat", 0) +end + +local reset = function (pos) + action(pos, {a=false, b=false, c=false, d=false}) +end + +-- ______ +-- | +-- | | | +-- |___| | __ ___ _ __ _ _ +-- | | | | |\ | | |_| | | | | |_ |_| +-- | |______ |__| | \| | | \ |__| |_ |_ |_ |\ +-- +-- Actually register all the stuff: + +for a = 0, 1 do +for b = 0, 1 do +for c = 0, 1 do +for d = 0, 1 do +local nodename = BASENAME..tostring(d)..tostring(c)..tostring(b)..tostring(a) +local top = "jeija_luacontroller_top.png" +if a == 1 then + top = top.."^jeija_luacontroller_LED_A.png" +end +if b == 1 then + top = top.."^jeija_luacontroller_LED_B.png" +end +if c == 1 then + top = top.."^jeija_luacontroller_LED_C.png" +end +if d == 1 then + top = top.."^jeija_luacontroller_LED_D.png" +end + +if a + b + c + d ~= 0 then + groups = {dig_immediate=2, not_in_creative_inventory=1} +else + groups = {dig_immediate=2} +end + +local output_rules={} +if (a == 1) then table.insert(output_rules, rules.a) end +if (b == 1) then table.insert(output_rules, rules.b) end +if (c == 1) then table.insert(output_rules, rules.c) end +if (d == 1) then table.insert(output_rules, rules.d) end + +local input_rules={} +if (a == 0) then table.insert(input_rules, rules.a) end +if (b == 0) then table.insert(input_rules, rules.b) end +if (c == 0) then table.insert(input_rules, rules.c) end +if (d == 0) then table.insert(input_rules, rules.d) end + +local mesecons = {effector = +{ + rules = input_rules, + action_change = function (pos) + update(pos) + end +}} +if nodename ~= BASENAME.."0000" then + mesecons.receptor = { + state = mesecon.state.on, + rules = output_rules + } +end + +local nodebox = { + type = "fixed", + fixed = { + { -8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }, -- bottom slab + { -5/16, -7/16, -5/16, 5/16, -6/16, 5/16 }, -- circuit board + { -3/16, -6/16, -3/16, 3/16, -5/16, 3/16 }, -- IC + } + } + +local selectionbox = { + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, + } + +minetest.register_node(nodename, { + description = "Luacontroller", + drawtype = "nodebox", + tiles = { + top, + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png" + }, + + paramtype = "light", + groups = groups, + drop = BASENAME.."0000", + sunlight_propagates = true, + selection_box = selectionbox, + node_box = nodebox, + on_construct = reset_meta, + on_receive_fields = function(pos, formname, fields) + reset(pos) + reset_meta(pos, fields.code) + local err = update(pos) + if err then print(err) end + reset_meta(pos, fields.code, err) + end, + mesecons = mesecons, + virtual_portstates = { a = a == 1, -- virtual portstates are + b = b == 1, -- the ports the the + c = c == 1, -- controller powers itself + d = d == 1},-- so those that light up + after_dig_node = function (pos, node) + mesecon:receptor_off(pos, output_rules) + end, +}) +end +end +end +end + +minetest.register_craft({ + output = BASENAME.."0000 2", + recipe = { + {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'group:mesecon_conductor_craftable'}, + {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'group:mesecon_conductor_craftable'}, + {'group:mesecon_conductor_craftable', 'group:mesecon_conductor_craftable', ''}, + } +}) diff --git a/mesecons_textures/textures/jeija_close_window.png b/mesecons_textures/textures/jeija_close_window.png new file mode 100644 index 0000000000000000000000000000000000000000..eb89179e3e7cbc634e55da707cd4f3e9b6a3618a GIT binary patch literal 7701 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

TU&}A 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 literal 0 HcmV?d00001 diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_A.png b/mesecons_textures/textures/jeija_luacontroller_LED_A.png new file mode 100644 index 0000000000000000000000000000000000000000..a187e8edec10ec5f49a52be3ba06d32c5e6dbe1a GIT binary patch literal 3541 zcmcgvYfuwe7H$W5s7TatQ3L@|!E%+j>VhH|MG^5qMif|iBx4wSj06zLfFLwVAtHt7 zxNKAm;A5~NLPQx5Ffmg z%!=N9_%r~_`Fi3z1Gsr>F|lYG>$Bg>v}1<3L*JfIab;0RU!z{#JDM9yTDC##jY| z@?ZHPl9~(*`cJ++E2(F~@4!W+hu}DNsA|fLT1^N3Nxk`3Z z_@M6X_kRh(d%E8_9k&faJGG?))S;m?achUW3OgYwZZiScI%>Xdv+C4Gi}pFi$qXkKG!<{&0bc_xmbw$i^za(8GwJrDL%6>` zzXr&xcVJ<$Zu>b91m(Md?zXZ{Alxblms7%&5R%oVQB$s`ixs!BUQx6!X~$9TIEL2F zoPpPsF>@2J#}qL0&TbAA;!GVw?O4&#U9+am$)x|u6h=SGah}l*krh1x>E>$oS>wLj zZ{Kh?%>0rR1&lOUN8O7oIB`>iNF)-jQizWwRvK^G7g_6Y=Im&b;(ZS_rDX3?IxmJ? z+kbn#T1iG!aZI@uZ?dbo=?1N7q6yUmlL@>3jKV%8OfRTE5TxGEFaFguwcVt@%9(}5 zR5q`DbmXcVRGce9>V92UhBYE5xms}K=gd;2v_XIi$syDvlugg#W8cR-mf}rNCLi0L zqeUbo5)txdU?U4-l)glDR18!79|NF)s7f@q`REf7QuKB;3!|2JNMNI<=*Z!?Wqg*p zIla=lze+ShN$hjwDvKWM;ZQif9@DGU5PO#^Ua#!0C=!NJIrwN3Iq~a$1*#tUS%k3Z zXF78~BRW0a3GLP5fdT^b+>QIMxj_#eh>%c;N&|G(ByC|~->n}|A$D22xXMq+T77Y;p*6#SJX8 z3Z}GQOiGrXC66N>H+~r>%6l7jth)^(7)Y^QFl_1Ur_+MgdOPZLucoV38R4-(mv?1JhmomINVdJ*C^I@~(5m6Qro z^Ba@U+&X?2{bCY0!L-K;0}W3vwn@gLd5yxY+32~0PuetSU7LnV$tnhQArVOuV`<9j zisyq_;?OJo!xd6r4t=4Q94Ufn5MIA7F1fmqkLNm;Czs}>i-iq|Tpq6UiopGQrzI*)HDKQ~$|n)87dCnaHN9bKAZesnxX+3F{wSH=E2bazy^6#OmM zxG;);Lu>qxYPjXbNps{qjUud9pH4rGs|DcAf z`jWAp%hJW>F}SJ6>Arn~I#t5()ExbOviLk6Lxd8iCRO!GaJM$rXIZ=YxjqUiCTiA; zZV|F5c?6}|)s_#$xVH2P><(4V?G!WRrr#V`fzSEp7ARCk!<`XK`!<`lpF>%am4Ko$ z0_@loLPUnDzaCSDkQrJt6yvmMGs*&meFth|GV`*|C{2} z8WTeFW!Sh=DU$7O6D(yCqhfYIDH8mK-=-qTA-JkVQ_nbcM@T<3K|p%l5jj|!+K!)l zBFrbW+p>dj^{06M6ruV-?5r+~8BnQYvm%lXdXu+BAe=3Nd0%pAgL@-f_I7L|ZmyCT z{}Yk`%S^99-H@^(sMr&xGJ9)4rgcbuqLvxKd?60>XWb!MlEx%2x_hKeH8H*EDReRm zhCvj@$%hS;`#0Q{{oH2 Bdn5n= literal 0 HcmV?d00001 diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_B.png b/mesecons_textures/textures/jeija_luacontroller_LED_B.png new file mode 100644 index 0000000000000000000000000000000000000000..738ba968b6d79a001f1b738847605a39cf565bae GIT binary patch literal 3537 zcmcgvdsGu=79T`G1QzQmbkz;0EpV(A&Z6MPNASTaBA{TXiVzlE#5Ee^Aygy-axC?M z9(6G)25PY&Vu%QWB*qCvi!GX<1QLXhSRO$F2^fZu*UWyle^>~{J^ryLCuio&H@V;a zJ?_08YrFf8h`B zOlL1Ql=+|Z+f>fOD?^S{aJk&`rR7SIu50+d zm<{uyO9Zrb-xQ4MYtMq;l*v>Jl^csBSV^-)UtcfLyQdv%xG2#hrk>D%y`~uNO{?KH zO{E&4wu$k+K2I%5gCLW=8v}x-LXaCkX9YpiA;=%x0fJ^iP$sxDThiW4wv%IDGAd97 zK^i2*lYOe`+l1?t=~&W;+|FX4$$}?5$Wx-k6zlp|cf>S)Z*N?`@#no4h;Z%hVgZE} zaUBg^Q;>1I_j-$(=bDc_5=6&mNS}qP3#$*NXJAT>3RQ%X$)%c&Mdv-MASL72gCp9x4Bvz$V7NNCJ{G=B8B+m1-LA4xqmAo~X?XHC>E-xZe zg~u*)v&w`1idXKVUnC;8Zi#fwuSJ&KIvIQNv@fEL)4BQ%RHXAljCcLAuufPQ9mIrn zc?zDLWz$Vs7Dl)SBrWxCURJ6pyS14qyBEcFk`K1mgeyYbFGd&Q&*T3?{H<|OmN-A0 zHtSz7K0Dw%5h*_a*tK8*f3Rw%a~Er@uS?>ZHWpNYrVJ^Xibx(vl5aH~_pZiXtLdND zKxG{^yN!D;6XCyIxgnrkbx*upup`q#?q)n;G(YtlprSlBWe$tXFdR%D^X~l zX=4jz7Xzudf{;51`<@+?0S5XO0MsAc`dztZrjyTlv_*bvBD}fMT+3zWOZ2gQGe_H6 zTO<074TSV1DHtoVX8!S~IOLav+djp{+B?s(WVd6LBpsEoi!}FZu-UjS;Re*V%>1gD zo<&akXbVQupX8KDMqc+u$D8&ZyX(ZaM>5tJrgQ9Hvl`jEw=gN6$>_leChz;$NNI-{ z`Fn>wc0!^p0Zcco2fLazQ46rOw~PZCiR+5xr&%)685TYQrf!4qacfP~kmF6DbZ5MD z+R0A3VNj$C*w$TufKg?jI3y`*$~p|l{#d1p5)1(91BPBtqC6Uhx>WI9sOWry*t3MX_>|Q*C}c6 ztbF`QeFZB0X;l>#KPMkqED|y24<5+tF5k z1_b$i4+|;1TS{PWWjv=wAQT&2h{If_99C;yvb z+n9M_QTOSaX>F<#C`9Xw4=OS9Wg?fH7YH((A53<%j!zAonYe*xLrm<<2` literal 0 HcmV?d00001 diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_C.png b/mesecons_textures/textures/jeija_luacontroller_LED_C.png new file mode 100644 index 0000000000000000000000000000000000000000..abe0fe6b12691b94e6cc59f15da2c86dbdf70928 GIT binary patch literal 3537 zcmcgvZB!Fy79K%CMPU7?NU4By)fN?8rJxZU6%`R7#m@>7x=B@3BnV_d5GIZAGpP`ZOW|qpSmxYU2vVWNb}#kad*P2w{2}{VTbKS z>itQAFAV(E-z~m#c@!UA{(12Hpz4P;!7i_rpV%Z}7Lid=1&!PtOL&@` zx`RC~4z^E=Fh&zI#tL1@id#BD&gI~q zJ;G`ry~c%w$58_FU>N37Aa6%yJ8;lGgy;hq8W_!J)$70?Q>Fd684aM}2`vKii>Di$ zX3>d9caC39#BYI6`n7F&@BugK5az^+j_#N-VNJ&TkCia`ezw~bIqcrw)u>oom2+y^ zo2xIHd8?;RrbK(yj~$pdqJBDZNrK8`GM+|E3?)@eTeBldUN44?C`wT>#Q}rbZyu6Mk){&V^-1grv?0vzEg8Cgo8a;k)nI%VVp{jIa z;V~8UD@y)+fdUs@mY|QCR^Gv%qQ`g!NL`j*s!=>{B*g9qsL5DPc!m%^8golQ)WPXO zd}Fo&l@-e*Xmhs*3#XSp!A7V!uKhm-K!Y%?#Jc{_Z3)VM;mX3P#Xd5`{2r#>AHPV* z($%L{IH)QmYB1@I7f-`4+@1&K1^GVfBpE z&|il-2M_D0!Si?;q;ioc*_sqnnea7)O>M;|-5?l1$vai=Xeqjp74vzT+Hi3)QB@F-M@XHRXFW@N z(i^~8)!3GS&R8NU5-S-R4{8HoT1dvYnjm_*>RoIv*Xf^9?yFZ;MT)f!!l{~PJ*xgc z*^#V7dK$ydt9UoBY#;6JT}s9Mlg*2s+$Usm16+7US)N(M&CtaN2wzPHhKz4|HtF3| zBF6GIz|OX`ECmPNRjB$uuT8N<8zDxsI5+bxd`!7i4;&Ci`>^o*fE@YRA!)XzWv3F3 z#y0hgG#!e>qCXu*lQqItrS6+KGNQtdVc=#k43p{F4qA4n|L}Y|oO z%D2gP%gVATL}{&KKpuohSEM>?Kv9F7m~tD$@0K$VFMg|@y8d#iG;6DoM2)3)EL3MQ z8DpHb{R(~Z=w;|R%yICwt7md$gT41mLqLcA{AyfmSBmY+UOHYI zKMcWqZ?&eyiv#_lD7F5cnNMRwLPN@cd#^xk_Eu!2&w-?lD9aH!qFAheV0{yxr}4WU zEPx4ed|^AznQ(CUO*xE8y@9OHcw{DX{!3b0Tbta>zRUB;(Xt*bGCGr{G<)zgH=B<{ zVC7fvpa?ASBOkC-ORAIhdhpOljg-LhynGSz?DB!qYaW(=dF|HnBn<7JTqlN^-Gi=o zEc9^G?bLw|wbFj4Mqh-=Tt_zgiwNgr*-I9m=EE)MK^@=M7-=FsdPG z@V`z!q>heGa1E~U_^r$$W{+yxxfO71t-aYKnwG)OZ8*duhX!&eYHA7=*ox?-+w!={ zI7zSwj8`Pr3667+SSFlN^tM%BSQs>fDYhy^bECW+tMJKm@&4{PqMyHLlc!^+8&o!L p9$-nf56C}K6Hv;Ow0E@XorHW@+G9>a8A(RKe@oEj;!R(l`8U`hj5GiM literal 0 HcmV?d00001 diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_D.png b/mesecons_textures/textures/jeija_luacontroller_LED_D.png new file mode 100644 index 0000000000000000000000000000000000000000..cc101706eeaed6435e8bdd8af62d040595029f7a GIT binary patch literal 3537 zcmcgvYfuwe7H(f4f-pJ`jG~~dg5@Z<;)q5d;{y>NWPAXNNTOjy9f2ScL6CGDN>M3{ zkHt7*hz^Pq8Hgx?kO>W?AO%PqCkEC4$rg_Q4dD?&>?Ga2jb#-j$>6L%wz^Wc>)yWS zp7WjWe&^)E_ksR1XUv-c0Km+Et($iPz+~ceGBDkO7={z2dSbAkZ};B}ydHgebE}lZ zj8*K`&=UY){pILy5^(d@*Tke{e85gW%a%zt_KPRa=0wdREK&nDZ`hmowy&k-V))^? z6@#J4!fy?Eo)?xB-95f-MbxY!r=(X?#5R zxCAYo{$o6S>E0v9UdtkLJq-~liPP+_rVZ3TWI>vQ>;xfNAjTgDo-7oJL{|g_uoP(< zeA*}k#nk%^4EY)+7PZDY9~{b4*ycND&<*^+2-wap0?twnE}+n1e1uCrE3>mmm1?*? zWCK=rJq6`lx)evlEr3@L5N8E^M+8P7@&y2}iMOc$u#gxg0l;*?bSajzjSHw1adX2! z_3vUSO7V(-9kkv>=D=4`1!W+uQ!_cEo8P+G;55ru6onl{L0_Yq6v9;zkuz08>G1Z%`%)Ts`j;aj-du z7ZRruv6ypfKI7hYK*yM6T&F$$&bHY)pG9|DgQnv3o8W7p?E-INn~A^X?2H}z&gD>0 zkhmO3uX15x@uZzR2!i+|(A!DX3LKid4_A{TG!T-}q}P#eq{;ekWxOOCYN$t0{{*_h z*@likD~ira!XA;q^q;r#p#AQYVbqx!8>_UMFehW@kEJm7w@mj*&5%cbdxK(~h3k|NK3Us;6JBF6*CF1b$5JHk%`zrNDe#fQQ=X!Op$Ut` zOkI6isbg1}bda3f=_SzQJ=n%0^8$S)W~({$E|t7q(p8ct38(Pzp*oM`FT46tUGEbq z!lj*R&H4oCOmHW-SAmB#5Khlrz4ICgdhkGsgv+&hptU?@Jrn!qs%|afoUuiqX@r?Q z#wz-M!WQlt(NT8I5oqAD5dz&Y@|xH-cMaFJUgY>*LeHc@bHZqrpskPo#L)V~5wMPs zK0c-niL-uK8(mRFJ}1z)T?^yE&zH5dY!^q1`Af3R&4@*uDAK75@4Jyk*?fv4Bjc`K47LQ8rB9cD2zG`7f zWm(w?hs8-fg8REw9^5)9;>Bo50prL1bnzn+zjKdyc6-H@q%W8iitbk z2RbS@^xAo|-1W(|g^Eq(8b#Bv=luvn|6AmOFAzeoodEFq4=11^)#d-@v8W2Q~x6VI-bZ-b|K&6 zob5q=baeE+2C%pA#cq|Nj9Is+#%LGosRJu|IZ$6;lm6whV(glv^Nu#>iraXVm{@ZO z6e^|!`wqp9*wdl3(@!t%{=x#}_Jw&-$enX$G?iueunHBN1`ONA-? z+7vYFnOI3Xp8}2|?X%cSu``Kn4DncDt;Cmup4s!bNsm5j(o@J8`Ji!sREm6>g1xMy zvL{0pez~i!L=niN&GAzsc`y~it5znkM73f(%e9zQn4Kn*R3{6BxW+FE59$~%@oeBz z)n|a6*>BXoRPx^?L`~@k6F4Yo{pHR^Yf+_Eatr_g|cptAUGy*Ji|Ud(;V#c8HXB~0>>jaT}Rb*2M?mI4m|jCPR`#P&a^H&SBg)G z1Tlp;*=w{X(R|LG-p0MHpz6`8_60U#t6>=jM5ELW6*VDj6IPfM2osT@-QMrc6*%5_ z87a;tFHI-ph?@-f(~fO~g}w{G2X9Nqyhx>>9A0$4wR(_!*-m zKy^oZzvR}UfzO~|acx-v(U9^2_oyhY*QAKSU?56G+i@X-oqKd6%m8O+;Wf_+wJp`& zMc9$AvY>BU(!+5jCMvMbr!BX4(;NMsL}!t}weveMOYa)gd9A@X+MNFH3iH0xj?7#S zhQ5$_F^4BVzpf~4vpF;IP58i}k1|zJ81%j_$A@!Ccvsgijg|)r|8ciL;tLY(MG+j1sAfjY93}g5?(zhu)3;RRaS20yh_IJn-Xx0i>aO>i_@% literal 0 HcmV?d00001 diff --git a/mesecons_textures/textures/jeija_luacontroller_top.png b/mesecons_textures/textures/jeija_luacontroller_top.png new file mode 100644 index 0000000000000000000000000000000000000000..3128230e60bad3c14655636958a53a152de69c6e GIT binary patch literal 11913 zcmch7c{r49`~O%%$<~7G@hBoxwz7<(6rrdn%aBLeN7-VSL4}gEkRm1uDGX)FHlv8b z*fla3S;jKPV3;xM{kwbL?{R#8&+)#;^ZS0^KYqs?bDeYF_uTh&o!5DO&g;C->vQj% zqpid?g>4WBMB>b88)pba5d0|!5fcH$`mG^0C`7K>+uA?|et(vVzfOW@wuYU)91ekq z@BIB0faJWC2TzJdoN+iQIxetXRz!bgD#``|QG=YZIey{RD0MvOy2FOG*F zpK{KmnhL86f7pKdnU#pf_buM;8AMje5Oe7#?p+An)GuMy=~j# z2DeD>5WCYda%uOhc#rt)ZTO9{ruhj3G>H1lYVpO-xlJxo??}#(>&)flg(DPPXzu|u zXKXI8Y<_LFD`>*f5pAj5!P}d75xc?p*ZD_(O9@8KaMAA zbqb3@fpT#ONg&;%UuQNT<&!T$Q9&dW6^*MY=kcM;v2Y5O4}m;{LDpm;383O)kpHP@ zI=#Pn%gTT!wu!Xigyi|-_|Z+_I7-mQ9zl)2e~22`4``XciZK7Yrig`scTSUS_jY!$ z^(X!G5kKECq2c82cT8N^uP`?JpvsmHMU*;?+Q( zBQyhYxXNW7DVEcZ1X{pp`s?uj2S+P{j`_zT7u|3IbFP+;xJy4jzMlY6pxj@emhtTM z1}J2|({dz_1dKPJNhUZy90kT(8X|HT7SQ z5_ow^$&p8_$|Hw4uuow=IjL01kW>WpKEvOH3A^ zPXk8YVE}6!jzob*lKlZ5Y92*nvQu0rd=4UP!F!m4wm?LIEfj?uM**&(sB{RV<QW!{1{CQVw~{`2E?aKQim+5hY?0lfS#V{Q2rHQ*lB6hC8P zS-Z$XF{4ogm|zEUjz)ksEb^f12;74H=l=*&T*rK~=+NQ)VY8iCAk6;(c9_&+6(52G zI3(Bx|9a2Mqd(AqV(2Fy(31ZMn&9Mn=~Nch5Yf(^ptr@bK7hcPJeC2uC7#ea|I9t~ z-iL+albNX>SmVWnOX|rXG-_!Hb`~!v05N4t0E$-!$FftM3o{jDT8)L<7(w(tY6ujd zpI4vCC2@;Qq=X@pZ(~{&Ck%`^hiVy`>UM$LAZ;Qh5~r^@!F^U|b1!v2I&L6$D^wr| zl3?ApN!sBz_{8?0-{3EOKLx((&Xz|Apma53Jp>+4ac?eAgFtKx=Wrp-T|*R-@!|r7 zxDUzU#8_BqPk;Js9umf()**b4Lm-mj)2c2hmPU*5V)6+7;47;a3V?hre+PZniF==> zAHr5dTE#0xAZ~cmZZw;b<^@#m^XA}Uws|)N4rT=i*&LjJ83;m@j$shvlpGa=wq|D~ zm6N?5^pmk{A4u;=I7be+y;t2~ccy${TVC|ULb`|sq~({QU~2VqeR4i;=&pXiB9yse zZ&MyF=Fd0BC>m~uoB|ab;-KP>aG}OCxmkRfqEKXd#UXSG@OqE(w_mUJ9MF=99^WvA zn}X3<@?;09>I-z^2c>uzQFN!YH;|C zBMra*^eYt-FoC0fccQa=5$HLlM)|sGuUKlTkJfogl&#fx9IYw&+_r=~fywW1ey5jI z7-I?PG&$*wqoCuXz`(rmj#ohfOjmPVc@Qo`HO_lBV{$9>uIuObu#H76YnyVv##pmBg|1y9T>laYX4cu`vvPe*mPa*ZUEgKfo=S8JZt8(JA6 zM5XdJQ2ZYor1_2~ zMD9XxO9N};v8~Fg516@xZH`AwJA`YGnRnoLv@2IfRq9?s^+TNMYprMK-&*zo8R;v# z42oqEYd0Oe!sPlHUtmmqFS+yT`7z`da!|oOjF3NhdGJpwCR-f?Pi>kg&?^>%fX{t9 zerwv{#-M`5yPps>+&`^z&*m-7T@0AyGjON6h?6iLY!C zgD5%b<5t^;AlYB<^9;X@D?iS~UV5f8SJIz!xVEzOS_Ze07m~B7&+BA`Zb6=L7bSAf z%Qnh{Vp-(W9jnl?2#<=e?0wbR^<_o^8^kJ-&L2qp*^9^o(azQ*kDD@now zq?=ue$R!HECZK}_PrJ0LITJ1OH;BrR3u{6Cm!u?DSFB?JH4w((uYC4>KXzyfDKqTtea&(8-aZ6FPoGc(f#z!0MNQ(6+5dul+`g!E~s8Fa~fWk^~ zblw3FMvREA9v@l=5GOxMy&*%LKc4O|GG8nDu+&Gl+BNsP_9jxKmuiy4&7OQy4USP?X!v$ z_lCVZ{`{D8!{D;>^ot)t4-jkYtxW3Xj(3diUSf51}E)W5kjCLW`pxD5hZCKeaAcQzoRv3TCLz9eC-#;PjzUnGZDe9C zb`Is!V0(Vxy*F-dxP(a{`1k@uOiTPoB-`_z-z?GG?$Ib~=y~WnQjs;XVGz)H3*tcW_)wQZu@ZfMwW>t%^r?*YJGJqM^a4^c~UTk*?;95noH)ARbq>j6+9F zwIK8_<7{dCNQ`!rC(6Me~gA#LUu$0@<={|Gy zz{Jj~5t(y^+A6y|srf$sUA$)>7QVtHoXq();h*4pt{zedBX~x$T3WUVLq6@Z0HQLu zWAF6?yv(UtXvS=B_?mU};fcO1UiuIWO=MPhq4YL)=EeX~;=evT@2Nxc85iTBSoWrC zuCgHhG1kw;e4YwNHU7h})in}hn>7VTi|e)*9sQ2kvqwua`EYkL+3+w_Rygp~PCNJg z-p_xCznMB7S#j7@|I|{Qq*rr3pe_t5URyZHHP7{wTx8q^Q=$eYYT08@2dxN<8Zz*4 zaoyp}=^M3F-#3pF3(oH5lCMIG%2QyYcklEoRVg}rALowDD%5=`(smpAp_i(4gE=0} zfq>w*tz3m7^fo%{Iu;$%fw7U{E98(Htrz~RTgc14kc*o+VOHZ=gq~xC$8!~mj^^$+ zVOWPtwlw*#ELh0#c&0G^nrmTRzQ2^k0qc9wP1DMjr^E8z3PD_}Qrrtq?XerW(zpX# zG!9b@XqT60b& zCCETboqL+O9!IjFjItChDwgZfpr4X3Fx;dc`SBQZ_q29z^iA*X^gxH*sNznfwaS#L zb;sCdcIqv*yAv#%xnK`t50LXURkg=d{MYSiaV1i_Kx7FkfaL;bOtWD)y%rSW`jT>M8%HFQp$FZ1{UzwyOwT#qvCTELg6E54S)VRRBLme3eiIjL}D z3j|@}A0Ul5bO|>4OyBu){t)-1hj@Ol}P_OJd*YGvr z5WK3ZV_UX)pfvtoJfVa~D><>YkV;2H^ja`C6B5A(Rr7#QRZi{P#KwyK<%hB}?Tte> z4tYl}$A9$HGg`6!`D`UU;$>JP(L3}4g=;=oFPNK{U~~%7zyioNZGItwV5n>*aOdtu z_N#m}!v_$!%~iTmO8sZ03?-0tPhSO$rTDx&np(V0`}7VM;6G?+Woh{KXzpgi$>Qaf z!ce>otPTXpS%DV&i0O2b+Pj;{PcE&Nl;5&8OoI%HY{s1TnxLRvc~T2RjhyxmL&q`{ z&Nk2Oz58I`!LgZu)F#g`tsq@Nt&q~G_1T;sf@9I7cuRk8VThzV4K>(ca&g@*XSm0L zK1R<_1}$NS$`{4-tK_@nS|gL6W1lDv>>XtTo(Gd^q9^9MoqZAJH;>$ZY^(S3(pE4} zl&)VWR`fk&Zz16;g+C6(ukeOiRgKfQ?O?b$ZI0h%2tZAy0wR2r)K9mP@y}X95BOLb z->Nz@*|4u<;YVvghy*y&7e}F?m`DOJ4PB1rq50pD z1R5frK5Dtf&nS-tq>wAOZ9g(qt;5IQUNeOCsxCS{hEV+0sWe2$jeaHRTD(<6iFi~a zIcj+o7AhBPD^me{JEKf$%{)$a5Ew^nI^8mA`N!)u4RBXQ01Xm-`M!N9{&ldJMd_tR z^GaPfo1L(}9Jmz=;b4*{uhBzqYJaX@uf<49Z&VcsQ;3yl?oZ58~B%l`W~E@ponu!VZc- zR@9rPc4OuxM+4^Oa~~&M*a&6grSX>B>NwoxmnOi^%A>kk<8Xflx3~07=HWawgHY&m zh5ip39_yOP80*l^k{#sNPdVrBYrAEoGP#|Y%}Frg=tT4B0a5+sUsUZHUxm02n5aMF z5M2`Uiv_)_Gu)H?>$W>)yy#U)B|{2We|)K`FULQ;Ykv3;a`mCv@~2`Nv6(qR%v9HN zP}4rNoqF2NvhwZdE-}|UPsoZhyQ94L@k@g^+V z*b16{PJL>*ktr@v|A6LJ6ZXw#U-OTs5UT^hLvoga6$)TlaxxwAK>Jm#1#4bzF>*FB zs5)(RP5V~S!9?N@E_!*F!*O(K>8(EVWZ3IAgM;sM`sFk`IaGUuG&~^rU@?^QwUPEv zOH(C&eLu$SCaIa}U@hl&zQ!O&1P4no$U5}!begJ$l7z4zq|8#d4?~8dsN&r08#=&; zs&wRe57)Iisonh-m2`Q1o8(l!`2bg$7S~Z6v054Md`{@W z)$=X;3(ZEf$Q`f?c1oDiA_O&Z)IuiBQ#Jtt2}*~or(b&!Jf3)TL>#dDRry5`R zOz>R?=D*e2`LylwX}{mqBPt>QxnvydiYXDf)p5GzX5cF-^BK~FOQ&|h?=!d4znwst zo(l|{j!_`9_SIbWf#Ux#q%T*QI+`{hYFbvJxeLuw=uWKyGU__zQ#cW9rJ{`$$=flMWOxN^hc zrpE~O`DZCok+)Z;V}$84IARB;e|?kKk^U`6ZeTUR42|*!j)SX;j9{m!T4foWq`brM zfyLw#MD=(jD%7xXN2|l@%j(Z=GkDr4>aSxp?H4}z?=fs>$Eo&YM9mb^zSNzJ?Tp&? zM}t*$j3;qcXfXT*L0OVY(d{2Y#Gy;91i*EirwDxDq>{)HEpFR8>NWuT15!Ldyl4vjBw zFD?j;5?S|Am#WHk>&e!y?G3>eM9r}d2144D43kT1kpVx3Ys6&+n*${cyQqlAw{0&c zztQrOxxzkWS+_>z3{W4W?r41#@qO5^DR`VopXv1M8!Q21dRsn#q`Aj%M4@0kim(dn z-W&a}m}%VC?Q6C^5g@^P=mG$vFDsq zx+~GYF5S0{zCFk!lG9->>>gzoS&GgBC zk1n2V%#*ANzlCZHQhz2c7xeSS6`uf#mLWy8OaQEg{IG|#M!mm61STT8Lk#H)MVI^Y z74cCi?s>7l=v7~;@=#6^j6#A66~mK8Ri8{=yVUHEh^{yQ3y|YyoqT=<7;dWY@3r(l zu=|@#n_Dl=2TF|LtLj#(?T;aIlaOuXvg`Wp?8 zAW_UodzTI@@tNFsJ)}Q5q4twE8(WbABjQQg$GTB9wt>g)#sA^OO$140odNYHaRfpQ^xt(1UvkA^>Q{JH1cS{To~+H%HoizYsqnKoM}v7>Q0%lf2)yJShSiBYZ5BHg^5uDVyr zkMOX$NvO~;oY!?XnR-+dA9YFqQgPs-(d5a^2_{yqXgl%ZCbf?tP5sf77rs_RBIY;r z8PSyFW%rAQszm!cPIrkeW`4Mghg#HByZ9W#)&)Dt28(E~z2oijAZwuPcj}Q3rdj6< z!f~(TRiD|aZzn!-an8W4Q}*4w{3~^{70P`er3O}LvTOy|$yE`})7RQw>0bI|i~2Lv zbql;xv?#Rjq;j-s_jQ1=UqUZhIYMW(W6m^7Gnlbx6wdC7l;qX6S4^N(j{6JtE^k1> zcNcsZJNCR5+S8~L@jIl|2w7$NDSS(hCAcw+=p7cknxW-S6GQSPkMAB+`6E+dfy=9J zM}=dks+m49m#h}jwtf{?+8~DZ!KDloh-(G9f*m&ly%8A-^vAd&l9{w8WC1M%uG+C% zCp*?R!{H6a&8wrk7WRzhqpHP)O0t;sH(|Q8@t(&eg%*+g`~vaqW<81?4^-AQWbrz9 z_gyLLO@X75FI-m%%3zfw^#ES$M1Yj;0iHlx%docur0F#H>VDRy?mjYKN|o$&OAl_w zXzw_8Zea3rwLC^=pP}3oTH*76EQj`E&-THl*vyb#T)l0hh<9k5z1haO_9Bt`{NrX+ zu!g1e0KqL0icg7;OaG(fOLo!Z#3K+8Mb?=RXSkWkT&uK$*=6!EX5+(#bkFqQ zL4;!l^lqY0aA65;*=an8uv1s{J+xH~KnAu11-#oFu5Lgn6!zN6nO#J$?Co%j*{b_P8 zJXB$wZ}qYXihHx=M!j2KpV5!O$5@`^Z6$@;*Afo!CVlQx#<0mOvP33nH1lv-)qC!; z+lW82s;OwJah02mJTK?Yjq|=kN8N&T#2N0I^m<__%v6+7WcBwjHul}CH17q`-vb$bvqLj)MzDg?n(m| z1x4LR_0yho9u#aHOVdxA>)SPd&rNqe$X1Ts_axdj_>29$QTU0MDi|B!c}tDAj9QZo ziMJe`8?zEn;8h(yUc}I$Q9fi(n6w3WdX@GocRrOJPXC%@=XJ}3IZ9V=#XjmyJf$W9 zZnbRt%>}robG0EfFw)+|)E}wNf~F|9a*1DWdrH5!w6!=-3V-0+6Wc?hTco8dH(yC9 zcxar0c$3a2jAeM1_4Fcu*9S`#10H+3Zo!n#sXFw(e3JBaYQ2dn*k(S1)jgc)$m_yU zB`Gf)CA)oPeU;J9b!GzU=^mMk$~Q_{S3CAv_wT+K*dut3qbdwBUDsBV!brKC&o901 z9v)<3G7>rJD3^8xOi6`K4W`iEQ5{ak1TM1RbxI5~q0xg6{Gt!#kK~)3>x_~@5&Sc3 z6{6kch=owIYo`KHj>mCgH!Pz@R{rpCN49%Qkyt&^&)%=*CYLK0!x^Nx%oQ9@~rGGDtmn*;hf!27;E4;X&*)XxmOFl~ zTc@4`39R3ZTdQrpP_BP9nikK$z0O^{mVH9E&XD~0e(~bu$ZJ}$eqq~(vn%UE4|uo1 znt)(FlD$Cw6X&xuynN*-`qE0BxIo7scObK+*0yOOF8iqAoBlhc??@4`Fhs03hf^(9 zSu47=M&d?*ta^{e4(pF!Z{&Z_>X+5;78f5pb59d}*3?i#P%}MsXvgY3r?@Yo;^4G% zvEUv}jrC%Tj)!Xj#?bG!##MRpscJoOdSKnLl(E#WtPuh{Jog$y+D`*hV_I*uu(tOPZtVlI==;xa`A z8}-3f(Q95y`Ms(odls+i{9>TfOM_t96v>;?3PSebojy5Vw5SN*`QJ|W1j|Z?cUv!M zK9e97uBKhP;JtjhS9~-1u-XmKew>&8z)BAMe&H+oF$F~yCNfW~i zle12Kr+3S^z_HuYgc9vc8XonEX=zR+iW>66EM5pEygz7^9H|S*Oqq**Ib)(<=`NYl zt21BM${gGqv(T4cA&F8neby*bNUrBsyQrCTKE7>*dfRuCVCD6|G`?dh;dRqy6?9Sz z^e)?xr!drEiC){f6S(ncsAv*Z;HZNPdO-4LbP8=oJGoZv+=A@-!Dx-lRWFBtiCVT* z=+f(mbky=jcGHmpIJc|mn$P(sxA?dW6nEOv6kMwMnKc+xxlZ+<+}wBfc{}%8`v-n} zs``@_6^wl&+Y~|EEM8dOOPF2=?!-5We2XGZ!k^oRV_t2YKF8HBwJD#&A` zS2K2ZWK>a;0;=+0Aszj2KbFxp^oWr2tVgO;W+{a{SXf^#;3+H8xnH`+nij4xenFwT znc<`0=pW0%yWAUh-`+KKq18VYpvH(SFs%(;cExzM2`Ql5@SvNxGq=8k;z%1%c7H=J z?uP{+=vbcnS+64zofI^`+M$|ZhWgcWEth1d3TvcBj;9{y8`Y+90(D(EbGTQs&ax1WRe8-)vh06Z+}X zaxd^XzYfQd1GD&FDL>)?W;{PzPXSyQsqZsTM&+qaL~3#q3TJro=IDW>-1d6o{S1jx z=EO5mJ>p=B9V`PnEcaZcK4Q1{pzlniIKDKQcT_~v=}@=8>ldS10m{cSH}B*_%N)Us za z)nVm%lb%aUZexVJ>qCAoMJ)?fMZx{b$C$WToyT1iW8zdY)+E1c;UURW?)_Q{c0J6? zZiIK)rSiIYr^&`t3fZe_x_%~Hup#NBwc$lU`T}zBV$BFe3fwh!0t>;}xyRTJRg)J? z_e;HSk_bC6@l=x;Z{c`uQa?vjYqXyalr#DN+1V}px!CADlvcNa4_TV_)(FQ zwdb6|mzFyJqp`FsiJc0hR8vb06%dsM; zg53O-ntF?%-y9U$*!AJcWW?F9?^I6TL-L$gjMs(dQkx5b(rdON zoF|{DvA2il8RlE6SZJTdN3Y%#+*bO-lJ(t*Z7(DM`E-T9?!^B?T^-5d!zOCKT7OKy z91S&Lc19~nm|qlAQl$GRS;~(ZJPzDBgltnAEftV}g2V!&^$r+!8q}NFNXm;{igCuh z*K?~i0$j2ZuN1oolXn9Fb_L}uv`R^R2N|atw{je%4Kh3kU2@o!y9+oHJ)fy7x$r%b zKSxDs2EKWMt$*Sj9LTD%W{-ciAcn1$It8pBhd?edS-mJMiw7oVm>#n&?V}K0AJ6pg zxtm2e|A)I(aO(?BsL|Z*f{?J0c*aL`{27ALZo$Oq-H_1u={aU>f;;Kc+)mT_P?7rS z^6X1|oz0qyH2yDUe8eyZwQ^f^-Q`Ng`S77&-y16%t!%;v6&`TDth`o6H>teq5w0D;d0M4_9X zK~h}w^2`62()O^9#Dc22vG%-N$!@9IP~~@EFht1MtF7Ro01`kTV7cmlA(|4N%ISHy zZESsM7QO67LYZE^)Ql>pAR+Ki)J`t~3M4i)EYblgbhG6h4X{Oqj1vGefJs_rvZWXZ zAxkb+gU>{PQ4-*nAvp5Mk(^hU7<>@Os4BA0e(?7b`M(?KUsd}jC+q(*Mc7cLK5{iJ z62Cueb?WOyQo>+~6DAg50t8ez$N&>{U2JfARe=D04K?iHPOg1!03cZ(Zp!(Ob5uR9 zFnJgqfXic|fZwdVWW`Xo4SrA^>i;t_FRM3xIXrS$_;6Y7aXqgld5{eIPa5n$9qZ%u zUXVl?jpZy`z<_*c3rM5X_ZXqEpYCTiVwYK%-jF&Z66DF|9jjTKqj6dED+Rmr#+X8J zZ2->%oUi}Luh(T;RG?M}zOcpGN{&Ygn tv_U2Q&v6b3LCUv~_LTn5bRYntbsa*_Ux@G320MeCIq7Iqal$+4{{T4;nUMeh literal 0 HcmV?d00001