\=} :RtI*&ݒ5j[k E\{eN\uǸmƪUBNGlx; #@@_vCi5h͠>';gs/n=pyv`6n緎p͹>̺Uݶl,>+C:hT5I'Q@AaD"3۠U7@ d تiهj( QKLD mM;mӏ{w:{#]4ː  `}gC@uuP +=}hv=sz}^R"E@[ig|p@h&J̔'R9W@@ڽ@m!7۪n]:i( -T%n㪐;rUPIvջwp*F&+=t(VQX.H&ɟ2OvMW5I_4ND|Mp:M<->TU}>d4OVQ:'ʓ?/5'u\VVVVҾu} a/G_QKb #QMٖ2i2'ő<.eY>/'%&ZK'I~yOKOK{]ZO?nNe['ԓ뉵L&^tO' gb~ZSjl Bz9$OJ&y dxө7 cuڧBt1"cՉMO["z3`O^&!Oa5HOfNc]y?'+jv$OY$ꟿ' XL?&&WjOO'D}>}ɲx;?~\'W* /I.UŨWXy/ËlE^KQ=-U_˥/%_~)?K^KtKRΥ-?ۥK ^qO '©+cB}O͈O J /N~'zMZi*\VQșsђ"6!+b#mMu{~I]V +gY{ڼދޕ{ҴVU;uȒ?&C$'Ґ!`ω!~QvV+ez+xע q*YV; rGHh,&RL5ZChȟL,FBl?bHEMy"j,rF#[ax+u,`CXđF"kỈFk%{O!jW`^Wl_,גY;_W`1-׍v%~mn▧Wz-%SMx,`GkHH1 kDTcQd41&Z# ?l1qK,KηX/1x ^bk xUJE*|?.^"G~zV$/{5/|֯Oh},+n,UV᪸R8VʵPed.r+\NrpUW!Ĝ' \U\W!.prHN*Up.prBC\%pUȜIrVe]]Ir8N*\$9Uq'prJ$9Ur9WNU\*ՄNt:8SW!ʮ)rN*\9Uq*I\)ʫ8UȜ)W}Uڻv$䫈8NI\'%\G)ڝ:UrRrUrqW'"r'$ND'%\')®I\p%9'prpNRrUr*UȜ䫄=TWCUNJNSUtYdQu*ꎩœ99TrQutNWCĜp9G)tNWCȜp9G):]r*I\ʗr*U~u_[> t ~}zX61x]^;+KgVf4nMMѡ2MaK90 d-!M3hl4|&lG~̳%*rSWxQȮ$+qWȮCrpSpRW!99G'Ir+䜜''\$8q8\rNN#qW 䜛UXq8%8䜜qWU9)W$;)WdSUp\)\N9T\' 8*p\''rSrr'NU\'8W* hU9)ʫ7xμ*UO_ľWB9S =qLJ`G5 %{.ԓr|2(C/E%l1JH(h&'͚F73s33D&`N m(trȝ@tCԋ"II R "JYpTTnVi,r3C#pd`,֒[YԘ >GI.S_Uq%sUnSQ-dRdJLF`BsAɃmcv#X H#j"7&$,BTp"ŕ*)(6A8*I7ň L,H&Q)$"#:V*iCU4b0t݄{='ՔTyK>D^ÍDUsI7 $I{:mARJք$"Q 4F,lm "V:ګyV$B"'bdóvfCΌ,:?\>:d=lׄ:!K#;)'l;!2*`;O m۠hP:iGP}ɐ4I 1ˎ<ݍ$:rQnLd 2E hѐdGoeD;)&i۝Wî6FWB &L0$,IQUh)Ke-ZB rA$krNJDD)1A(P TTE0`3%*P (“ (R A&C#A upJ"D"*LFj͒V0PLD)L`)D$ADJ0S` AĤUVfl fVBC,$RЂSĢPS))0 a:$СQX2`¥)J0S J¥*QE&eL !A $*QUJi4Q&0jUJ `Fl,Ae f0UVHHв!\ ٱ"#z,AR$&bJ!SU*X5'U$p`21"xsoUз]X/Eв +Wj}(+]׀jw°],wՂ^֢/{ׅz5E/W]` 5#|xVExZKZKׂX_]IwKƲ/%/fRS*GHTk0zsY"Wd]񬋼]Q#QR=FyRE< e#QR;FvfyIRFļ/Zzk,X^5wKY^x%ՉwK±/4%WzXt*y1zcIb=,FwKY_y^ ewՉwXevK+kVb]DžtԮR^%ڼ5٩_h42^4^}ĻzMu+U޵Xy^5|40񬅓ٚHk&wXyׄ=Uڼ^5b>Z|cY 0Xq}ňi %т>`8vi5G cI>`,>0>`P5Pl` &#*]ƺ/Tj=HWz_L+#Q= s~ ]ExYvU̿]z^V+7K]Z\/4=&nzYti~`TVOj*]j9K/z !,ԓ>C@k؟RCRMi! f֟!!~Y][+]bEw+*UU^rS)CfdUx)WzUx~cW6ʮr?^/U9b8b<^wW+1jyһ+ԫٻUwUYqW*W]UVQ;بTJ*%#8o?@~}j>|O?@Gԟͥ'#>~߆<+ۺA=ʐ ra$ DП}hǾ=#֞yGTmORqyטddi“Gx$K)S HdCZuu6Jm4L1XY2ɓdbe '^:^0}1vfWՎڟ?@cb FvٔNK)f>A[ Ir3hs1=z^M[O,Y$伈Jo5[djD¾*n_>RD 3'5N;(WxGؽ7rWj<5wt#5L]SxڞN<,cGWC񻏣]+ԫU󡜍e<RA  0eAP}H2zR }H<:Pv}H6_7d|j1xQ¯qfߪS`Pʇ >Ӂa.?.rkX~`~gԃ* ~Ʒ@]~P2s }@@k}H>i5`1__]bnhex_Gt2 *6̌BTt9/[eM?I5}k$uLSl36۷dba0)F -1}W^ײ"%*#A5 |bf{e~pfk$#BYGR|u8莘d;4j:9%%UXr:c 0'^\[MŶmMi mvҦͲ4U !(d! KOZRih& UV2es%/dxh|;L;PA=Ccяq~c>9c=yQ};ux*r9} ?V;l멪cOܝ1<]z;z~wM؝Ix49G{)Nq;y=)'tdOR{'tyt'm;է g/7٧ym󖥎K/1wRR}~sy;y2pY;mKѓ}wrx$OR~;ɴNO&ԟN}6tӽ75L?Cý;ޝS:.<~ޗyo%Zr^Ϗt˩gR]2rrzKwlQ[/ w[/rX]˹:/-1y컖ܶ_/8CDd>4>>!'QWd{'Ww{ߗ;˽'/Lux{!zCGP?d?}ACPd?]UޭWzɪRU~z%_V//ޯɕL)V?,?)$0:);:Xc!gI}(ݏI?C Ds'阮P` ^R>'9=<NN9j3{݉-z=OmmUB?įHG`ltqq9%O? q%M'M&ock7g)^~e~&U;3$;ޮ]'H>C L>CPTPd8''oLN;Rtiꞙޝ{ޞss\Ӽ=3n~w雞|;51_77=ۊg;z]vX;ߵwyϪmwNbw~ϩm9ݷoeݷwmwwz]vnvާwOSo;]vr=-NL˼YݷoKOzo7wwwo7w;ߒ;m/Wٔ?%(FUC_$4]JUF45?=3b4ޘ#dy<1E(&0AJF5t!OT0"¤0a)_eAb_1nIb% ReqJXXT`E*Rqr ji/R^2S))p prކX&b'>E۰N(f?TBӦU^RVMRb "c5s)K-U2ňňҕ v 0%sr-aR"Pj[jQ-5 G26Y1@7 +?}D܏&Џl>G۟sI 4m042+~Y I2H$s A$ҦMh00IP#!$C@GG'G'H:nOm>''#??$q֏xO:Ie>9B4M'~*r^s8sB>,#}5tN+o%G}ʧJ ]&gsNfwC'f|&zm7䎤7%> ݈|A:?秒]t推uugTΌiyBhQt <{q8K!P S <1 2:s9 M#d01~?丂?(]r߬U+۵_H>emW+/DĻM5}X\XIPδ Qa,'*FjLHoO#o8Ku:dݩnun[neffk,<Rj9DŖ--X*,SSC,SMxY??|x#}d[yC2+jԥo4!1U/]1OT|DhMP96Nm#'`!7( h9tsyF7$tcɥ{gMнvUV]P  ` `VI 8-*?Wb^KN?PO2|5Zy窝Z~wI"uڍhX*,1e)맪,lH HN,X&["a2#G8w eL*agF/O(y0;=z"{ P*AE{?`nku}BJ_]Km],}TvM d5JJLm,>) ە*h9&IMHN9;%57|r͔lΉ|vBrG4XlKm˵a;LO5MONjk'G?3FI>e!Z if[_ /)B9$ɦj|[cMMɧڛcSli1ox- n6kk|L4Xh{$EwYR·]5J"4!  Pu*3n*c (ØrԲmC_yq"pߛfTY{̦iULRfSLTe3də d: Ue>l-}>?CLONuv_17%FG pNT3 ' 8iOL:i%ܜ$> =*_:V,@ n>?o>>(#ڵS)`d"C%~~@#(?lQ2x`%OvO͚&)Y1i=Tee4*I6flv;t${)ntwJPesǵ_}}RA[*y)LjyC)u" b9(2yC:"ud ݡa'HM2J,̘,ٴ];:Cw7;ߊ;uCW::kQ8<%Ĥpg*湝8̏ ~ܙ<]Ҳc&M<ɉX$c @  2C(`̩Zm L#1V1mb N+DCDyc*~QLǃtGxO`!O :aOz!qQ`;sCH4ab+u!uSrrid[z[h25Te9sދ!(E瘇̌ҪTUp2aS2T˜7jZDB,21e>I8TɦM2q1ma,L&? qM.DʳIL0O,VV1usZgW}o'_TmdxK8j#< 0>J|@s L+.S,rɡg%y LmќE>hVi5}0`4ꨘ6X114ON83~=A~qg8npȷnQ7LfTk}|Ҙ6<>_UL>%?Z0C| ,YOp4ٶ=%tmOvGp|I?l9:@›W&,F, Q?`"HwkFZk,~Rn킒ݬ|IWk1;d;ȩvj*"ʞ$$;ҁf0=w@y΍|KOrwd4'ꊟ^"`_[v~0aD PG^=i6>oī/>gX\T$yF=-*:f4ڮ6?8#5CIQ&FGȇOj|IQ";- HOO?'/?@ E;sC~ߜ`IZfP>$$H#aY x*HK$#!G*/VUe)IQK4Y#Š*D2{e`R `ʲ*Tt,b8T1,T*A,&# )dRJ C,Q^UI뚫Q*H,MuAG'LkSd'y_:3CAJ`;e;iMC”TJc&ڎLDȜu$wvtv3h m9G''J$ȱ7.˟hI3,-b6l,3(r/G(RaÆnYϐxLA49#)Jad'f9zFj(ғt&T˜K8P*s3LWCs&-MMe72%iX0j֕Ʀ敦LXe<rrjiL[[SM =21" ;M:nmLc.Vq:VcncEmѩbmdiɓ'('D(t%1,c11), 1KĚ2&bƘV6Lrtڱ&ڙ:X!)`1P2$%`i3@bFRSm̙1tLu1*b01`h!4ƘҲdNL+&LFLcLV+MŦ4le:cTL1DaxvpO,DDoV ?z:j9^IrG:׿mdO`=CUuJ?p #)f`߮z%zQs-_~計JQmʕ58FoطDmqx}YGB9i9C %-(_a U(iG`}~p _g35NRө0ۥ>3O~UW\<Jb|WٙH,'4?Mii4%kZ"-XI(%|0IM3W|c#|c⿅/^mhZJ&i+m֕fK3$L6RdڕfڍFij٬jfRmj+5UDiRH+"d2*JeK)VcZMc&1LCdBCvf g0nf#Y,I>_B"5޾A>5򭼞LX#ؘ5 H3bDX0bl#s431)bEe$-QdMX[dv2FdpϗwZ5mH%aj۲EZ`Ӂ0lb-ƘscHhYIeYT_~j仹 wwwmKk-(Z)mQw;twuw]J㺜]1nC w]t9Μn;ƔkXY iZXJ%coŶūھm;r$=x FXyFFSO)=4wBwYbhn6mxzQl??|J+;O _Why#e?4RL5rfY}!7 :Dڝx㉸5In`8&D2Q0DBAAA11UV_ g+T\[b)VX+*bWuΝQJ#MK/WҒ~vĞKDumvb$((* b Ep) aa™:2tc j#s3$:s#ss 3#ZkFѦfM?դZh>NrNQn\ K#!> ><:tGI6_,AGҞI<s'c9΄li_Pumſt4 f0Gk FP? 6BXCPc"R 0iAb[@npea'bNcIkk%Vbd<"|43#Xe,Ub֬E^^NHe eg4hҦ4K3cȲMӭoɷW'qޏ=H&?i?{)ǔGdf4ʲn`)&ކ6ɨכoH(頍oߞpd;R_'RڛfoO"!9}.M&L`?&G >s?(13Eafm-EL 0єJRX)e66IKNc3, 2-iKeUENS]eRIyYm)es)e(Zc Ln4p6˖4et9w󣤴JQ X-XŌK$3)BC@+GX0MT$$볤xFq"DB;[lB+eMK%ՈeiIZh2RC%QcbyHI$W]ő QhS-Ȕ*%DU lF9Z&ն֣Եj#,Ȗ #kls1@QZUʦ0+$D3k &P-Xۄ;][m- ŹjP4V$U_?thk{hw{&Kky<M9zׇZVpu9:ޥ1h^VpGFMoM11ħJ , Ɇqh@,q"|(ʷ2l_ުͽuČ9b9`q?a>vf-0SG᧗i0W0j}ˬ7 FvŬH3k}ȟ& 'bdR?PWd=Pi9rA4Mbxs&'F0X5 秼?pG20?Ye'ړI '''&dIJ Q\Ԫngrôqnj8CrSx5N+Nx r2& M549v~yl D ()tۇĶ;?utwI+S+L;RZB2$>`y>QD50J6u#{ȕ:Χ( >O:&?޳]+ͨhѵMQImVj6MՕXdڒ&e$kbuf˛T6ՈHT)6ŨHш5UDUh$Y6fHMljMb-6 EIjHAmbAY5Qm3i1 (ٌ̖a_+EdNeXxr#װH*?H)RőEBj ,)OsZ4lLOѱÅ/go&zdNI&D=6g!|,'䯘Y!@C9>D#4T+1%Sů w`|H|bPG4O2Nu>fq9&Il h۬ F5}p AJ%la7lE۾)ְõIQYv"3D;1LDBy6}"<6>QTL51;4,Q2Td>Bf%?a8|vչBlO:iTןO MRQ2Ș"0OXOd!pI #MIRJ*dM$D`lnC=>Dp[nFBƪ`>LCa7FsAk} KOqXͺ0nO022:$F8 L0(}xګi=R4ݜvx᧦B=R= DOyRedQHGGʎ@'~T{R*Y$g,Ke QHYbF>CqD}i#ךd")94LF ns%g<&S$Fbf`ȣNdvdp)NrÌdTi,Lo0mg8I޲eD$4Nzzfp;YS'YޅUe]DMngN4voT5ՠG$(~#xGU]a3LGCƴזY4\L 'NᢛI\= ݹ<## Tllll66o\nwጠ>9Zi fSӝ=lO= $}!ҽBl6ejm'Hsrl -*T4M2ʓHTR:Xmk;qU*#,OG{UUmUՏt(' DwHv·l?H?T>Hs1 4?$ti_O3jU%vWɺ_dNt&#  r' S" yFuE59]šY r?χ$w92hțO@;3?MIP :z~1d!JŊ&,԰). J^ hW͢5ό'|W{s|%ҽBJbi1~动3nUOE a<ړp?*ۜ9v3.$x.XUhCŭb/1 TRY:BU sdCB Ҙoz!A,LDL֖Ygw7:u NvŠ#4xo㮤\]} /P3^ R*(glcBm84FAw5Kf>4ڦQa7#Q>r"#S?%ވippȴHftKRDPX b^`-NSYZ>5<¼ȳ4UAڱbX/2L̓N^<NbX VsO@ lY^9@cIudS{@Vs{K5 kZMk"o9Ȃf8Vm}Pu~9y-v:%G"#]ӧIð,Gqd= Do..ﻻQ*; 9MTMrJjS;2zu;ǯ_T\#q~b;f%ƛlhvw*)Âoa׃Şlr\= F4S;Ó:rqjN$5qlŗ=`icRybOkT=~uyՏIkx[E F'+_S'o]?˖|m[)Ρ:Miњ26wq;NQ kT:!zм\2,jiE<$P-10ѿZxJZCoJgJu}6O>^4DG|#_r;IAV1ʙ`4YQEҾlN2L&!Auo=3zڸGpwqw7޸Zx^_wc 6c|vp|tM jyٝqV."|2%M [{ɋ6b\]{9 L*SҜAPOq}w9nR&ީ.4m-s_{nIӼ>Z'"lY%Orx1} H.ż9^ַh"ʼn2=LДo1ΩF8KtOR nwyAV>^qX"7COf=Wh<^|QUM;4Ibf8SUMr|?ܞ^9|͢-WΌ;mN!bK*5{ -_h"V}Kbh~㶨G V^u.ծa+wƸŅ ͬn*in3&,d5@{ocFZM.=x{]h|NU݂o5 kU޺ k_ \q?zғK/jAHy*Zݝ2Fjy[Ryf']dXo<;DG-uvq^͵喥jv~\>ǢӼ pǷ KCsݎٯ>ps>˾5q,gDqh]S݊Sgr".\-3g<ٮ[i=\|hɪ5Q4$n5JXU=aw=+4,9F68[ع)!})#?Qٹ.4G3FrҷAa1dY:0P.`<-%Nir^aܘGwdI(yyДUg4sK@'GMCڏ4G#ߛxiNlm o2W>RrHbPF 'klVj=hjl8ړlbŠo3)kW/{1na6i}Ѿy[v1TY__7lss—3{*ۈmHgW`ڗ&VW; }MN35N!m{44>W3?LMno~@O}Vs⁃`8D|aQk5fl~fk,׍y`Țrթl_UZUZOkc^$)QH%dR)))0O=PL`OB&F{'G #޴pߧ,Q\'^9s!]0CN*vn;H:םuŝmNvCR7v#wc&jg3~q]q`bamk\Pc1_'0uA903ՑQ #?,[ ,ߢַQLl4 بMX`(+{ hZݫE9ʕyp/[ɋ-n\al䛅L^/Z e)I|I(glio ׶pg8o0=/SY v#*kߋTu  z鸮M< Ĥ-ďlpS!wvً=f;c{1ٯ~v$y>g lcf4|xQăǘ!%̤gu7: }ĄaddGR(*eb+U+aIT"*0%R $ŠS"ăKG֛ߞ RxL Nhl#ACY4$&cpqG'O0wtQBՒhcFiVzLc*[Uun|dNk&bbWƞtQ0K7NnFo0thiAd!'+M5)q8ZV,RO~ Gl\1Dž0w:;q:yaeu~vY?T~nlB;#܉ug @#ʎAQ8#d8tC>}|)񏨎!V`20`$OߨAN^kG^c{Ŷ:|y2@&P/L]W_EN/Ȟx4XjTR%ejS2YkdƱ XVjd:1$e""ea0B&U~ )VIZl&Bfj2`FJ&`L(*#RTL)KPRK #>؏(g>QCʟ,V,d2 XԨg2}T%(tHrDd=V3$%HmbnNv࢔**`P34 )LA*U+!<`͢U:O!@Z)TlKVR"JT$JPJI$JDEYYJҕ!J%R$U )mEm,TJ--E--DΘti'>ts)G 9?O&FGx:֍#l铦06 !;rծGLLUVXe)Ŗմ##49Jdx"hŶ%:W}EMQ?y+O G4fpf\ Mѹ~\6LlMb;t'`pDt XaR[#G3[h=WbUZ[kԺap4ږۜ٭-S8J nKg*UVQ\x\V_y"=Ir`({pn$hM3 Qa^5F4<'HU*Nꬬi1^3͕eSysjl˳d,,LI--$;,|cl-}>)(E1g|e6ey3δo'li-_-`ՠrq[l.open_mod(minetest.get_current_modname()) -- Default tracks for advtrains -- (c) orwell96 and contributors --flat advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack", texture_prefix="advtrains_dtrack", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared.png", description=attrans("Track"), formats={}, }, advtrains.ap.t_30deg_flat) minetest.register_craft({ output = 'advtrains:dtrack_placer 50', recipe = { {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, }, }) -- y-turnout advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_sy", texture_prefix="advtrains_dtrack_sy", models_prefix="advtrains_dtrack_sy", models_suffix=".obj", shared_texture="advtrains_dtrack_shared.png", description=attrans("Y-turnout"), formats = {}, }, advtrains.ap.t_yturnout) minetest.register_craft({ output = 'advtrains:dtrack_sy_placer 2', recipe = { {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}, {'', 'advtrains:dtrack_placer', ''}, {'', 'advtrains:dtrack_placer', ''}, }, }) --3-way turnout advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_s3", texture_prefix="advtrains_dtrack_s3", models_prefix="advtrains_dtrack_s3", models_suffix=".obj", shared_texture="advtrains_dtrack_shared.png", description=attrans("3-way turnout"), formats = {}, }, advtrains.ap.t_s3way) minetest.register_craft({ output = 'advtrains:dtrack_s3_placer 1', recipe = { {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, {'', 'advtrains:dtrack_placer', ''}, {'', '', ''}, }, }) -- Diamond Crossings -- perpendicular advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_xing", texture_prefix="advtrains_dtrack_xing", models_prefix="advtrains_dtrack_xing", models_suffix=".obj", shared_texture="advtrains_dtrack_shared.png", description=attrans("Perpendicular Diamond Crossing Track"), formats = {} }, advtrains.ap.t_perpcrossing) minetest.register_craft({ output = 'advtrains:dtrack_xing_placer 3', recipe = { {'', 'advtrains:dtrack_placer', ''}, {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, {'', 'advtrains:dtrack_placer', ''} } }) -- 90plusx -- When you face east and param2=0, then this set of rails has a rail at 90 -- degrees to the viewer, plus another rail crossing at 30, 45 or 60 degrees. advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_xing90plusx", texture_prefix="advtrains_dtrack_xing4590", models_prefix="advtrains_dtrack_xing90plusx", models_suffix=".obj", shared_texture="advtrains_dtrack_shared.png", description=attrans("90+Angle Diamond Crossing Track"), formats = {} }, advtrains.ap.t_90plusx_crossing) minetest.register_craft({ output = 'advtrains:dtrack_xing90plusx_placer 2', recipe = { {'advtrains:dtrack_placer', '', ''}, {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, {'', '', 'advtrains:dtrack_placer'} } }) -- Deprecate any rails using the old name scheme minetest.register_lbm({ label = "Upgrade legacy 4590 rails", name = "advtrains_train_track:replace_legacy_4590", nodenames = {"advtrains:dtrack_xing4590_st"}, run_at_every_load = true, action = function(pos, node) minetest.log("actionPos!: " .. pos.x .. "," .. pos.y .. "," .. pos.z) minetest.log("node!: " .. node.name .. "," .. node.param1 .. "," .. node.param2) advtrains.ndb.swap_node(pos, { name="advtrains:dtrack_xing90plusx_45l", param1=node.param1, param2=node.param2, }) end }) -- This will replace any items left in the inventory minetest.register_alias("advtrains:dtrack_xing4590_placer", "advtrains:dtrack_xing90plusx_placer") -- Diagonal -- This set of rail crossings is named based on the angle of each intersecting -- direction when facing east and param2=0. Rails with l/r swapped are mirror -- images. For example, 30r45l is the mirror image of 30l45r. advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_xingdiag", texture_prefix="advtrains_dtrack_xingdiag", models_prefix="advtrains_dtrack_xingdiag", models_suffix=".obj", shared_texture="advtrains_dtrack_shared.png", description=attrans("Diagonal Diamond Crossing Track"), formats = {}, }, advtrains.ap.t_diagonalcrossing) minetest.register_craft({ output = 'advtrains:dtrack_xingdiag_placer 2', recipe = { {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}, {'', 'advtrains:dtrack_placer', ''}, {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'} } }) ---- Not included: very shallow crossings like (30/60)+45. ---- At an angle of only 18.4 degrees, the models would not ---- translate well to a block game. -- END crossings advtrains.default_slope_formats = {t_30deg_slope = { vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}, vst41={true}, vst42={true}, vst43={true}, vst44={true}, vst51={true}, vst52={true}, vst53={true}, vst54={true}, vst55={true}, vst61={true}, vst62={true}, vst63={true}, vst64={true}, vst65={true}, vst66={true}, vst71={true}, vst72={true}, vst73={true}, vst74={true}, vst75={true}, vst76={true}, vst77={true}, vst81={true}, vst82={true}, vst83={true}, vst84={true}, vst85={true}, vst86={true}, vst87={true}, vst88={true}, }} --slopes advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack", texture_prefix="advtrains_dtrack", models_prefix="advtrains_dtrack", models_suffix=".obj", shared_texture="advtrains_dtrack_shared.png", second_texture="default_gravel.png", description=attrans("Track"), formats=advtrains.default_slope_formats.t_30deg_slope, }, advtrains.ap.t_30deg_slope) minetest.register_craft({ type = "shapeless", output = 'advtrains:dtrack_slopeplacer 2', recipe = { "advtrains:dtrack_placer", "advtrains:dtrack_placer", "default:gravel", }, }) advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_rg", texture_prefix="advtrains_dtrack_rg", models_prefix="advtrains_dtrack", models_suffix=".obj", shared_texture="advtrains_dtrack_shared.png", second_texture="default_gravel.png^[multiply:#956338", description=attrans("Track with Railway Gravel"), formats=advtrains.default_slope_formats.t_30deg_slope, }, advtrains.ap.t_30deg_slope) minetest.register_craft({ type = "shapeless", output = 'advtrains:dtrack_rg_slopeplacer 2', recipe = { "advtrains:dtrack_placer", "advtrains:dtrack_placer", "ch_core:railway_gravel", }, }) --bumpers advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_bumper", texture_prefix="advtrains_dtrack_bumper", models_prefix="advtrains_dtrack_bumper", models_suffix=".b3d", shared_texture="advtrains_dtrack_rail.png", --bumpers still use the old texture until the models are redone. description=attrans("Bumper"), formats={}, }, advtrains.ap.t_30deg_straightonly) minetest.register_craft({ output = 'advtrains:dtrack_bumper_placer 2', recipe = { {'group:wood', 'dye:red'}, {'default:steel_ingot', 'default:steel_ingot'}, {'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, }, }) --legacy bumpers for _,rot in ipairs({"", "_30", "_45", "_60"}) do minetest.register_alias("advtrains:dtrack_bumper"..rot, "advtrains:dtrack_bumper_st"..rot) end -- atc track advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_atc", texture_prefix="advtrains_dtrack_atc", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_atc.png", description=attrans("ATC controller"), formats={}, get_additional_definiton = advtrains.atc_function }, advtrains.trackpresets.t_30deg_straightonly) minetest.register_craft({ output = "advtrains:dtrack_atc_placer", recipe = { {"mesecons_microcontroller:microcontroller0000", ""}, {"advtrains:dtrack_placer", ""}, }, }) -- Tracks for loading and unloading trains -- Copyright (C) 2017 Gabriel Pérez-Cerezo <gabriel@gpcf.eu> local function get_far_node(pos) local node = minetest.get_node(pos) if node.name == "ignore" then minetest.get_voxel_manip():read_from_map(pos, pos) node = minetest.get_node(pos) end return node end local function show_fc_formspec(pos,player) local pname = player:get_player_name() if minetest.is_protected(pos,pname) then minetest.chat_send_player(pname, "Position is protected!") return end local meta = minetest.get_meta(pos) local fc = meta:get_string("fc") or "" local form = 'formspec_version[4]'.. 'size[10,5]'.. 'label[0.5,0.4;Advtrains Loading/Unloading Track]'.. 'label[0.5,1.1;Set the code to match against the wagon\'s freight code]'.. 'label[0.5,1.6;A blank field matches all wagons (default)]'.. 'label[0.5,2.1;Use code # to disable the track section]'.. 'field[0.5,3;5.5,1;fc;FC;'..minetest.formspec_escape(fc)..']'.. 'button[6.5,3;3,1;save;Submit]' minetest.show_formspec(pname, "at_load_unload_"..advtrains.encode_pos(pos), form) end minetest.register_on_player_receive_fields(function(player, formname, fields) local pname = player:get_player_name() local pe = string.match(formname, "^at_load_unload_(............)$") local pos = advtrains.decode_pos(pe) if pos then if minetest.is_protected(pos, pname) then minetest.chat_send_player(pname, "Position is protected!") return end if fields.save then minetest.get_meta(pos):set_string("fc",tostring(fields.fc)) minetest.chat_send_player(pname,"Freight code set: "..tostring(fields.fc)) show_fc_formspec(pos,player) end end end) local function train_load(pos, train_id, unload) local train=advtrains.trains[train_id] local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z}) if not string.match(below.name, "chest") then atprint("this is not a chest! at "..minetest.pos_to_string(pos)) return end local node_fc = minetest.get_meta(pos):get_string("fc") or "" if node_fc == "#" then --track section is disabled return end local inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}}) if inv and train.velocity < 2 then for k, v in ipairs(train.trainparts) do local i=minetest.get_inventory({type="detached", name="advtrains_wgn_"..v}) if i and i:get_list("box") then local wagon_data = advtrains.wagons[v] local wagon_fc if wagon_data.fc then if not wagon_data.fcind then wagon_data.fcind = 1 end wagon_fc = tostring(wagon_data.fc[wagon_data.fcind]) or "" end if node_fc == "" or wagon_fc == node_fc then if not unload then for _, item in ipairs(inv:get_list("main")) do if i:get_list("box") and i:room_for_item("box", item) then i:add_item("box", item) inv:remove_item("main", item) end end else for _, item in ipairs(i:get_list("box")) do if inv:get_list("main") and inv:room_for_item("main", item) then i:remove_item("box", item) inv:add_item("main", item) end end end end end end end end advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_unload", texture_prefix="advtrains_dtrack_unload", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_unload.png", description=attrans("Unloading Track"), formats={}, get_additional_definiton = function(def, preset, suffix, rotation) return { after_dig_node=function(pos) advtrains.invalidate_all_paths() advtrains.ndb.clear(pos) end, on_rightclick = function(pos, node, player) show_fc_formspec(pos, player) end, advtrains = { on_train_enter = function(pos, train_id) train_load(pos, train_id, true) end, }, } end }, advtrains.trackpresets.t_30deg_straightonly) advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_load", texture_prefix="advtrains_dtrack_load", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_load.png", description=attrans("Loading Track"), formats={}, get_additional_definiton = function(def, preset, suffix, rotation) return { after_dig_node=function(pos) advtrains.invalidate_all_paths() advtrains.ndb.clear(pos) end, on_rightclick = function(pos, node, player) show_fc_formspec(pos, player) end, advtrains = { on_train_enter = function(pos, train_id) train_load(pos, train_id, false) end, }, } end }, advtrains.trackpresets.t_30deg_straightonly) -- mod-dependent crafts local loader_core = "default:mese_crystal" --fallback if minetest.get_modpath("basic_materials") then loader_core = "basic_materials:ic" elseif minetest.get_modpath("technic") then loader_core = "technic:control_logic_unit" end --print("Loader Core: "..loader_core) minetest.register_craft({ type="shapeless", output = 'advtrains:dtrack_load_placer', recipe = { "advtrains:dtrack_placer", loader_core, "default:chest" }, }) loader_core = nil --nil the crafting variable --craft between load/unload tracks minetest.register_craft({ type="shapeless", output = 'advtrains:dtrack_unload_placer', recipe = { "advtrains:dtrack_load_placer", }, }) minetest.register_craft({ type="shapeless", output = 'advtrains:dtrack_load_placer', recipe = { "advtrains:dtrack_unload_placer", }, }) if minetest.get_modpath("mesecons") then advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_detector_off", texture_prefix="advtrains_dtrack_detector", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_detector_off.png", description=attrans("Detector Rail"), formats={}, get_additional_definiton = function(def, preset, suffix, rotation) return { mesecons = { receptor = { state = mesecon.state.off, rules = advtrains.meseconrules } }, advtrains = { on_updated_from_nodedb = function(pos, node) mesecon.receptor_off(pos, advtrains.meseconrules) end, on_train_enter=function(pos, train_id) advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_on".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2}) if advtrains.is_node_loaded(pos) then mesecon.receptor_on(pos, advtrains.meseconrules) end end } } end }, advtrains.ap.t_30deg_straightonly) advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_detector_on", texture_prefix="advtrains_dtrack", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_detector_on.png", description="Detector(on)(you hacker you)", formats={}, get_additional_definiton = function(def, preset, suffix, rotation) return { mesecons = { receptor = { state = mesecon.state.on, rules = advtrains.meseconrules } }, advtrains = { on_updated_from_nodedb = function(pos, node) mesecon.receptor_on(pos, advtrains.meseconrules) end, on_train_leave=function(pos, train_id) advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_off".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2}) if advtrains.is_node_loaded(pos) then mesecon.receptor_off(pos, advtrains.meseconrules) end end } } end }, advtrains.ap.t_30deg_straightonly_noplacer) minetest.register_craft({ type="shapeless", output = 'advtrains:dtrack_detector_off_placer', recipe = { "advtrains:dtrack_placer", "mesecons:wire_00000000_off" }, }) local function swap_to_off(pos) local node = advtrains.ndb.get_node(pos) if node == nil then minetest.log("error", "Advtrains node at "..minetest.pos_to_string(pos).." expected, but not found!") else local old_node_name = node.name node.name = old_node_name:gsub("rdetector_on", "rdetector_off") assert(node.name) if node.name ~= old_node_name then advtrains.ndb.swap_node(pos, node) if advtrains.is_node_loaded(pos) then mesecon.receptor_off(pos, advtrains.meseconrules) end end end end local function swap_to_on(pos) local node = advtrains.ndb.get_node(pos) if node == nil then minetest.log("error", "Advtrains node at "..minetest.pos_to_string(pos).." expected, but not found!") else local old_node_name = node.name node.name = old_node_name:gsub("rdetector_off", "rdetector_on") assert(node.name) if node.name ~= old_node_name then advtrains.ndb.swap_node(pos, node) if advtrains.is_node_loaded(pos) then mesecon.receptor_on(pos, advtrains.meseconrules) end end end end local rdetector_data = { --[[ [pos_hash] = { pos = pos, created = ..., trains = { [train_id] = {expiration = timestamp}}} ]] } local function watch_trains(pos_hash, created) assert(pos_hash) assert(created) local data = rdetector_data[pos_hash] if data == nil then return elseif created ~= data.created then return -- not my data else minetest.after(1, watch_trains, pos_hash, created) end local kept = 0 local to_delete = {} local now = minetest.get_us_time() for train_id, traindata in pairs(data.trains) do local train = advtrains.trains[train_id] if train == nil or not train.last_pos then table.insert(to_delete, train_id) -- train does not exist elseif traindata.expiration ~= nil and traindata.expiration <= now then table.insert(to_delete, train_id) -- train expired else kept = kept + 1 end end if kept == 0 then -- no kept trains => disable the node swap_to_off(data.pos) rdetector_data[pos_hash] = nil -- no trains remain, delete data elseif #to_delete > 0 then for _, train_id in ipairs(to_delete) do data.trains[train_id] = nil end end end local function on_train_approach(pos, train_id) local pos_hash = advtrains.encode_pos(pos) local data = rdetector_data[pos_hash] local now = minetest.get_us_time() local expiration = now + 30000000 if data == nil then rdetector_data[pos_hash] = { pos = pos, created = now, trains = {[train_id] = {expiration = expiration}}, } minetest.after(0.1, swap_to_on, pos) minetest.after(1, watch_trains, pos_hash, now) else data.trains[train_id] = {expiration = expiration} end end local function on_train_enter(pos, train_id) local pos_hash = advtrains.encode_pos(pos) local data = rdetector_data[pos_hash] local now = minetest.get_us_time() if data == nil then rdetector_data[pos_hash] = { pos = pos, created = now, trains = {[train_id] = {}}, } minetest.after(0.1, swap_to_on, pos) minetest.after(1, watch_trains, pos_hash, now) else data.trains[train_id] = {} end end local function on_train_leave(pos, train_id) local pos_hash = advtrains.encode_pos(pos) local data = rdetector_data[pos_hash] if data ~= nil then data.trains[train_id] = {expiration = minetest.get_us_time() - 1000000} end end local function after_dig_node(pos) rdetector_data[advtrains.encode_pos(pos)] = nil end advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_rdetector_off", texture_prefix="advtrains_dtrack_detector", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_rdetector_off.png", description=attrans("Remote Detector Rail"), formats={}, get_additional_definiton = function(def, preset, suffix, rotation) return { mesecons = { receptor = { state = mesecon.state.off, rules = advtrains.meseconrules } }, after_dig_node = after_dig_node, drop = "advtrains:dtrack_rdetector_off_placer", advtrains = { on_updated_from_nodedb = function(pos, node) mesecon.receptor_off(pos, advtrains.meseconrules) end, on_train_approach = function(pos, train_id, train, index, has_entered) if has_entered then on_train_enter(pos, train_id) else on_train_approach(pos, train_id) end end, on_train_enter = on_train_enter, on_train_leave = on_train_leave, } } end }, advtrains.ap.t_30deg_straightonly) advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack_rdetector_on", texture_prefix="advtrains_dtrack", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_rdetector_on.png", description=attrans("Remote Detector Rail"), formats={}, get_additional_definiton = function(def, preset, suffix, rotation) return { after_dig_node = after_dig_node, drop = "advtrains:dtrack_rdetector_off_placer", mesecons = { receptor = { state = mesecon.state.on, rules = advtrains.meseconrules } }, advtrains = { on_updated_from_nodedb = function(pos, node) mesecon.receptor_on(pos, advtrains.meseconrules) end, on_train_approach = function(pos, train_id, train, index, has_entered) if has_entered then on_train_enter(pos, train_id) else on_train_approach(pos, train_id) end end, on_train_enter = on_train_enter, on_train_leave = on_train_leave, } } end }, advtrains.ap.t_30deg_straightonly_noplacer) minetest.register_craft({ type="shapeless", output = 'advtrains:dtrack_rdetector_off_placer', recipe = { "advtrains:dtrack_detector_off_placer", "default:mese_crystal", }, }) end --TODO legacy --I know lbms are better for this purpose for name,rep in pairs({swl_st="swlst", swr_st="swrst", swl_cr="swlcr", swr_cr="swrcr", }) do minetest.register_abm({ -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_"..name}, interval = 1.0, -- Operation interval in seconds chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep, param2=node.param2}) end, }) minetest.register_abm({ -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_"..name.."_45"}, interval = 1.0, -- Operation interval in seconds chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep.."_45", param2=node.param2}) end, }) end if advtrains.register_replacement_lbms then minetest.register_lbm({ name = "advtrains:ramp_replacement_1", -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_vert1"}, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst1", param2=(node.param2+2)%4}) end, }) minetest.register_lbm({ name = "advtrains:ramp_replacement_1", -- -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_vert2"}, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst2", param2=(node.param2+2)%4}) end, }) minetest.register_abm({ name = "advtrains:st_rep_1", -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_st"}, interval=1, chance=1, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st", param2=node.param2}) end, }) minetest.register_lbm({ name = "advtrains:st_rep_1", -- -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_st_45"}, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st_45", param2=node.param2}) end, }) end ch_base.close_mod(minetest.get_current_modname()) I;4jKr7Ə&s#8rB<a,TzbGz*ԟ1Z\[!N]{eS+_U/7)$Ο+~7OK}/* {GhUOë>6қǀ}ByQ?u34Zl0?S|YY9s.|sMsOnys?,Fy} ;y3tG.m{3T -4jrx՝Jvy>aݏb~O|zA;?xO?6{G}=^tO LʯuU=CTG6o~:{S>ۿ<=G+:CIGu 71jz_v I4dxW=}v=dqFɞ ]Fms'ؽ˟S;mӈm9Vw>su3vh?Wre1ʞ9 6D {e<.~'jfÂz3N$)7mfm\)bRlrĥ'5|<{0}7@0?~.%'XUG .0SviÆ8h q 8s3 ~GVv3 Voz$kJc$Mkd@Ka֣@_|i1,ےr,/w : ;jrlq1r$QO:z2 ԗYra/&q:K)9h_WU$iYu9_ u|>䣵JD>ݿ^N~4h.1 $>y!{ܯeѦr$#Of'R.Uʟ)>_wGΠY6$=pCH  '32R#"f0JRR7!?|]?T6&`lc3xRȩ>i?S$<|gf4?L[gBvJO2PlTf)G^8޴MCkRN]G\:8:}eNftC[|Ϡ{ a ߏEޏʍ^iG;O>hMۘ  ϛ璙 /^X [ ĩOP;ɧiJc-q2 ߳_>$w::Ga"3O'ٴYWSd֚.]!\InŦyMo(N1^MՓSYC={)ʟg+{fxx>S>ф倅&ҡA x.54Z7A@oW9z%W^x ]Wzޯd,`0Ci,27F*@`cIR9Gtr3I)tZG#s}ϔMܖe(\e|ĽcٜT:mT4jK髁BÔ?\/[5G 7E #8SJL C{mWsrXڞn(z! XxӃ:! x;dPvOxNdnNdk!&ݞC|38tsSܧ"}Ze,ř0K3GvImh9ͧ=N|8#Ϯ+?xՔj9k-zZAe+辋ȼj-@z.FD%?"feG:m;9%}pꓽ{99iJK9G9:9l ¢|wJGk@Nh%5 U.`:R:s ϜrvҎ)$x}!z§̍Ĕ3<݆GhMNH;#vd2dݻysxnN؞j$ls=a:bk#u W- ܟO09'67=x\ȪddsM˜^MWI04%It֔R8G h:93{YG62snIΏ5pG:1859'n);#h7dܛ&S&8Dۜjneљ6 $n 6GG?5oQM7xCڙ >; QsFҩ释)GFG#Yppsm'sf٨aCNSrLc s'66M\$oɾ7Fojv4xcMq4;==|zr8Iғrm M;3rGVLvo+>4{O7kj:uG<08~;G@< j4菄:!'LK6O5)JyM fn]3I̍;ۆc6)LXf5f`B2 [8A% byl4M"4hC\ gf 51I;>Ab8"N&4Hn[ʺb-+)[Vӳe60I!` yic1'ڻS=cתFI2M&be4nF ߎ\ 4hb'p.5ЭE)S|7Dl Jc݅YX1YLLCJ!R,F`!%5 DНxo u1ɼvrro}l`pil76AS qv5%3 fk]k*8˚R&eF>>` \h39 <4yS*y 0nNdl[/nf*hhadǃ)Ld):AgSCu8Ә8xwS[btg 9gws觛&>)5UU S9Цד'dsշǏRMt')'D9 Q ;)9q csV-O͖YYY=iJ#էNqN 6pZ~瓙/!:4#]UJ!=6 @h)Px6fȳ{`l6 1c ]M{:CϧzЮY%yLa`L\$$1։R?U" m^] ~ʷɌdy'bX+BiNp 3s cDFqtuzi=e sTH Sa8N:<18ê8g9 cr qN0)ڂ})KYSFFw#hy<[Ut.\7o}RrJ8[;tZǍ+Nl̝*w!j3 񣪦I7PD߃ Tdnu3t'8zՊ`9لjS?4:u~17?m1OsC#\ad nQfL #k=|s );hBBAAI ur%=sW|{wuF1ۮlG0yJkzEޭS /~vȧ2 CQ49?1)0bJ$P4CSߥ&l @|Ud$~/KCLܪw~ᅢZ;O‡aJ<7-;rO( I49a<7'\wQ>O8# %;Gvz` ǕDs>-<Ey{CNS9SDmA3[0^N\@:C:#9|yAՏvG-Xp!Jx> 6_S+q&.18#tۍppIBs;TzDbldo^*2?09 )9R xǔcbrJAd'L 0Ḉ:8]7| 4= (H$O⟪aD"jȓŷ>s=qQ)m6Joj܁9b:7ڸU{/exo0hԻ0Z?Lᦥn+ -=S!pl%T}\SS+X{WRmrqݕX=] ݆S9\WkCȘygN2Go'xnjUt^em{QrÌ:$ǯ~=9s|7g8 ɧNp@(N)!G(Ms\ NNol)uO&:A0i=7 JvzB= ;twA Ǘ( y19'wBQbf`CQ1 !wdĽ(|8f _3I:pcBՓ >?,>'񘼲 \Š86+x #K[-%O'237#>~Cy`Sy_ $ M'>U;,dxSO9U_2a@\ ȏ 8$C![1f.ᒲ+w#9ϝP|t3Ўu_&ʱF ݧ@0!$S7fd =5qOH8VVm_,]X;-1m|vPe<ZHޞ8fS:Xw ̣5(t: :)W"*:|8`Q62mK4v#d)'F4s>]|0Z̒*Y&t}qB}qalP;Jx8ء#bۋ&XEtIjZ.0Ū L7| uK"T`uomd[!G>¬JZ}xbQ3|8&?~7/1|6ED9nM]מz%DŽ^x=  2B<~}}y!0Zr]q~&lKVSo:Kz(du3e+Mqi GL` vڪ*TnǕ8^]׻|:hhVY Ζ3V0ɞPra;sxGLw %N:p f;jO9'aAaGs ^ /*^_3\:U8$roShZ͌udIp1n忨DMٿjIƿ$ۛMu.i2L\m)Zbڪs~z[cB햊*j)Ɵ "/VѴk6[ p8[6cI?$pq:W[i*οP$&#!dڒf F#f3)d3B-AQID@(RQA IQ$F)b"Sk|J<⃦Ob`~>ힸ)J ?tsNYgi;t Hh١ڦ_I֐Sn(V/"@>*+@WJ)[`ITkGx (:moy[olEC#StӲ 'ZO>44Y5$lS%_>JWOpߓ7q,aH7GJ20n ' vָTY8Sߙ4VUT܎uPA$xVws(} bdzu3Yg9}3{O-Z4 A (R߿b`yS"?WOSUK(t5F="'sLc(P՚B}Iw~zNk>yOПTO07s"T?P~ {<'*ه[r[SDLȋWYd:뤤dцiRĤFe)0%&UPu#k "2*uIgto22 kx6pR''#!*|!էN~q} pé~ 3*,ҔVWZn QDxt=qU8m:"~d>ȟ,MT?NS)ʛ)9&DdN~vdYq=U],tSZGJv|;ñ7ci̷%N슌:%Nv!4obp t^=AG,M2k9Pxe$HmOګJU,LcDȐES#2) HAfB$H2T*ߣғѡi7 bãY& Q֖vSdndRO*C ESJf%9Y7b=)O- 9#}-ǭ* n}݃~w]J-"$Lc īs#5+'HU4>y < t>O8}nj\WƳ!ÄaJ\Ѐ]fpGM35FВy冗ތN\ܩ[`xLG4F?d< ROԁ"$A=q >`A(S2RS#s)(F #)IELL``SASnbh)Ee3` `P2qD c$YJPJdSHRL`șL0R)L$i)eRQF Y"K(LE y`ќ, cJ~ddf+[Q ʵ+ 6%.̷?a?r)g9sI`' :OtONMD`1H#Zn1b Y<FD0Q+A%0E0Ił{'vo4$f0-̆3 M5Lҥ2ifd4$běR,%_̎HFGN'Oؿb}f##Y'p$ < '-/1LMhV)f UN+ʚ1& Nl w(758Ji= }]gVJ`gZ~Og&~HO( ;6c?~J{$Dv%yzwzEU[U}S({}9Nr,܇%e,c `6%y%b1/8I`c{|΍,y%=7 A$n d5x %K**YKiL18t7F9z~gpPdeȎDYgNz)~A$O BrJUO?҄I>l,S8K~n:ns7fy>uoϰdhdi5"Zi{WH5ܼfv Z"e䐇*4pasaw$Glm[UWŎzއ$&x&Gh;{g( E bxvxMe*pqS#8D Q ^D1jPz|-Zm`Ӕk(PU0 %m&&d0{w@2Dl((a#S$XT`b\u][hu5eeګ,RQgzwӌݣp0Tm%+{&& onZёMfyS;S4#dk\%:S\}C1FFIIf'0MYe28;e9c }>66`SnuL#Ewتk .Ѷҵ kalAԶ+߉RߟJtcpxm{1W=Rg35I~SOemTeQZƧ %)9!rz%)]uu범4kirԗ$5G% CCb&g3MmTt.iiǪ8ۊs2@ o߸&HؓF>áݍ8%Eda^xQټ?q͛k4d61 ##6*ٹN`䎘s朮`[,tr(sF͕˜ x(ɚsFJOPR2᢭{m&&1$~gawxcǸ>y(2Z B:d)Hr"+Wߓxqfk4xdGj4$/.rOTmn*c99Q5p.͙Yl2tW:w[l^KURLTpG'L60 ʫ@0 JJ)V28frb&CsrtV#Ǫ78UkŦv,LVԞ)ʒ$N:7R(ԝa|7^U2xVSclBF$a[Dd% @\h&<0%2A,1B$@Ie(DIHŀ%^dZdP(Dp  A'{YՒ +U$"FLS ;8`daT0hL& IBSIA)IFr DH1'l )nԲdMdX,EC d LړZV2a7X2M+A8LNƜdLhc敩YKtҵclj1.Sm cu H'K;0$A%&5cLVs nՌJ&R)!g,d"JaIHAKSɓϫ74CsuY4ZClV7< 1( aD< #&J&V2sjsN'N ɃCYeeBGt'#nsr<C#}233M|d z7Q|of_+Y/ry[wZi,i-r@V+e)V[6 SSjo8sL1M Lc58Jqmn1bӎNM4JLid'ƚmlcƦ16N4Sq1d&4mƚi&1)ƚc1M+ܟo1&1VLfYYݺ322̲2nv۳7YjYfm#NQˌI89$;2iNPcl[$Z[lENtJ:19H`Gぃ}9a!)zyrl1N8 ,gRJ><6f$*D_@pdJ.1}1z C Mdm lp$}U?rgO>&5)?0 QL2͝On{oɞ%ټ oli8J¿O H1HG,lTQsrA<>`OD#mU{kF4 r dw" rqV w14h[JRaTXܛ 5Q5s)fG;xCt5zc$Ԝ$_WAFJ-}Uŋ-}i&6Rx5TȒumI|`&7 ԥYx&d#+=1F"[*: a]g36H,ZѲ#-vLaOVM$2fLHISnG6m T]Y%]MD))"ZN qf$F0պ ̲A{:-VU<#߃Jv:1D9aۈuuwy#BH#CB*,LRs` ĘD9C"?&g@#"LI< QKdPJCd"ˆQ*R؆Jd9b7OD)Ij%=9JwCYX;pGyr<牾~|[L9rxÎsUcj\1jk99C &ٶs揜>8 c> 똛J~hwTbA&&wI͍:4qtfC()m\ JLEM0&6#&LIMRhLw/|xhG9)`=?WϠ@krX')(CA11XEL#S2UӶHGE))?tdL 4>p#FDf*a;4ѣH,!.r16lP$%tSfF"J_QӑI٠~)џW:%Cۖ2Lp689A✗ؘ?S%񭞦ˌb4hTM4Àgb0_A_/,{[O6mۨ19[rw0' ^$Nu3mr&kȜ(i\"-5'yX/"P`m)mQDDD9M8.7KNڊ" p^ҝ:;hZ㝩mT!8wsq 6ѻsDm֪mǁcPŖRPY'N̼PX iZ^ov9m[EٶWǽt9V1Un׽CbӑDxTg/::uECjXw^唥9"bZfbn Jsm-LpNYuy!+Z)J 9%mXvlȳsvE Da'9/؁Z-aNn F 9ɸ<( WڻHPl߉_#$xq@grcTR)"R tk;u3gw]uc 0N3F46X041  )JZԭԥ)MzRF"i"3%(S1LL+JRk  1PHEZJ L*4Z@cozGyN 's LOxo o)$GFC31mػˊR"ʖ*KUK ]I;!v ׽cR{׊u'PuG9>66)ma[oZsXךbYɊ;aGڟGZ;jw϶i)N J=apN~ dt& z"`7R |#Τe'?i{|#cPךCr7”Sr{ui!sC5ZGjfVu%Êl -}]I$dP K*%/O|2,)0|RpxQ.O?F6&#fŧ9؃u^I"}yG^]#WpAnfӱ::cȯoGE=mN3)wN˥8Rk0xJ3RYm :郷09'N70[mD;;;Ӆ;ӝiK:vʼS0HRTadDPTuH*mhQEdY)k4(jt{^7E7SOaQsFhZO(LkAGVfy}7i8#"R+e5:x_9kJ_.Q,"E`2@@@ŚW RDjD;kOvj~9dMI*DxQ>0mD-imRՔeJ[E+[FʶTKk+ib)ڶlV[kk-@QjBljZsp]qsqVlmUhmYkA qW'ۼq1!a\9J`xS'K;ߜII4s[}={ }\=^wFƤIY h`G)2LX֘4n {bDI'FLj|Ѧ"2J)c̥=ojlk) 0| n]yb3nr\Ur r ߒoɜtr42N03)xZ«䜮(%*}vSkMř 36C#hpGi:e!^vzOyw*)WǑЉN;ŭ7'UA5̐Gb~ٌs@KK9,a)Uy1'tgO$M|f ?6 .$9'(F1r`RP6ira(ȈAm1i8PxX*VLB8#)©b!$?IJ"G*#Ĉ"`b$$IɏvÑD= n'LL{Rq?;!3<)Os84c [7#)Q- knچ@jj7Ͷώzs2xssKj=!DD}T>fipj=`̑v-+(dև|_Bu’]w beTl94pщ7u1+xު90/P!1-$xD'%1-Y$Ey |4FwY'^N܇#fjMJCbl6-t&(swt뫝hԹ"nnTmֶQȄ+-JeZ e QұEE%q rJeUr7/ߏ8O$<5` tOR]LcfjK%dYJVf5}[kX[UTUl`XbNZxuIBYg%3)ԛ%j#QJwS3@漯If&PJ+%~U6lTS ܦ )aMcN48 pD 04`%Sr`Jr~ynjKVm^ھ1LԖK%do}d H 9 V繝ӻ^KxG򖗕T(IY:Q#g&r:W̡,k1UKWVb$ѭ#DIcTr S QΈ䙒:FZ?,0emnNRT鍃DG7c'@!>Sףd{iMpsÌwrV[$ߙFA2.F\IE,&C$:5dK%jdM3hkj%P'Mv+Xxځ8]CaԢȥzg {h²/ށ7Xt`XTg!Ss9<]1=ARGh;hl/Qgj=1m'NqҦS(󟨶=U d:l6tne,RەABw>4d{t獝Deo ƪn:8&9hBtϮzG OSRUD|6ƬD)HQEECZ5yI7 K(`ETE08seRcMf-f%&3k崴]y'Lh>bhR6~@X[l*{̦hp}zOƮ֟XwҞTN4ƱkƱlu*Qi!,!A @)> "%ԥ8pMAb -@LB67I5{9T%)=E7)3%@/ggDH $L3ўȻIt/7DR:9#]ޠVxzVPhk)bdD }{ і,r0sdO"CZMN0RR2ًfuʷO'K?IO= tC,۞:,&NIdQu9~ŢQ)j1,q,Ȟtq8)fZƎQ15\dq ' $ƅYCQ;x$b'? mi=rn e3e4#=j*zqco%;9 ٪>|Of>A[-D5?ׂ :gBɒwA)ԥ9"Fwc8Jw!LXŶ+h{~yCL#( 'mҟOђ(%K<;ӮOtfK =:2e%Ҧ[bXSe2Ď8r<A(՟@{iuL0B0]R'QJf)}1C(Jx;C3{jXn]AfgYEK;9 Eݗ1ׯE*T/kkBrɒ1)WulS)89ӗ1cM0Ye*,*5Ot $D"+prF JL%R(3@Ípr$$+K  TaR 0 IL3FAĄbĂ rd|v =ɸ9s 9ᆰk ?\qSQAdbdզ"{;.rw8D|0:3:ͥ:02&߶M?ML[ \{uj,~Zu7\j43n0ZRO>6=9JzڑxpAG coqIBRzBQ=ަO{@