4u=-i{I킟 ޾^Ph[%l;Jnvp¨:;5wXCO(P hvw,Pb;yPjdCZ(Ph4-h@ f$1PHR@t(tQ @JfѠPt(h*(@ Eg6C t(ގ{WUovw:7g` dvq5t b}Q{F t*NKtwFg-gƢ)-e0:Jvw o5U{ԕ@ IJg|gc\{5l:RB)2;nЖ|N=sѮi]ҥdE:|LIk턾=m﹵ԍ6N2=3l(po]W}/Koh|wmx7h}wmt ׅaG޻wnUڝSlִ5_n5Fj)[US3]:R^on^㾗־;d=}u|3dE}_GîuxAv5˲j{o/tlm}ٻ>^Ce\xp sهݗw5S\x;0=[o\拭oNJ<5OYOpbo{0uׄ].z }z{G:7'zu][U;B=w a@`a g>ė|ۏ_[].=tvmթo[([7f[ZMbM I|0|۽ bNa\{0]4%+PQ!uSjX3ɾ"]3fln&}(RH qCmuwՀB  *qKSl}[ymH&+F aҀP@(ؠQ@Κ>ÁJ5[m ke[mHpz rzD\7uU. Wm{U(J$eVFDWf8ك>6y 4<$iqB.P֚=nV׾g* ((RKfMH(A\N)5 6ҘS{ek!$nw"pH pR[x{whrm},ž0著 W)*TT $EUQ `L10F 4i&4i&CF`J2MFh444"~A&4' OSShFMO5ODSOMO5?TL53M)ɵOOIޚL(ّ4!L@bSbOCTH|j&OrZ>r=v@[MEh_siM 'B,D20QAfMO΅@$岜TZk MD.j ܂ TޔH߆O;V=V~2<6c 8uAmB얢a|+[N.ТC)vHg@a̚Q@ !O?Dwڠ :<(@8Z s< "Q zx!|)D=d =NU`PQ:X/"[(H>{&.ISMQ[S*UY`m0~J >Ѝ 5>6N.o )mPi"HPPEx( YRTQhAyTrlP Q\ LiKO4 SW5I/SI)ʣl'Oq3_BêiMz*0ʉE eghLa Dz#"h"?l]qRA$ arCOTX!veO?So*"mGǠoYuyUDrz~ D$_ NGv9h!U MQ($8дbĄy"t@9J Qfnjzuij 9N!PR)HHKO/NTa:.s:"#.5y#UVQ1feQ1y7n[6d<:ɼ&^D\]k2r:JV-%,;CnEP aTPS^[|7Ĺs~,n&dՓZHw Ӎ*su7Vjj7yNQlyYy2;i,IAW]*eʭTڍw뺭P64^&n@s|/ܱz^K[M}#0 /l>pC쩩rUwy"q<  =  pxV:( >p;=8P!(AS}#Q1.ޠ>SFlпQ%5po4Rїƀx)HQ{1`RtNي[a"!<8ED"nB'Ec)Z{AY ]i A BP@'g -eߑ& +jWJ7*y.u_õ:njgvqsӖj7o߂hp0*6Fբn%ON>J@sy: E=mh ǎʮ[D/K|vZKQ4=Z s  *(D?^َKڹg#CGpP^G-+{jn?& :i/߿-Mc, Z:upz s @;2;G'4 \wE.a3/篋s8u  dR $S,`}!wmnE=JD)$iէD?>-:J4$35izȪ)o$2 ~;n AO'7iM22^H]N-%a'@"yҍLt^xQxѣELGxx#e!P {{N}ƶ)@*DXZR #AS,`)g_?6v}}WL C!y f;Gd{DOAKo{YWC!riyPF5Ӆ@ g@H1@pҒyݒ!>% aP)v u[P wʠΓˮG r][9.ꞧ|tz l"d&br">p*\Cw_OT0tyt$C75 0[7e:c@eҷwbrO6kIHIhlfnnxwMzdz-% * (| ?>Ϫ\<;np|_./{sV6edƃ9 2iumȁ-<Ķ7C0!C?r>ȣ~J.GEI'@ ^ Te#aqi ]B}EG6*ajĎ:['#!@Cs<8i5g?1="HH`}leř7?nN249Λv{ݴh{Z`$M1o 87㒄R.׋dK&kewSI 8 "6. X{\W_?I %V^)s]Im7~sЀ l`7?&7@S>M܃|{\9 )l%4 rBP>%s&d(;#]TLno +vqGnHmx> +  E+?H`ٌw5*,FAGA)%CRr>ϩq+ɇ8/nƈ$@@<ypl=Qo8@K54.UHB4unYA @t!0L^>_0$kKԴiMbG@Gn̂c%wޕN!kvfeKk  2/9'k7ҺW?.I0Ĭ}\Qi WiS o'2=1 HSⲘ7:_b\) %p#. QcMAY2(ȮΜ΢K#J&RǘǐEU%1#X ^4PX0%X\.edv`*Yop ALP!"52 IqFoeQ\&€P~7:,N׈F 7A$wa qD/zFOb[|z={ՃN!&U(/"-QW|%`vFAI czC(yYW/Cx^A@}($GO0^裙F0A~?&7kST 5<]r.L6d" 72o4~D{&7!/ӻ e75Yb 7Mh;'3u\)l5_ @ >h7p䵬 iF5F7XRPuΑn2tЈoS6y_#~`]DI׸VnN I9扪W '@lv.w ;o!Wos4'>1)#? ޺.Y'`\ƣ_3"@({@Y5M\Ӥ[~gύ$!ZjG/zB1#5`dUoUKpdc(^G$vѧgơ`Iɷk%-t4O&. P~qHmAv'XPMSL@sԬg  xbRiz{%Rr~-s)g{"r91v*N9@A!@P3+cY"tKK^-!|]bo'ZwSdpR1<=YiYOD@ Q3JJ`0EӺ-/,ِx=Ƕ@hc/L f@-r-&0&thIڭ>ZNeoyl ƻy[ 'A`L9ρvOlܨ]~ d Gh|ZDv0nAO { (z(|"H A=Wtum?:*q1EQr b@4(4 y9QBE0P3 ! AA3$ HU0RRSHSH LLBS PRAԕ1C4LT%3PA 2 PD-D5 TDEKAL1DAHLM$EM3 LQ,M KTĔUPET@QQA4̨L4H4L $RM!Q4PA-1QEQDPUULP $đLS AQAE LDSADE EM0TғP$S3U4!DAUIPЁHP4@PP 0CDSLQKLđEEUUTҤ UPUUATQMREAAT̩,UDS1DTEPLDL0 CKJTMD$ 2R5APA0TDI-T10  T44THDEĔ,DTIEAAUAULPEDPT4U E3QKMDSA1 M5QLKCIAE4AADQU1M TE+T5D̤M!II4QTA)Q,EL!4S4TDLTL0A1AAUQ%RD0AEL̲ha!` JZ b(!bR `Xj))j jh"*&jb )F)(h Jf***(*"&jf*&Hb!j""* !HbI%e(bd a(F!a)JZHH!Q&" Z**H!)h"" b`Y(hb%!dZJHa &"H B d(B ("J( i&BbB*bbb&d bH)h)(H B("idi)B"iF!%UH!T d CdrYAiQ PPZIOWn BܹU'~/$$(~/߹0Ma PTM*b *&J#_;0-TdbRS T3%PE 0PRT ʈEATAUQ5E,2PIL L2A$T@Qh)&"*X)B" je)""("jf"*j ZH")fb(( &b ($$ j"f* " (j*"(!"YhJ)*@H"cpaiR (i(*"&Y **H"R) *d"),hItߍ3ڼIY! Oy;mc%E4K 32E?i&/KLQ4D$IC0L%Q1K$T-$I %3Q3DTA!R4,14fDLK 0UDDEPUQ2!QLPд%(d($/!8JdQAU,T@QDEDʓ1QBEG PDP2C $@DCT% HDE,LbFШ;5 |zG&̀PMux;`*) `"JP`6lKL%!MA T-QS4R3T)15 L1%$IDST0E LPE PA @DAEURK RB1TIR )10D@EDHRдLD-LL3 $$)bi3)$- 0RФ1ECHıUJBQA!35)?YP)) TDT 0 KJTRST@ХRP $4A,IEBJI  HHPIU4UDDTQS1,DC!D@CE22Q5 @JE4Q1KdDTR LHD13 PPTDM4LTĐESM%  KTMUDLDT5TDA 00M5RDLCDEMD́1CQUEAQ-5+UBг,AA1UIPK3!PDM4$BA44! ?1&fah!”R%Q0aSQ0QSQT15J@I$QSMAT4Q0DM)QM 0TMT$ EI%QM T$K QKIKC2SA3BCMIDԅ2DM%IBDCAACABATR1LHJQDT,5MQJ#Q PAT H "G!I""PSL@PD"H3%1)%RMTTTSS"B~?PjDR!`*h&"d$RR<)@"XB))i!) )$*D $d Jb)i)R(! h1 ) H(*#($e j$*JZD* f`"J$I dh1! BTK(R5I@DSDK5LA ST4̄5 J) QD TR% D!$0DL$@STQCQAMMDLL$D50 A+DI 200Wd2("hY)R"Vb*&X`PRj"DAZ I * )(YHH&Z`N<%MAE!ZRaTHP D`TP" *$%%$Q@QD;cAyTjԊĉKn۲ٶZ pt}D)IlBD{S".a(|>;:_0U]X|mgɝCs gxh 0 Q?UYJ-}- ;8]ày蘗z`'_r-t{;AβY%TgF>2ܽ@*M 뫅f>貵[J2ǭ YcJXQٝ2"Ŧ(M\>xn05u,l$*G2Sa#/W;taPuSӺ,H=,P% >W#n'k2ed۔B~*5bkuh>l}9DSMf( M ^Jc=O/PSsV Xj3ʢHlQf--5OaEDI̒17 8(@85:6̀;FN|dlțwZk|!|&jXBd 9MU'GȺ=T8i*E3ijHiUNZ6gcx CSyx0"nvd*>}s @kº'g=%I( ᾽L/US*vݾ= *S׿eܩTvxg{?ʶdpx\3vkvOa"R L9g,qL Lqg+]L̠}(/Pd*~#71Y_> 2bD+hZ2[6-[aǻu sӣv&gv=v??D1m}~ E_EafVTvS\ l`t]C$RH5"O@tɏ.e˙nGڲ7n끶8忩pXޥ,~H/S6ĴO*0+A@U.t+,=@S~,tˀi*ysO=g_.Z6=:S7܋r++ ʈ rM٠ϡu]6k}_S+lM|۫`iR$(VjǮ n̑-X|QWY{zmlePCr%Ǚiy65fu #}$ L(C(nZhPbO}rvjnnNs;I4]=8%6U&\̓4#UPZX\t7p{1swuvUbC B]krċ߄)AIHW91dd@"kO›{ @֤E0]j,!ϏInW\Xrh%H})e4gYlyfpAunw( `.K c Xw#b0"[+{qt67 H6#0a Ft$a}˵a*­ެѢ,ڋr2jWyŠ|zis'T\ PLC"7n2>c'GIV83^1P٥WbL21{ yTvN~w٤/T-zb+Nvg4=g丼+N|A dͭbAٟV&V.̷ƶ%U4k8~Rlm6iX;_/oؓAUKB^_ p;3🵹|S+`ؠz0 *miɉ('061Kgau'9S+Kշ[uL^Oy@9gS1>F-CBF1fv֙]=h ְe-x]伿؝աՏ<]煻WƋzEUU_܍Q.gq3dfD̩d{< J"XjEAv\3qʮcsSq9aH% Jh(d lws$7_Cv;,}ء >/+Y@:Kp2F1W,ȴ0}=cI F"9~BԸ=c0'j~XXp葋`f R1XyPŐbZ#8"3)˝t'/xڗ|i" 3xh_kGMDEY\yRK"}(_ʎ1VkwghN|PSrVf7`sZN TVd6UQ էEM9⤍lpf 4>pH369>v`̉dUQUWe.TLx#?YVv fT[e1FT/?;ϋD_&Tj1R5$iϧ\[8pOۅ QϜcՓc;t) JKd4QUw|qZ)b, >Qʞ$\.,\@#䝅U[뎪-sEzr{rn;۱j|ތ!~T RnyPyHHmM+'n2L wFd3YRv_âH1#P*ʉr Q-5-RJGm=r|Hi 44>cGah>(9ss- b!2|NwzW1>Mf ka -¶114|΁G&! 'oඹZθ;vzeښ[ͧZ󪰩Gƞ[oBQ.ha`AՑ]Ӌ6> UH 0)'󜹢&*ɄF7EPPK>`@s_ɠtDƱ 0F/rP4f*B0~{k41GU2b_G> vܸ;pae 2W54#q3'f}y̤tgyӲiļkh9nOx^5joΆ I 0\ ul(98V5z![Dx𓢨MUMT7Z`z4>@~@DTLT|e|k'sD2? dW d _}wn$(*i`*6Zz=j*!+$30 ">-# k 5< 9#_uW}y~KL%uMtc$WcfYvorxC֔L 2vBM5K#AEW2/032hʐMff;EƜ7 ESP6u'Q >P>k5Wq mi6&&YVNgҤ5=2fD6!!ݼ'jYrL 'Ld }xf6Dn$rأeI!Yedbgo{#e} Vl}R\t'˶Tuy܏7,9Vʹo>HS1~&g=GuM 6 '3/>LMAǏЛ_|N{ >{=Y9xL,pZ,TI\ވWj鿢#Ľd,Fʫ@U=ɧda<ˁ-"5?" +#1W CmGQy~r1$$\)p!E1vV.@}*sP-=n7mq';8RY6!d񽧹IE%eZ ,RKц]+x.YهWi `2ٮ#v^Vj3&Dى+O6[ڬ˕WÊ!bhu@&Xlj,A4yG7Sek<B;(W5K(ȢdlXQM. 6%lc$##QrwԴgKFAiM =D"A Ј@Aήtbom_/1/pe=\j$ DP/kXu9|I2K䎈^k= e5[=z:" .sHp=%+&%3;8ԜctXfs36;}H gN,/ -3SLgIc ?RN)on p060 {qrz'پ"dX8lχ8o[R>DCP#WfW)Ýc蹑 pduPdsqЛ"8i }ۉ/g~ֵ?XƾNߧI}~h>թ5ʈfFC'CJ3%+P"~1>v^4~ 8_%E҅irLCQՇ e.RU1asRZ4C+uWfH^a?8TnK}L#W=-eEp3N80 &r6=fI>x{>֓$&.$I&dq UA'&_R]RAQ,2 U{?6OJa³\j!V. =,9>hPֽ= w"̣MگLʉ*:]Mcqy'̪&[[`6^XCo!oi̇d&&z {Gw\?$ʏjlsMK;ے5ދoc]34ɈKӂO^)0و_6Er+Dmj `+*f;2b)jl_B_.c Zz60NV6P(އ&Z7*E2%PtD؟DuγL՝bD6\#5&1%T V,.iTMjMwrut٦K]PSФȨ. (ZuԐ;W-O<^ JkUJxpO,9\&o燝0sj>p| is Ͻ dF 8i#"}g/Ǘr#gʩ_k퐝 #Tx^||?jN.m7DTy|޳Y7{Umv{sGX:o ~4'q+*' 5pC1Y|8eoH !!CgTHѻ;&34@v(3rRp7 >K lA.DS@Rը=`іOnI &=Ne 2-3Ud<,2e.bحm2.75*F3r7;z5$AE1O g>F >XLGL& )CB\dUT6o7~ aPnib.^MTѲMcȖKHԵ n"sRNrŠ]Tx Q7CAlc(3ISd40}hCL6%rϿmP-uxpaћ4u0Gyg`Q li#iD4j_A 6qYy F 0*|srUUV׹6!@Tij|in$t^9NV lTUQ%UO0CKy0ff[ɾ4=ۛ^*oSOL6%"Xٷ;UFVV7>[6dy u+fB YBk7ܬA+Y)?AS [A$QE#xӷR}XB-2>M~1RڔXH 6vvIx{:G bȐj*h|Q)L=\QYERWO  b)>Sj\nyУ6wUY \sSއȗl$aPw M(Oga/oDrD~cï5QyZK\䪫bhǺ"-rs qV+A~r1:|+ۑ{7%& mDDIdE/wSz-+L{ee:v=٫V5eqe*…6gfʆߑ"E|wWMaV5s Z053`fSG`Z竧óeCTBA78!h,kL=5Խ;>]=IqaeVMAQEPd噎NEQ%噘|VACHXcp(6k&p"7jC#l  HRWd)BIf~UWxs. яZ^ts[o{]>N۝~jk2>t,BJO w⪨*CY{$o7:QI*V7#6UqeOrqK?}70[GXNvLczKnV 2[*Uf;m\fO]gz]X}RO GW6dgl <|\&uh,1l!}__?wLT/۟nH| s?o--a𨏉eJ›d'ٌ%6j?l|wPl g۪:&+r8hye1/f8x&;ݒݍJ74~kqOt5.KέJUTOk^ #wͣ ϭy.J^k)i`]~o&0Zj9?y A{F\[F(j:'u ~霼C7j"m PĚwXCv٪Q{DŽl2wjkBR/tL>} *rPI~PD1_$Fs\#EGoo^Jx6Y0ӈziKxNL܆~lJz(6"4Rbv'uDf|{[;*@ 1I?q0Ҝ<$Ik>vXjж IgwH*Y/Ņr 4oQ>L UTU#OŸ؞p[{F/ܩv# <↔=I@:ҵ( >єBOWW_Ls|j˘ ![(/JkvHv~_Ğ :On;aߚ?D"HL6ma%YZA:" w]$+lm:T|)2+U۪>HJ,ec8\P I?@2K"6nR6+ 2lQAP8 d~ԕ$dPPȯe;a00YrVysλY7MLWh")r#YMXUvc jOW/x^%nUŠ!$vfW?)tU@4m<008X~U]T×t΄] 1QAFPFcBÓ0JuyCIQtjdm=ۺc7R$ scȃ/Z/Ӻ `@HDaN2b"=LKA>VM8'jK:?ΊKE܋&I>=0 1'J6=F&ݤgٟ)iud:wRsɡn0棙S1?oC'ܔ=^Bt0iu:[%1<[w?4:?ߤ{ks6x;sD_&_ҐN 1t߼ԟ\[wsotʫ7)UFz?>LJЅۺ:bvc{W*&?w,ɨRm/tUHM:u!I-|[F.Ҵ[5I'TQk㌙׻DT=d/a|x?U>+y> ;;lp?~e첊Gqa!~IS3c:G9OHF j1ǤMR^pt's@ TQ|oѓN? 0Xyr0BfTsjذ8(IgՏq$ +t"~ Χ>nʠap J;b8zMg ;_"W_בg##?-<_<\~ }F ֥ut.mg) sdSE4]nPɌ+r(Lr)< XѓswEqw23uhkzz3^c3N Y IWF#$T6*ut8#j{ҋ5K6?PCl%lli_7uôo/Y=LJ~cF|.cS<_zk]*dwmn<1<;d 1kmi-+Cg{!XMwWq9X$=Sa/3QȸƲazl`%W`-Cqcw5}וNrۄUKiGz:vGE9Ɖ9-+%nQt~zwΓ-ߵMll \~MIW>7Gnc{ vJàiArt 2 m1[P R)׋Q^$z<unzdžg@áD80,tN$p+̾F+d}sc|k)Ôx^d݇E--cdVlmF&NSv&:}\1~i) WuB `{+1 !]>KbY}?Y$*1 y|c\Cl[?ѹwn]ˉ!c Kn.mL]ke>X j/?Vat@w}b7+(J6km3W{ܤ;,i;')=À&DH~e8Q$(X32d7f\=%,^缦3O.  ^މ˥0YQ}4$@ CC>Q#媇]<ɨ|ak &=%e);K?tSu'c|qRf'o3@܉ v^AZ6+΅gRɕ蝛gGsUk-6MHtWٗPcJ2) ʷ| 75Qpzn*T4dP"8r8K_CXsI hF_{}S읺uO|(|f#y`M8ΤoÜ}:ݚN=TgT93%K>#q !)⡏?u՝7yCAi#-C)S%,G۵H<~k}ڭ|k 4C^9}B'y8_IBvQj?qN'NΥ1ʈ>rVYYhuV̯ԫ4ų%BgF%Ϳ!_FK^ KCoKF0y11},ՓmKT#Nk27ܣ62uML[Ad士rh<{Rq-yRX4#f6[?hiZ 8SSyED /APۆ9pOU@{P N|ok7t yTȜK=oU_g.ߛ ';k͕{PPޓLg}s[mg YVEvSB0D)CH >^j6 | ^4y<@aeiݪ[ n^Cx?]nhoT5QB›*& D/:?L}V;]a:=g,3>f٘Qc$;nES9n+@I@E5WvbdEfPştYݒgx$w'iY|ćP0lDIJ5LJ.8}Bi7*X (-[ؚ|T@TKRE?mE J+зӣClaG37Z+-PugDP=k[d|P?I0*L% !1N_QӐqZW;L^KzJK>uTUUH0LTT)5*Gz֩Sܺ6T 8B${ A}JY !B#m%}2"䤃Ƕ&I@'lLO0yWH< W:1$bit)3j ?Є/ Ld)'3?&bRRPf'>NoP/q=8vI$&I$ &EĄgI䆔ӥ5Ff%)6unh)w-CG]d!gҤ&jQ2Ш 4嚞 l#Cp{暫NaØ$@u{66{kE# u(H?ܨ"-) (f\h,b66G0Ht[kQB:⥬FW é bA3I E0&E݉ NpyClr2od'ƘmC 2 n.d&a$fa- `xn<p":ƿG_T4ͻR4z*|{/* 1kGi{"4S*īሪԽYG+7qHjFG77d{Kj|Ij2-ӣڶ >2]Ca˒9tY#] J䯏Ɗe r&9AZVB{M#G+5('K8Dh4@Ȁ$!~[ ?Qf\Womfeϐyc|ezw"b"HB||q #Q֙JDKS E,1W oedp'f/5́ڏ3""&&7-_0^*h4uk{ªwMkwɧ:y({=Ci;/ĸWWa5:|PB̚>w.U{b7;mfaA#irb?X\3 @-yA%Fq$6ݴ=o.UFvDX"?G3Q{dl ݖ#njfMYAi؟7v?k)QU'\|^§d֦H>KCѮӛ]:$MIύ+Ⱦ]I\%졋>EU(,˭֗R7= E*%/ YCSCyxzKp.JEC)g}sEFo6=1"%}C>h4Q?b ,-s{=~X*AΓ1FeЫbp_xlpOfYig>j*^8D:[=)QIӽ& r>qҕX'2i1fM'Գˡj1uٖA( 'X)Hʧ=U5e4#wkn5?BѼnflIJZҐiEag_A2 E'ÜZa0 |;tn^7NdY=(jޟ?oug@w(Mg| /*枵1ܿ)Sj_w~)t反Q=sůi lKwSz*}Yj~#QFEVxLg ݦjتڃE V$\S9{a\ EJ~oa(@k!-))nTN+| <gшH"9jW Z#UJϳ!~dTz" I9~ ]%΄~^6A\` ;s"h6 .QfwꊩG5Gs]>AG(oj#H2I*m,>]q43u"֡<:MDb{K/OGl&*Ty\~23 DДJ2$'ɋd}On;p'gy& ď.%5.LjCOp8WSLt|fwuAE=48{(M 4q GmKQ%_릜?/1>?o|>$K3dփ:mQT_٤R^ UBt)ʦ9-3D$Kp\MʠCvߢ^E e"]fv $ 1 "**7sp00sF@4*U #FHkaaƁ! AMU^mP%4UOd%'0f) JCcBv&*FI> 铯D|%#"Eϛ<'Ʋ/biD]:dcbJ/CR*"0 g:K7gkɾ!'7Uփ{/W_qiwJ h{*1Ez& 2"Pxb Q \/qGpKc p}d$!b񿼳4&w.yVm.vyt|eg}lYFb(TWRfmG^ YܚhfW[iBDzև2gӯyõ=so ?:O"opq7P9OE:(\{⦏,#k R|Jgcӏviw6R ǡ%` ppc]OlNzc :5o;H3WGSLYACTV o%;z߭}k=KY<»-(ݝP#> w !\P<^&]}(' Bj@0a$jSthd2tsYYg P`ŒmےQqys~ 2 :v4E0j1Y{֗hTx!rAB⎍hAxUe9;Yй+eg{@&A.v͖6(kv6`j` SK ӓoF X*8!ݷÏ.)Hq×[smw"+liٔ%[!i˩~m!'ةЦsT~%OT 0tɗح9B.$a4i yIEW)b`Y ŠE҇ ^D^:̡>ξX:t\V'-a,^ɲH܆+ig$TҵJ.|Uy\#ac(4#(qMS8m8oҲ /Þ4ANwG/ar67B46F@bu~#֓*>o;lH:T,&Uҩ.x>NhzPuoVϝ%6fdK G`|%E4N"\$|s)v IcufTSfD@.2 eI7E41J! Qt0B[G!/"a=[S\镘n~Lt؎LNwKByWNMl.E@Sd) `)^_GwBۍ0)8uR&bV] tA 8Fq_]ZQQd7o=S$_fp7#4,߳/K 9uzb0u_0ok̪`6~+HY4{ےʔ /!2^_5&"Q'f䦬R Y[]\")xFBY unܘҰ6ƣI!q[uIF T 96M >fuأhFB ta 1ZRNٴVFD1. c]k{ß?<.$\;/I$(vZ1ٻn3332333{REY2,;UUW*ʪ*ʪʥUUUUU\ےꃎwS_I >F5;8ވ`&_[BfqX,z=f&-uRVҥˌB-T W[ywd e:}edO"‡a{OT# a῍Ei9^zୣ@V{?#7Zcu\"q5ȃ|EM7o^kJ!adQm"bֹSS`r[cB%ApAEw\:y2|眲rKAcpx=8/ uȂ=87ElTE8o|Ad@f:<:oA`Bn꿷|JXvZ ; 77=/(~w>r$K-+ä^F})o` ,?WAC#d \f.ml--%*nJ/!n?7,\8$b)"ƛİq,þ[_eS#AE7< m@Y-+dbb2bf+u\e&fQr{Z /@*O2y/-Ukx\ܥ8#?}SWgӝQ4 "wh*]<(u@ \GіOZR|t=R';!HB$z]y$L#! 540JK?)CQ,3vo-~ I> CCkEWÑsoS}o mWbZWX3]l$bE.HzH'`neuK6& ,ѳ2զGE2՚9wD([zelmAuk$uj,awԊt(޳l94{xl̚S-AT͝ %(-^OD!}{>j]oS#Ff&ebkP+1յ o0 v_18EG\MR8|F5h h#`]!B`E;n^.gp=ٺNڳvQ?ٳwީ=CfuKj[G}d PKx\rnYB4LazqMwF: o޺۝\g 뉥<CM V啡4^\$бO͟6A:E\%UWfnvpmK(VM b&]KP2+DHѸX!Aub6'c'Q۶1UiS6U+8.Cw_81?K>h1H&τC?r8'^*: fc}EaFR.kHiK56c?{벍̮ 'cPaZn:Yjn5S̺m4fa՚q8F>|c}R#I.X,b낽p]oQjdJFß)EpK ͵6=V.s֭*U !!Y[M&%y㧒9jb*e29}Xiͳ<W:Dc9M\$;;U3V`,z*% xnjj3RĶjXk]$FE!~R( YHEYvjo]0|ɣlE 8KF:HԶm1ˆ7oaxhL|"8Vts '-uN;lL8fVgԳha@⏺,Io+)?%>_ڟbJst9*MB,IЮ ,!>P|t ź'z)}Ǖ칠|E(dn&MQB?ol= yA-q@JZږKƏY1pun P5"H3߮^4uq~ wUz!M=f~O7Lfj:̇rnH#s^:$QT95>rԺ,]uj a^ B\;Jv|IH{U] QoՋ;9BEqI%XI.X-kTsj4ʘy$yކnfM,"ڡzi$&($-\!|NTnݴj eǦf M/9k9eETઢHѩA54HPb**/Ãg| VOs6}ҖY˗dc1j4cs9RwyhآWk:@PGB D\r8qUNXCD2,1>fZn]@CnGAEeFjM<1740ȶdž*/G!s>kh(篝]Î=#ԾG#KBg[{(_ѡBl\WWUEBIE@l΃:l[>L맋tfAҦʏOkfpB;(/9!9^ !q9ykR)ECr1/ݒÞЧ$85f*v)b67^e~:eY.fS7sg6Yof!DpݑE]mxڋa~z[EELxOJͶ}AH)3fZB+ &+߈#//W>=ӆ@4טϬLvR[d9KQEOd&(!TaicFo:!PvB D%ɈuVue/ҺDi [dQqPRY> Ap(MV. ]=fd.2>^fx2L Cc ׈jSC% oՕLʄ x,:' ӏVLm+>aa"9ǞIjQ:M J@_[gwV;rr-r\NQ(`eG7\Cu*t(s5:;)'QrgQ6Kو-k;Iu^<"#7ȻucTo-05.:% b:!hYJ&9YkFĞ_6)Wm)Bb` t_~ ^Z6&\#\ .7EQS vFe3g8n !mDg~*k㈛d'ACd f?bߏ}6ӣa Y< %󞦦Ը#)==;ƞks6;vq4I>Ƨ7>=Qrd̔in ۴-:!5qe2Y.n9C .{jv(o_d AAUUٮc`aa=:~k< )\~ sqUUR+w᳗Rf3}YbLNs+Kq&sF)H:bD1=zOSnyAWS28O*Z +Y}FT cF T6[OWfΎ.6k٣=rκAEb j+x$(=0^4ESxǻא]"UgP;OQO]6X}Yˀ\h!Ĥa|6+XSĮKayْZԤV.]5] %\o6cFl V'VvߋIv|=W(o\(x<9v8&a@XU/ 5CTP,2PQPikLU1%jc.Y\# (d.VoLk Wᐥ6UQ|qe~%U`0Pr -) z8`D79/507u*0"4iNrdR晙6C\D݄"; tV=RI?r_0 "f]I{4 M{g[Wsj`rdc '+.|i'i *XoVE&v0DTXHd@سHmXJ6Lp݅P+uorq3鮻f[Il^޴1KWSo"QL ABUbź;d| fL5yT)shw] lQ˭;#far^p8g9/Gˇ , ?U^śV7TyP|?C~Qޓd_ɔEQg7hEx}OrrG5.JOzZ;%]~{т3+h\v`~{Heyon$Q9U#rm.1Eq˽2ٌ]6-=D1J p/4q/Qv!S6ϝ 0҈$I 1Gd r1|h}x`1Y5p*Z b*@RU/>:ݻKz!R`y՗˿D`]zSܽ&udl8gH0a.6B5?^uTD"ؙ SJTw?ٽ#WvH7X &ΦD"n f}𸽑}՞bi+39Gي[Bf<ӄRyiVp~U:/BsȾ$sm~,aZQM^hqYpӾXSV NӟHIm&T~0'h2Iy Wr@/qWI}Qkܫ( 01&y;R&*:\xSEJjXSH1脎A c&}+i :eUM3|uv36h\ngXĄ=!%ib2i:4ImK^cX{>Μ&݅]vnv%Anfb<"vghv]7O0ȁ?+FK6DG0Dt):FnC&$zn7+KΫCc%m!Klhu*Չjf©%mŒJjUXKE15"mɉiy SϘBR5;d1ɯi2 orވ wy0 9dWP~M` /%/ y9OsݗcS#)őA㌾'F3?F>msG㞸kpgwgb4-NUBҬ++xQ=3\zL*$MTPU&i$E#gB;Bb,"3G慂REAFbm. Kz[:݊V8 "^  )xMEF-qO7 캦ђHr;)meO;+h4!O:ϧ5,6-j_̻uԯTSK s.6֧&;5tsC_ML4Rhe^ϥ!8{! AbDt0X\ڳ z"""6*1|cGHî_I4ZKWNLoz܏MNWY%w&QaNrHL&pYX60)L05zkKF#QoF%y 77i`~. kd/!Y´NS/K[V(Q2?0TRzQ7J!Z5L/׌D~ xMǛtsT7f$-;aA'4 KZ=U'Ipc[,|/.Ly-"au; VX-VS\G(ȓ>fk+^`i,6kP \`&|"WdKuq5}e5܅s1>ÏldˣZӶ.\  ,\qQ@F샭2C75ut(GXN%MW'hԢxYeUTeCu@y}& tWP#{:}d<""".Tx<-K"17_20 ɝ AWqzĭ3^uI3M;=ރ$Mừ[u,zt0CĊ>1|;5F YTUQUE~ڦL7>_;~A/_e E2BkoLtNѲH">"}}+Mi$%v7kuj1̳ (j=I*'Ga iVjIk&ч\Ws3_"MJa|c# v?l_\xl!$  CbBe@n+Pub@|Xqђ-lTt ت&cQ~Q!Tbv}b7e:ӑ&Rvָ;沉~cj]\WMxd }qtD#^͑[E.v #}mrSb:醾!JsXi(߃C8?WqTSM EHT_HH^`-%';ITTnatTIWqwOҫS皿sN&0 $hw0kd _&_+Ez)B.Zr)T.OD P'lI$T{65}u5P0QQDQT٨RqˏM{wZj='OqaFRir(^ nH"g'2OΗ|6TC4"5ML|^R1b兲)0g|P !*"БڴYq$_!A{Eǐ*EX=l*w 'e,ٓ1ȕVTfC[|h\iAjx *nֽev inUpR ;>yc!;2ٖ $U뾵~wd$ XH:;_3K9qP<~8A/dѪQk։~|FO{#wvUm%iYJlb̲qUUN,+Η,yU*R≮sGh?]ٶU567z9xw"F)ߵ$ 0g|#\}q؜-T2ύ ҕΔzcзch¸ ^ W6[&Yк:~LdGQv/wۋǼw1Y>yR\W5[I)4'zW5#Ye&ʓH#~qz]}8hι'=9ܾPva9֣xLG,Akk}F!0eU ab&ܲF撻\ &Fٴ5%´ԏp4%Oo ҲK˾V',izߨՌ;Ӧ#/N$kIEU )GuҎ$l;\ &FɣK^de]7_> ISIup/f;Xb As(YPi:lǴ[3F끔O!6/Jɹu AHt |0V+k6?_S?.-Y$#290='UcwAV֯tivRB >dRl>MBDE^d&ߙOcBBڣjRNEx#] 2;މf*e0$öRk~6SyY6_k*b1U,?B4o}l}15+W7NxbEv)asG}ϟh4]]=~SxdrK7ںOB#spORELGjpүz#5Bi͐b;AYK7RsuVҼ͒dvh  Pׂ|!2,Bxj2ʎmd:AB zˢsG㥱,-ut6H|Iː[T@|GQ.u4¬4SE M2%Cɣn]2uwDz7\&ۉ]̈́{I^ǯETATtJ!L^8G_)S@lEy \BtX ޵:{ڱxCԿ$v1D5-wLPQ˃l!p.Y%8B֞ X]7uɘ 5*!Qe48|rc`4bVaY\ͱ/%pESJ=N(=MyPrCB3Յ)\) ;zAg'5H܈皨%,Q\T|Rk9(W12rI`<`<{Ʃ :$Pc{ITL<6lݝܰvE.N,Nezpf[OX.)I ja<1۾@KZ ).2CYmɟ=^, 2Dl4Տ 9^AE.QT@uTȊ D!adN^8.7VF&jy6#VuQQT@[8zޝTݞ^dY&:ljT؈ G(a=RC\],E>#mJ͕`O/m%I'f53*ۊPzCFc OcI12C~A`;0bROM [tVWJo7 ͨ%3H{/D6CbԨ*MKIsqpo|pZ\}4hMGhv"Yi=*^Ȁek< X :xW\z֦\9f)圳C[Ϡ"""&DF+~rMf}o(KhAMg@ ktE'?@D=!Dؐ9`6(#$C=S|f"SDY8jWE&'&)tdZΕ~Z%UG- W.pA3ea |ϭԃڌlTp9yu\3X:FWf2ngXz3AKKo ;FAHT`QUrˆ%2JM~ƈ|n_5&|[Ml>c/Evz"p@a1Xeki m]!Q@QAC$ n%>FKÕ:\9wcTx.fM3HZsgqEz)gۓ17zClEX"1̻p 0 8F LpYzM" B)a*{>b1@@5 $U!uĘӣglRȘP2RHtkkP;;,Ua+@F((׳doEpVl+,0$~b՞x_\1hNҒ~=~@1d(=>Ҧˬ锔߂M^bSTL2H lZFWы%vzw!6FZîR5Qtԭ,&l{_{\BuܱG%QiW {[G RvaX|aķUɔNBIK{Iw [џ5-?&&[gu\Ŧ'K_L(]nnI$49:iDU!h!_fÖ +xéng}qQ pfLU_*v_)}O5ϧt_bſ沪usHMcxpsSB>RI{17]P^tN~[)2J/Tdz@>R: 2qq*9eQwCe?bF 7=IlNj&c|~f@QS*m0+r1 6qd6XYoִj>( Ekd3'$:AwtNnRY09sl䂫#Q2L|Lq,re|˹0ET?[9ohy亝&O>+}}]xV{<>X]'lOe^sl+&M܍rkDz#S]M `uV>޶6IyuƳ4_KF=Q>Z5Gzk^yFOsb 9Z0V#BYRۓA1W>73eI;o9bŖݨ_3ح^VvOkiS?/Cuvs,VcI^tUck,UEE74x7arg0YN-efaUEV[otGo.3j?nX7TZ~.7I^eQE1'K]9&hcB0#fjsۼBckncֺshs, sot il ֛r=("Os7U^8Q.Ƿ7чi)z\ҦZr{k@ ;$ s[dZ;TKBp0eӷIիaw^ x`ߞe? 2'?ZkrJPN=B,aU/GTvQUeu,,wqXQw:dOC=&i%'3 p7[ewcTDҐ,Amp~ŢH6&cR$(WI (^p UUM6 |t鷘"5R.HrO͏Uދᠣ*zm`DU6IITۭ᳛/Uf D$ h:ktR6FTj꓏Ljڑ$UgsД5!/G2jiChL(2Jv?ښ],3320`NCS4Es wUTAEٯ.:GwLȪ*lHy+5|:vo?j|3s\m][*>mqqr9Fƣow-њ yM8M>.Y~;~yP:BycR f!W]5qZ(qT=vOD΃#% %"Ja߳oE(ɪ{=!m7 - uJ Jvv;1 E H% KӐGUSHpƃ4W5ҰLdt9ML(;۝R@ :& ,S0Y8/ HX*ÆGRo79*ʬ̘0cLQY3!e LC 3˘dSTVfg;=O^r#> ؄ycfAA[e6»rVRc0#=Px꩓QP%~"G`\+;T+8|>< yH$74%Ti>_;FƤV-Ʌq7Ϟ@Lm?sJ4kIm #oQ#}|PX! P9eu@Am /(6d~GptTs8` \؎=2jDs'7+H&X! ( 50 QD%±l4 0"ce@PA? }BQß[J 7zX,E \()oEb y\jHtoD< /!ؔXi۹?d;lv-#$  ȉPa*D5h's ?BL W={~kXU\I # L)G5 dE5I$+x…! U ?eվDe榾 2D<:6Z׊KOS:ϟRx,0;y$ݎ{]qE;Tw ߀Mzڈ@ â{4M-D}i|fMx6fy2/CDDDQ:MB& DK-D2$8'DF6:Ch]%Aɦ}}e8O|?ZYy\)Q:}a>oU$D?wѹ島hZgf0ϖ(:Pì(ApS忏UsKKQ5h TKQ:(%8-fu>zF*CFXPĤ  R9EE_5$YuCqÜpr#D,=+,`B U/i叐o"Iל!H' sy⒗h(ap [,|Lv{ @b# |U [89?XAƈT 8 &"h3(>J8CA"TUPhm.+tλ<`e;NBpF{%2Bl.SsN$]q0$<ӐY pv?%ߥQev@社8GPVv8ʜupxb~G<5#mGiW!ﱑêi*!K,#"p-mejX$;K*,%`AKNt_ 3E`OErWp-ie.q@tZd@=J…@!u'&oDXIazy^|z` dPDI"4>qޱY$&(a&pbPMP(cwV !R!ZmMbYbxQ]ֽf5[u QP$ ث$J Bٹ6vN J ۜZA0(vO;?!j B LN2wfޖ>>< -?D?/_ #5y{<_&AF9X *YhF?羢b fɲ2>&8I'(xwh}-Sb|g{Ohn^WB)$d# #"0e#FpmwZ_%AhPa%EHf9,KMb~r^hojzK ,D Ï$d1lOPYoo)DJA)IIHSC: gi0=(\j*3W脕x.`L-R}rh? QAʃj1L3eQ"-+ {Ec;kU\YGsmXH<@<*=Cs)l]3z| 26 c !0PC싸0h!zXϦ1YSANF %-2 "HwWK^YC\S)(I4O*!05mxB"a5hAl̩uM9O%~n^{y6Vtyyp:ʈ .wL4NG94uϋzO*;垭؈\c*ĶWUC3$cBRO7=y/#I,؂!u1-r2}T+\GѺ8?W}?:!FӕпqpVP%ʓu JO.F,kHȐ ՑpX@ߟܝQ*^Li;ݔaϕ8r;]ult8CoU'h1#꣔J]uQY`:|s_nDXukrSL7훛iu/5szJ*?z޻nmGr>t+دܜk7>'!ԊMMv֌OŐ2rBm^hb`oMC iQ-zu'£<gO;4 4nҗ\<>? `|xgo|5DŐs{x21d ijne -""0ɂ[C *{? (b?AkxOMTkҪ=}ZS>m7%F.m`!vUDEQ1ht$a%" CGeY7:hŌdC'>O-̈sgz\27]IˊKޡߊH2xWBt)Ysggh~s 4c!Hr?>"ƽoyL`[vNْV%́ R8Vq)ZLfZ^ -B rՈqP6Tw;˓q y}^FD"wD2r}~&A k:g |qҞ?B d蟣UIR@,-ٞ |5q -!#l^3.^O<!ORWμxA03Br'6l бY4@_"I ԧMv1FXD-UUuQZ[fq"ce!R k Fᆤǟl8޲WG0A`GadԞ?L﹆P3?-bs8!S4`.z xwhM8#dsp`q!b R ^QTQDy-4M?"{$j*@֥%SteWDce6;2R/~mG 0 d.3n4Gѹ,a'r9WsiK<M¢*kMc;w拉nC5Xo\ sp%g>aA㶲6?q$ʤ.MD`OG?a_6ҌTS;Ykckr;=Ҏ]D0m?po~rY\>&gv @E pW} ԠX%ldfE.HE HoOqaF4ښy,6;:F4QmTG4qwӯiهkDl :XvAؐ>A!_<ѽ=^z]ܔ#z~CAkDN/l1-36} AEwPI؄'ƚ1=𢚅2C]AeBQ[ ^^%nD=y"|@dBt{j:5nP:I ЃRcx"䯱BMd};`XcH#jLd2I qsna' f؈qD3< HcuEo+Okwm,g̪HjIיz:yd&{C@3v5js܂Wyu^PZl͍jS[ejv#YS{X8@L7s%Phζ5QbkdWFfVs 7F+svpҟbpe[zM *tGix1A AcGҪT₊"_q o0H.0CP[ݨ΢:D0)ꇒ&>хd*<Ǡ%9% q#FXVGKlI W5cPd 4%y\0EA 546J1k*F.QQy)7Xh"4 dƄ3nQ&\gD!=u篑Eh L13,(,pv㓏R9Eۙ$;^F 25l`nCl5B `a\6Do8B#ੴ6HTm!uGR fRxtHܕp:U>_QʏTM3s5Ch`Gzi՟g3C,e+ˏshة0a68dQՙΓX\ ֡oZ(# (ulY#7ף"_ַI8cIe?!UI*[S&f_() Az V/#NQ- 9nKmI6bK\B"$EwrA0eMG,wn! EFE!Da9HsX0tI#9eSS|O=544O=DP; >>qǖ @~|k!N@ger!r&w!?i( '{GhB81 0>$ XPZgm 0d}vvKmSo3F񨹋α*#j{KF>+:0{;*'7qx򡼥sG:^`Lqhu`ٺ~s}盹ςG_ęCP"G`?m{G )*nh4XևQ+RiEśTTnm?iInB5(G#tKtA6q+:{agq s.4mb /c3T 1' toյCl%Z՞06rKKUɄX:J;Wc1Hml.+uIUD6jV]A 5x&!.b XLH˚V>&aj='^2羜ճM},mɦ,`GӇ4:pח!a 2:."tKPo%`2%j{Xw,.[mRO=6E_PU80b$&4SY\UUB[LQk& 5pe95c/ ^.:_yM:J`NX{kWĤ3Hm ʇNmh]|-՘^H f, `<u~O9C^vUf6eOCMuM]\STBP] uoovPͫ^40rrbSս s ҞTy4VL9u e[D f t6 B}w{; 2>DhʭrHJ440)z4C=wibY)q\m+,*Zz|ُwזfg2nM+*^֋n.C;m@CEȩl*oP9N87IywF6׳QѪ6hf2'\_6KRv9gnٰbhj>dmBPfV6ʞr ~Oߜk?<g<'iǐI$qq2%N@OT7!'um( jA%V%8cEc&o]ފ:=Vh?<k޻WQDueW1m`(J_OGO/LbۂH eYKPlնIJ"oO&gq8l]WːlyEMӂh:"NeDCvu*a7"&)2N9zXzm]ͅce*0 ΕNL8ՉnϬI.l:%#*F)jBFNuf2Ȥ!ꁲ?!v#cϥF r^k47vDΚ %Tc*bQ꒓n(7uٗRO=^zbHfͷW2>dH3'Vd#)$gG] W/7KgÔ_=V}᭝RJww*Ili;uV*B+ƄhT bK\򪐩ҫ^WKQQrGؒJLCV{WsD"0t0Oe:V}1TU4r̋H,hRX]C *BG~/_͔]*HgvA=H爦jQ^+$Uln7z]}|u޺(lR'#u) &53u}wmyS'[e)$m(a>O)|Muͻ Q!㺜4yQڽ"EE`K(@¾…(tͼ#@cW( cpuQh׳W4\pQBx7m:#^ڣ˂eZq7[ULWŻ^0YsZݔ$%'iܹX{dKCe{>I[$¿>mu0Y՛FLUE]М՞rt=z6j)7,ӛ^-3(qVP?)՗=ٓH)b[C7ٛw-Ln536-~].S̮|9t=zn9|DAq!HveC~/+0ҿ~;j:ķUFUfh_mũ޻͝^.]c& ̭H NT~C?ֽS;\SZZ<׫ɜE]%j kQ ˶zۥ;ׄuY/36 6!vv< GU5<'6^ B 5ӋJOM]FX 4HxzCfbLNf8nrG2䂰TDK)mTf7a3>o3} 1k&%( S<ǮczzXx8)ðcuDA dKy- A, ̣p)% T¯?P]MSQ(b~`js3gݶ]rnO)j C|A;f4 X S_y/w)WY?'s}ŇCo9{dq(CdͱF1b6ݒ}ľ?m,q/6W>sO|bPNf6圥ݎG1,)<8axj =zr2h +w57#4=cQʛK E+uTzOC& ɾXHI th(i_ٟ1#OKkq@Zqp]$<9LJD +p(Wt9Sb-xC}Yx+zgwfNA") !:?9fNnvI?tP.$U2TȉHYDRDxkr1.V:RBė }FfJ`t+^GfA,2mh(. "*hZ%@2ɢd&IArTjf_0q;C&ՠac Z9ឨ.Ⱦ9L_(6+' e1Ed8nfEf[)Bɒdx]0ڍ" 6q((l.FH1qɃ(OTn5l(P)d˲)&g"~xaADjPBAS'}u #72msVCHo(MTebB 6^uevm^_TFH @H)V^4⧮q|8M3bso85 &!{Yil jxwp>D(jž^G{sZ 8 R Hm P~ Wlp  (m7/؂d6&w02A\"e >f*ǢK%n +.^W)c8%;$`X$C.-5kм^OZ3ϾOxT{q_s89>2aN4*KRީȕ+=p9 ՕzX 4'a~ `JD R H cD[ 04}!#?Sw~=' 1Pzć Ux' &}iYPDP}?WNFuތҦBJ\_=~rкqk8v~Ќ4qoCΖA䅂p.]!|BbETR!d /{Z )\O =չ@wC;GJ'qNFLQNw"e;<5E6?Nh'Nfr<F;~L类P|9&܍J!kzHJcn?@~ZNG r/PP0:Yjh<_4ib^,:ݧ;-lQIփ8^Gu+w00 񛧩PbLby/T0§#A7LaqrY^Rg/A/%:(@aAFТο ޠnF֗GnQê,dG)?(xhh̡ګܚo~@?RhJ1 \_ \9ER)96,nRpY<{8{\V3.5^̆(W@a18rDMWj"+3\;W)$.b"#*p33WP߃e̢@zPx=u{=si(˅4EC҄Qh7챶a'?2g?[澕Βݯ r08,˂>{+.N3LaEO9yvuϡqhkMDvWyQ:(]XRNI%9&@vyHB xl 5)( q 2ɉK{<H mM5mkqf!=~ :MA, Go0P$+[|8`sڟyD7ߜQ7WpDe(AZrx Ad͎7{"y`ۆ\ JFV%Z(¨fJgie JKץqo+97Y?3lr9YAW;2[kԾr\'T M!Bs ޺o=;/?40=ҞXQX IW ['8&fPPRBEHGz_aeSzwP7ۨC 5V29&b W<·F6+)q(kA,64Mx7i410A‘*e;XiFd|JVp<"TJ tpj2<ǽvܘ{pwOȍAnǟeCN XkMG8L`lpsv|a_ K7N$!AH>T|Cg.GSE8(;N <:yз4ux,g<, Ay] Ɉh5l-TCaG9F.4ӧR)΀Ca)aBmak;i(EUEQf:KdQ/(a\|VodRv[).N0K';h: rkP wblMr)#5sWrm^Ѹ>ȡ#r0Pgp)qwrNhSӗ1ޮPg'&ڷȊGt7gE.**8 ~~pZp!0&9ܲz3bcSrpqݷ[t|C4bȈ#꼄 |pvx٬  ԏ^Vf0_ds8 \LIm܆减e˵/h'in+eym a4 Ԕڑ(LMβl_`"N?iKb.e1t3rhxblؗ0i3Ŗ}y949FfREE.99,.iGΖZ`H|Vs g-w%~4UGi]mѺZE]] LN>dso,IqߙKZo&+lmT:.9`W.TE9[- Vݢ(o%qK!`7H+Mu m H׏L.bQ9v͛6u'?NR6p]Au ӧXYYB ^k^!ۤ^PV'q_$Ĕp;{Pv%|cWHXA3m1mƿ'VvgQX}oOp  Z 0 ̀ZЀ+D\NM7o3$% JPLq?K72]ǣ(3* >, jjd&)aTIE%p"06:*X ( $(*4%ő(&^du67pSb$b$H :;H[m= 6#($_Td& &lPAS]]JD^LT2L, MPkVW %p0[p?rcI%_)4;PEc<`#oA^*SG4N r ]/ޏe WGֶ&[q襣 PPX;'5>F = &1mŜBKyf|b|LI!:@C gdL@nE Q@BRGH\r.| -"V&7b".E_f=,D__9۠S0TVVzUtͣ12WeDo۷O}Z< >ӽ|k?? `V=5[൝%^v>- VRNMݠIXKe| [W.WR##c& uCk h3x10FP /y6~hҞ4o{&?Leݫn0jlhU~EM1?s^CգYhp{34]n!צo0H juX`tXZ8-΋obisDShdV,*O4b3+̲,!b:7_Q5 8Ml]"z4%%c05S= oj-*!VYؓΤmt0 /IUH[mF C#/Xւ $JQ5,%vrbl5)IYX7 FcG1UhȘ`哰MC +5$!u7=r=&b, ;:8GVӂЉ PxH6l= 5JxQEQD!vP͘*\XAr!X_܃Cg>YjxE|9Rboދm֏+ב)zҥ4 L I !*S}i= :a&16OSW~ED۳9[@_}?}h=MpY5醯7A~g8+iNSao6aVi,hpZRpn^ ]ջf'e*ҎzlNs'=Ν†$KĹV{HWm8s 9? ,|x%s>Qկ[.~]a-\bߜ[=ӚM(fcg˴KJ][.W~M:1ζM8(}ר۩ fd\ژB@eұ#voS툵ch`*dkC-nW |y*}q8?߯OOg?u?HRhKҰfK79_QEee-36V4N'LfK Oe%!M>еV1/)Z4X+~=f;c<_mԫAsyZH4q=_D IUL/g5o[MW;4a„Df?ZuEf2~9g7]5Gr:UVEś~U%WjV$VҤOx ޾V{٣7..ErͶKilhRzr:9%OuCdy*zd[ٙj*HL~F%Orx7R/p+RT^B_{l'́ Ŕ}¢Y-rw/_U .e؞#@>47o`fs+5MMYkj!$1>l ٴ(Ed s%M6AaOO1 Q%>O>/ s;_w{M@BT%G=NS J- Pl6J%'a] H"Ld6#" !q 3(29eZni:˜ضQE'捺5U}N b_ DWXV9˜s (3K72n+J"]%%LU[[7bl,# TL u(_+cm.u'H~V"!KTp |H 5 23AB;yWlgoi#-*VTT* 7¬渔P06Apü5 b;8 7SPCIg_-[3M_ h|}ra[\m%بi,"#9MC|dNࣽ\;ٓ.dCߥ1 ,tКMgH _V{`F#9/+?k ^8E\vgEfÖ́jl =!x&ڏee=b78`cg]eVdd"h! DL![|u>_t9,/k#FWGDQd5붋KHDd+Z[6.'jAn/k5J&l3)lyKnoA;"}<_Q|Whc†0 -lt>-Pi%ҍ$GD$˵}b]&k*q{;>UAYD!FH c^>߷no?\q_^sq_(yM FU TCT# K̮8Je'МnߛJWʉI&ŁCScD B$ dLЭ$1"u*aW%Z!9*Zv4yVHI$S"De l:S.7"D bABF'[¥n53+D0xT>P8upJuډdhXK by$r̛  Z\150D^ hnd~K`uVMsZee{uk5h^^ I @4&ͼ8PR) n:ݓU->PgG S}(Y)OƔl1Ӣί̧rN7{=b߾i5β>đ@\t:pjُKMGmO#LoŏфycM Ne3ˆ^>`(B@4"E;tLP"p;kzk`H *qQ7xfsz"p-b`(& @P ePJ UB!H ? I+(Ҵ$%NzH&o;W9ß}Aq8H;jg6;*ܠ:Ҋ87SGd}>xCY{᜚Ϗmev| wlڎefP~.@$CAìCRDcl_՟O@1|R J c%/Ra)0,NE!IKs C$4AKn6P08 䡓DED=M=fR 'Pe9;RPlíy.BnnaE4:4fdBSH "Z`ʠ1՘c3 hs%҉$"G  x} up`v{WDg%h%{d޵"!+yhM4MT 5%uo*|VX#H{7[@ш HZB[CbE[Pn$4402=e:C{Gzy:3u wہ&soivk."!ԭqV_7s~&En.I,7ʽOdEٙmn$gHG7=}nog:,~?^[jp  !lP7L$ Q1T<eb`cZAF?!EU`CA!ߏ"=}d zcFQ濑EᔒYׯ^YD5Su¤@kJUZϚr{NxbuTy*"2XST-(c$lie 'DqYpSarVj9UQԶYgYoS0N ED7;{SNdfk#,K%eW{lm1T5h0=Cv0ˏm ԩC59w|'^t*B{/(2Ž( -ʰFͳ׾l7J dFo2D"'pfos{AAR)qd+"htvQ,FEO ̓ ( y"!GxMJq@ PY )"lH>DJob)SQ%:x[ syfZrTb ,H[] @E h?m|7 !4#IQ6FC5ipI_Kng88ͣhhh4@-Y YA>12ߕb|}Ba#KzӪ2;;DT%~QTGd1 [r®#cxD0h- kj#bTvT%a)Lh'.a1D?Z9T(' UPI: e(!`u7[rGa3}\F#UX|`&?߹[/pAP!+ L JEB3%([dL" t vL N@R̡7/sdxlu՚V@i~ )eNmwP\H9P*9Tk^LTEIFu=ű(1ܪY/wA06$$ft1&&!' _VmLOQ'{h0crqnɏߐd4m&"  9P e?Xe}.,Rw b]\X.$:AD$&P Kb@d%-P PKJR.$"B$"@ߓP5I: 0 E#-\ukrA_]+vA9C ~t*h&E ۜ϶ SIf-'vrC`$OP1F편a4d:I*5rP,UTzmr,C8}=&Y'suGXb.jxT@C5FLD $D՘S TDD2LI1 330A1D(6Щ*Uސ{2FXX KRNẜLN"|Ԫ;LT׌+(HV|#Op̦V$A\\e$DDC1Es0 i\t3>G{En7x iSX\K>8kqo1l=7 u:KT~W8wF{j޻~=zb7_տ2ߒoc.h<+Э%EVSc<zq026 14Z6K]~m ""Xl]&۶\) If -P1$GeēMhndao 77d4׆N>񷝤qT  clHr7wmwƐmYB#{hs ]_1  hPP!q*|Ǒ QT+vw'qA'Dz?JUs2HVW,^eNQP*}%&/m )?8uZō2${KK)T0g(,q㇕NrYKZ#W-ܺ>7qWs;ՙ}+\C:9 ̾Wm tI$B,?]>Ir_=ۜ'C)(UVƑף&$A:Fb]O(5{9+6'}=dRRzmߔz+r閛p#DrAxfT2C Iy-BdM:>{Q΂.k*R"🛃^3wte SemM0}% ~m]vԉvҟ%6iv}4xx[B!*M*ou,ob!%ކ@;WVh÷ZPƸ4{5+Z$;]^N Y ' 9 mb:f̴V !ʔPQG5[JO,x7s,2:I.l,J-.)ZϠӨ#Vx ]ڀ'e="8Kmr AЋj>fW '!~Xjk5e\!$9!w_"4yi{frm)$;5 .V("d=}ҞםI-$\,B|uVӼ_!9鸹젚{SV$9 R>Tϭ g`dğkBJd\g!bx%n>g/Ѿr?n[w`pݗŵ:[% [,B˵e.RUG;Bj^_&So-!N:T~B^L9 wO^ UsQ25[=F,sCptU-ߊbd<?P߀%k@2CP C|PhzLTx1H(gCL&93qe" BCѧ-|8Q4PZ@'@&VM]+T %wlrM9Xޡ{{U*pX)(0/G2= =1fY9]Nwy=! {G?N79H8I_3v;wRd<",lO!/K݃o32,4xr88rÅKR+F\,[mw/^߅{~7_yFj_OȗN1 (L҄\ND*"`?LS+ҥn ׯ<σhkwU4T? p^TOC)K$ap|EIXa 3:>cDxSERo֖$PPȲo !mܮjF5(IeP\mcHTq%Gt9Y'>;3~źXMq$ڥNۍHx贜^g7#;~'+=zMwc\Jű' TIE% %iU0)IlDfip%$1#0̃rFrJH0'0pa' &d#dAZ`2G8!rY<`)-Odko_0(` YCL-B8m#^HV 2X$I4JQhҟSR:h98BSv퀄PAcbyqCXX^Q|\3M2+DI C tsxpbIŹ/@4X EU^ťs(=51R} a.~.l";ː }ir*e3'Qxsv )@0zf6Gj|jH;Y*!j ;15ՂlCrЦSl9H\M߾ 0B -̽@%njk̽w#^paO38 @/' k7X!_ rsdCOd[X4n'=V+[2!~m3/X9NGw5V.prj}ޱEL< 2KjJ+dc%+U~>|kMm}t''@A%@oޟᕕp9TknjIh>O c_gFJwA+f@*%S4P|UYeL)G[Aˏ>l9'^19NeZ`mq1m ~Y{x\LE8"!x+,kqXl5/7^8eKdUq%u!k$:f랓Ca_cH>ȥt-eZ"$r?pveI.ix: &VR"Mh[>7m{kH93IPchI!jus@⟥@!N!1K^~!ޡ*_բk{yڑ0 @"avZ.Be?Fƪho,P4]H["T@^zכ߉5+H' Őh69N{ۿ_T-X;D3aE_ wqW䜌Gi9juԂ%uJ[%}Gl:H2Uaw|~Wj1.8b~y͢ n{>s`?Dӡz'tZNwڽG=ГaJYJYmm؉v+r۶e۴R唟׹+_ә'tֻm2d!\ڃSF`'=xE?!_!Sg^_ѱ:2 L;%#Nػv 5nkE߿ۈC'XWxK hF4w,RdƟB~I^F_7H'T426WhۗB X9S@JRt}F#BGPxrg[RC!HdI sY5%W7ϗVj>8/UQ|SXi7-f\3ua Lto&sjR_ݵ,dPs?ڜzA lQo)Q#zJȏu=U#Ld|Qjт /(j~@IgDD^ȭ̄"z/[_lhr.V>V0̽GD/邎},NB}H@n V !(;Y>^iϩ@y{2G7nwxFa>-`ȅf7Y#ch [[x_xk3&vYŖK\DS65(8{M_ ; 2?ON(ntotK""D Բ""kX&}K)'ɺה/&3 ?Wq _5TH/3, ԑX)+Rx' h??L?(moŇ;L3?r c߇]\+fs'ZQc l%ecӧ'[?=lu9oys,$rj;ܭ=\L#oi\30ocR׭?i Tޢ;D6}wX9P<{ ;vFEf^4:*qW|Iq5MY']E m6Y3:HV>k/w,ZL*7=UWSO'{+t8љw<Z'X3 JNpQ\# ;/ꡱVZر|RTEZO> I`Y&  Tv/` pxF %art O ?Eȧn3D#xnyzW7I9M-O@@ Yy:Jcx%ȝp\3:8=ZVZ@ >C ^Np s'-^!  d:0Bܦ͠tdO5LFCÀ C[-NpJ$O{Nsw^s_3tN\$qKqA-3F7(?ֽC*ps ^$!H5(.luX ~CTN)3o؄cA#+e _@Y~ԁKE/^p(].L/_wAA$Ld 0" &,m?DܹB|yLɓVbS<< sz^Bhs>F0GKr+7=Q .񆓵 N u9(vwoGwƒG.IZaSGwWl @qlt,"XUu+X}SH2+~&Lh.ТzR8}ԇxu2l,x>+l#*BzWb(j~ƎiiX1AfoC~y+kAϚ{_3uLyålm0O^<DnU;剐ҍ<Q.S ў /Dꉪ s30OI[N G \l=",pQ0<0lW~L22k{o~~/a HgOo-ϐ ATs'QӤSn_àq5PTH$SDqOw\d`Ya>t=zP(б Ŵ A5 P2AT %Kp痖%xBy/4U8@ *F| %H)$eBX3˵(݃a>lK.)@@ID)@QX;cs!!QШ S@J)H2F-4&!,݂6j?RHg 2PSUKgy:äc"e+nb6Jz!i$m3#z4-ou(JHȷvҒ֔f|3Wܛ4ċ`r]n3T(zDDLРāy߶\ka8 F` R~ၒ6Ⱥϻ 1ïA4A,< tStDE8_s|{ e0E.~ñ'U 4B'" K9ף6D7s,YFEU,e@PS\%R.%LxF||ҾaԠ&L (ےz/+<,2pOXW{CIT oMyPsg[C.%r,xXÝ]ly8z˦Тfׂ$-?TRN߸jb4èE21/y9m:'M&(;qJl>nuεN;m*z렧PY,8륰 58Kgzy5Kj*J( Cz6P93>'?MK섅".*&\%d~%LY6ml#-^ (sε_5k;>t;նTk-CX(\^1s1+ .@ JD;#mbASF"F ł*獷(2>B2]z;N`tώ{FOnCwԣξ ni[{ ;#y-u:/n.0td0~%M C|5`N5$:v]16X&a9!|n,(z:5cRvr9i>ٯ^+zOhwhcٛz~&-CĢ23gBjf2G)7ٴ*`\bKb"cfA:2dj!Ïw?gVk}ݽd/JjboTD(MnTIUcDn꜔;欢 1 ڰ E@`;;T Mm(a-'1ۆw[BJ$Cyǫю;fHhP|- ի<8NZx'hG(]8>C{ qLƜ[Ij]dUf£&$u8 {z2eaܱ{nԈ 9SVu0 cb}pqgjU,޿.~mj#{\aaT)@S%6P_mĚ}~ "HP?=-P}ЎFBt}ov&& ȏi@KP/R#Ԃ/nsũkQyn>uQ CKH?ףk/uuKM$\&&0<:y{8jUrj7N/S3{t\{6ׂ螾gcyvlx%l21}N*߫–զP<@8[o-Jfn> %ug8Aa%6qyFojmh9&|)s[)3o_$_ r݆ £(訕l^(d*1GجLK^ם8oD ?{gdgQ -sΩg[)@=:$Is%Z4?[M?7~#ɟ[b\}9ڌpvܷԣ;g$I_e3UXtELQP ᳝KU-qu^aC%OmZgf.rZ]SExz(!k `<e gdTIm D:GDX~p anbWQDx2jtx ڳSc2.JǼ5{͢VhVjPtڰ`͛Azg&|5urcr0ވ_,=htЧ\ݝS,,~Ȣ"?C7%fYL^ .m/wP%hl:tT"'-+02%ؐ5=bgJ]dIϷ̞ci\=cd6f9~-a/5 ofx`Zb@" i38Rd[ЮjCmSx?FVͳz|4vH^AˏJ[^lT V~8?tCG AӦe~HG߶{J# -iǴCocs1LvɘPI's740h(8uTzGh29E<ԛE(V˜K hxR/z5Træ\gmJ ;Y"fƴR )8bWK.FVkGmCTHF ۛl&"Hnhɚl+ϲ;=nvy6*d?EK"Z_GqJ>u2\Ed ]|ҏf49%_h }pd>~v;Q?SgW5itOQ{5|nlb݋5]񂳵8;*sՔY}Qx'}\^x6+߻ES԰T2@ٙY,|L7Uŷ. T,J‹׷~g|,oS~<|xihZg@\ 40B/3zy2'{Y=bI,ݘVggfʮhu x,:}ܸ.5j~7@(PapqAH}?s8eBέ[ǍЂ(|TvaJEd(T6tãÚ >.rX16  e^:?@G4-_"\?&,~/@C(HQ,GYEI3:^# .K6狖;ШQ#mROW_ (d]O߈JI +~mK)2M6-6V}:rrdX\a8ZAxav̽5S:YUUVYu$+^W_!asG BI+~N&P "#}40kkNeD6bXƘ.' D Y6Ik$CvhidA,"h!m ߷gl(lEAŽ "n[j[g/rlYn´:h:pIt4G{wg/>LWPhPX=._4WoW? =]Y/.Vo7Cd e;~IE@|ݹN]sѱ}x/;>P'f6|m5L\k;fѲ}Wv}'iX[7@ıF!I D666Jܧ7)q$ދ=_KFB0I0+`-Ps- B-t¥$hj&`B!b?o/a*rtW  (@Ql(©X{Qߴx^V}4܂> J=[OZu: >1P?Vu^Mg1Pj/:FYKWEg,G7}.6U)Gi<gb{fm݇m4>@M@ C]_:dZ@V >)`kX9[md̔S4AD!̢JHKI@D%!  C09R24,B3?̒J1)X_na1_pBI`v3, [C=NęiHwbLHQ.p0Fń C"99P'P㸧KD\"iɢ0h+_2{cWi)z * j* d)%HxIS;I-TĄ2%ECDBEXbfI@)'Sx`U@4CEW`9@8 DIExBrTIErDz HP1\pZ*,3 ƅ'%z@ T`^x3! '8P;D+ڠqNv`\ H|y$0CP:b,TЧ S(2C3!{wӯYT _9"$&v O(@@?nx:mD!"jy"R 0]B$D҆ 1"Y#BQ$ASKnޞtNx`ù/$F˿q D 4!8f*oW%0'~̣FwWh8F{%q($/j$lh;a*$?hkT%$:I@E^0Z-a8^e`4L{nOp?ϛ7J~W>I&fk` |'0ÙӼ"p^5S{JP"fl͕@O@&s9nlo/>ʩ|~CzN'b{Obاɟty[==& 8l~K/IgUd3T76؆(>9$" wCMxH{Aq0 ~i `,ɉb=Y_4d`]_y8se9,KxsCgǃV>̿U~w*ROB)O?jߨPGP.-?ə4Kl8=P/^]S?8b7郧]=+)g5KH` jTg]jz(uL_b/L6?vÐSdħ0a֪hMgAi[Y`D7l+#S"$ rµ)JJxT5u3uYi=L2&ʐ(֖^os^ၜGOR ɭQL\K RIJ8zpkyƟ_6iǭ@gўEY r3CQ\3u Oѐ$tJô } 8;Pqu@. 4g5SQq]``<ܖVؿv8 Z7Sb(\yևMBT'g??|J0?o= d6/\>_|'k:evxzPi iaXYEuݜ#C`5;! D@!|AAE`E)&ix̊@DZt|D!%.cN wcADCkmPDC܅"vk!Ua_/48Y3F#c7ܪ+8 qR ʒ0SGYSt$mGh@;9.ۢFKv 8 V+5)˖ɒyP хCh w7aGQRL3KSkGǯs'Ѽ1FVze4`X\BUپCu] =1̜vb<$(W#K }L$\kC0=Mx4N lEIt&@@Y%;"G[Lg%AJpW{NF4P'<,\*ǴY@x&2$#Y }E㯞)IUJR{O49TAFj6ʅ#T5dFT{={(r8>T 8N 5 &xE{{ʱ"^8L L78&&1EjAmg0F@.CK}۠Yw) p2# *`ʪ(7CN=Tv# "#TPMREUKU'7K59`;^_!7>p<]w=/]qRСTBz˭h4!K+lQ5D^=QcxkȺdd"H ۞%r|YI5tЃQIMnOB h5[h$W,~ 8ެtC'1&EUAUDB L(D?<ߖ)BCzAaXFXq$D &Y^5x㧤_ٿm'cث?\Uď& 4/CF!M]$qcl9Dɉyy?\Md"7@O4ScaK4n+*LYW D*ҴcsE3|T+:嚟Ql;ǝ}04 BvxQ ƁP! 0tV[&ɞ8z@Co=* ¥ d!M:ǞzsRVݕN쨨fT]we[WvnbɈ"*S5NQUE3Nf ǧz Yr sGA<Z)(DP[Pk;$ƗӉm3m4ꘈ0HI&韒LzU:?`VFね]yػ^HR^ )NE`րш|," tZ0pm0J܁W vfe8jh bB h0uCp{'m6==`ъ l $mgSM= i|r71)0rr/<30ȳ 307M-5133 2(-! 3Mb2-703pȷ 7 pȢ8{%FDy:_,cD.̘e߽8.# хKstA! e ͜$P'  /:D(N~հ|νq?~Ol.s!$I(n(dnAB/,HG)7$votQSCsꔺHJeнM1(@b^-oa3Rki/-TY~&"OfG4*(4>Q[tC@E#\>9B08@7*.|iD(ߵ+~|Ďǜ $ƙxgvKA0lD<EQTާR(WK*=/SHuA+u >kFw3p;ẃjτe /g쨖{ֳM E:0:k8-DLAk=_vv<,OwBL=5!{  ()rIm*U zr#\?|f=-_TNLb`C[2l3e3K˖O[bzL g;s H (ka 'vJ܇ӒT3Ԓ9`̤~w0#~t$oSQ+#kD.gL 6ocYwTUP/@ܫxFdFu nH  hBL*O?.?ͧHx4 =apZ$6{\y6'b<~ROmxZ.QP˾yk/!hS3c^B_і8HhmZD)@RC `hރK'sԶ XLj4y} |n`r-%U)F}UB%J$C/ =g:@͚0xόV=R|hrrJg*7d ݪ 5btҷwt<snj)*d'x> Ubx[e4+|#jp]x޹ P~ܚw#m~ʷ1Qc)"oynjP?OWW%,H"4w+&rQtw6Bӆ4 h>)n@$9!^s{&ln AO%!ŭǝ$@m葪`*T<(~.%3G;]QQtcHdd̊7s uehxƇ N3b]Ђͦ4ےcđE.~/ɒDWDG}-hT(#D'_OѰm$D) k h /} YkC\G$"vil \T SkOos>NXE^ƀֲ= 'Aai f]TnckH!CD+VY{:JȈ@tF4P"Nbxb03aA`̭< \!10Oe]RPQ@:r!$]>~Ƥd$IJZ:Xl㩛(>@KD2HYbѻ?dui04(̤[s(`>tRK{ bxP y=9E%=+'&٬ڪe\GJTG,*UGk  DL6.%cکMp[8F@Ճpu[83ӥ󿁖<Ocvk WO?[q@g|ϱ*©="OBu % >)T熆emQ MB_-{cGCtCk4m] B gGp]?1Z*SA0A$ȰI CkwKL Cd8'mu ɦJTS%I*WpqP+ Fű}z`+$Q{wX߁FD$;pw DNB8$Ix6 Xd2, h}pQ ƸUtpdԔKW>̺]pXD{d䇳_l[qz}\ \aeqIYcHu#ǑLdI.fss?% HP Jtf Q3%!C7DM{Vt8Dhy ޴Jnٕkn˄?܆{x݇]0pHOSs~2sZ*w;L"kz3m\T7R\&xE-0jH[X`juaډJuoJY Bet~wÄ^:|d$C(݁8v׉` xssyIi4;/LPO'?[qE!^p09fUYp (۠xth|ha52wa$Wg>h0ޣHH&G#bi(Vl"@*^%1BAY};- gϯ MV{lL(F(veAG#戣- \+.`܀H`z:}aV崵-K}-.Fsװ&h^hKWRiٶjIxJB""p!=|mcQ@Q?H݅=?;MGu;{Pn39|yĎ\ݓBptH+y00S}n$E?h4 6#*}t9m1 Awf|c#2=z1dfPPoZwQ_gIӖZQ 'ez[l|Wmr^p/鿮k}΃gT<v}i0SK__qXbT>m; VOko4)x; zSO.VQobR."8!_J R(BO2+x{ v<.T$qCo&+\yP<&Yy:^ z'bAs?-C[f_}~1fM4Q@w'UdZ,e#f4!'=?_[mȤ'rW@22@+EU/PQh::}J<"mDQ>Q;IOwY0 U~;gվ]?֍% YcdA@DD׈쪮UOK h~z:Ţ0"߿! U@g`87Kxz6R?{ 598iJP5h Ky/ee)I IBy!> kM*(J*Г<饽!pUT8H @B =\6ҪګӪaUۄKȞD(^AXE>T3y*MA;xƐ EH~W j,H;-Ŕ'BNPN %L/zRT̿w*(1o !$.UL2Oe$2D'L+ 2Q] @XB- +Q S-1p> B!T)76$Kw-~pL7M<[^MKwEHu2qGQOACq{}(ȃI $z@h![M1qG,c7=#\ۙ`hLi lؿBsWW` Er:\\8sVD:WkUv&Wt]z건ٜ|3&u>%&4Rp*o d r0U}=[g6w٩p (g7XO>"QG"YAP?>ݸQqCoiilzfںѩ4>lCl l~G9;VuPi==x@!tF17A|szzퟍFwCyq?1 YShޮsT~@@p$iIqlF!}$g4XFZxfi5{#0ESO֝g ]97O؛#R ЬO/hΗ3޷XBXLEeZK #TtfkxJj;?y:/bz~sE.ݫ[8҄Aw,:U^' !EN;,HZJ?@hâQ m:X~!>Zl-l.B$mJ dd`g-02"s7@<4D% SanGKb?pA} %'֩ t o^z?o||'T6 ;0'5|0s}ݳR e]lhC(2c ri PϩH+w6q: If JFI'iԻǺO@CQ U*wuyr ^1Gr TR򪽁zBt1P9`w8#>.nHqV f=DL!Ê|`M"oثa7L0)"L$(brrLb(MƩ =XŦhd~-6Fa d TvY /k|CۃXB4??gg9IIXweץf1(1:s?U:Ɣ3z%(_v;ӏ3[$m Bq,{2%-7O宲qˏ*\ȓtZTi zL=Sa#OF]!\qK2 /] rnN$$3iK :>Ở;NaȁM,O Ly60Hf^#8"ԀA09eJ'BA񎳡ыz jh  &{8..[;ubs* ;vW9YC0HvX j+17߂4HQw@{2`%`S+#"sE2*K/ܛ&pOvB'^1y!&T - E`7:˷0W^5 qʄQ\' w~I [<5j 5Eaᰒ@&$$BI $I$$"l(Xo?9|Acp l LgƊ{1b'cF`Ϩ4RBkrJ~M5&+RR} G fR( _O1#9>EC4 /((HPY 鲽<|t|Y[q((x]e`GJQ~2[C|`e:i# .']:nw5%Ly|aDgv>C5= "ikb >CyjݔIgr:-MYRE53ɝ!2\0~-m-v&)0Dn6G v0$$CჄ slIksⶢL&? Q;0e1 z7RXv_qƲfcrLKȢEE'20\c,#LXsmD S mO#sNHLi:.نRDžeI eFF.b_[-\z3hL*imt-.3n28jQY:>pZN=쌽KfǺN4Jĥ0ɲn(%EǞWP;A>V,@ђ\ p%8 1({=+Ȫ`WqRt:C=_'<^֛asR1 uއ'U0CM7m(ҹ 9B~"&@.l==_~n`H"QHi,=rV QNf>ꁅh&qJܫpK"B/ma B[Ar &()"YtSDAp MCwU/s3Uc:=kop6RPʮ2#$$$"hEfDںtqLPhh߼R pF'̓_DG0Fp z8zZ<n 䫃}0:bIp@f NY9@jMDs.@%I?\ u4FL(H-6"!,wrINJ VH0nYݎL<4$U/xCR?,/gXF2L(9 0*F){זWG1BFrR8` (=!b0W_mR;=H_KT{khNle"oКi^߀4;Ut3mO:=fn۹[!y*sNx:؂~s* m!(8(1Ԩ.:nmL rRC-TLs,I  ` _  A91tɡ}e~{S) l)"8.PXY!X;9M *@}?5ص=ì{AÍ#џo qo9ک1 .'dl?`?hE}0vŠe )5H BiX|' 0f/s\q*BI _~#$_s6"=8Ia'Y4^ğJ`KjI%0RH^wݿ;;鯭ijZڶ<ݷEw]uqHHĄaz|}`1r%-r8O'E# ]t CggCioQĥ56ߺ@~=$Dd lCp:=E%eE5f`Y 8$HLGpi/w􂸶)S 02%pNPg_9DwW3tx2CHbv(z aub}/.89b|;~{l˞=A.cijAxSV)>*ew1O=!-ڽgϵ]N#8u E7'=޷ ? Q@! fe$a8MNbOΈ,!s* n%.$H$-ߺۑ__?m8.p#6M IY~?tQ:;Tn\^EۀT!W'x:qCB#T~MDCM!7ztS<ٛOKjs۔=)tMTL^Gnvش?RH4 >/(C;K= J9ay'{KR댄5P}dam$ds203W j}ڹ~9PU}j40RxWB"p*Ѐt|O<+۽ވ?8jj?v/p "^刧F!|/]䝥QV XO܂|99T$R0_q"7`#y``*EkQ*AXFOYq2zȝ>dcHKK{Hm٠x~n)O8z%_AI // Search for the player std::string playername = testplayer.getName(); Player *player = getPlayer(playername.c_str()); if(player == NULL) { dstream<<"Didn't find matching player, ignoring file "<<path<<std::endl; continue; } //dstream<<"Found matching player, overwriting."<<std::endl; // OK, found. Save player there. { // Open file and serialize std::ofstream os(path.c_str(), std::ios_base::binary); if(os.good() == false) { dstream<<"Failed to overwrite "<<path<<std::endl; continue; } player->serialize(os); saved_players.insert(player, true); } } for(core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; if(saved_players.find(player) != NULL) { /*dstream<<"Player "<<player->getName() <<" was already saved."<<std::endl;*/ continue; } std::string playername = player->getName(); // Don't save unnamed player if(playername == "") { //dstream<<"Not saving unnamed player."<<std::endl; continue; } /* Find a sane filename */ if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS) == false) playername = "player"; std::string path = players_path + "/" + playername; bool found = false; for(u32 i=0; i<1000; i++) { if(fs::PathExists(path) == false) { found = true; break; } path = players_path + "/" + playername + itos(i); } if(found == false) { dstream<<"WARNING: Didn't find free file for player"<<std::endl; continue; } { /*dstream<<"Saving player "<<player->getName()<<" to " <<path<<std::endl;*/ // Open file and serialize std::ofstream os(path.c_str(), std::ios_base::binary); if(os.good() == false) { dstream<<"WARNING: Failed to overwrite "<<path<<std::endl; continue; } player->serialize(os); saved_players.insert(player, true); } } //dstream<<"Saved "<<saved_players.size()<<" players."<<std::endl; } void ServerEnvironment::deSerializePlayers(const std::string &savedir) { std::string players_path = savedir + "/players"; core::map<Player*, bool> saved_players; std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path); for(u32 i=0; i<player_files.size(); i++) { if(player_files[i].dir) continue; // Full path to this file std::string path = players_path + "/" + player_files[i].name; dstream<<"Checking player file "<<path<<std::endl; // Load player to see what is its name ServerRemotePlayer testplayer; { // Open file and deserialize std::ifstream is(path.c_str(), std::ios_base::binary); if(is.good() == false) { dstream<<"Failed to read "<<path<<std::endl; continue; } testplayer.deSerialize(is); } if(!string_allowed(testplayer.getName(), PLAYERNAME_ALLOWED_CHARS)) { dstream<<"Not loading player with invalid name: " <<testplayer.getName()<<std::endl; } dstream<<"Loaded test player with name "<<testplayer.getName() <<std::endl; // Search for the player std::string playername = testplayer.getName(); Player *player = getPlayer(playername.c_str()); bool newplayer = false; if(player == NULL) { dstream<<"Is a new player"<<std::endl; player = new ServerRemotePlayer(); newplayer = true; } // Load player { dstream<<"Reading player "<<testplayer.getName()<<" from " <<path<<std::endl; // Open file and deserialize std::ifstream is(path.c_str(), std::ios_base::binary); if(is.good() == false) { dstream<<"Failed to read "<<path<<std::endl; continue; } player->deSerialize(is); } if(newplayer) addPlayer(player); } } void ServerEnvironment::saveMeta(const std::string &savedir) { std::string path = savedir + "/env_meta.txt"; // Open file and serialize std::ofstream os(path.c_str(), std::ios_base::binary); if(os.good() == false) { dstream<<"WARNING: ServerEnvironment::saveMeta(): Failed to open " <<path<<std::endl; throw SerializationError("Couldn't save env meta"); } Settings args; args.setU64("game_time", m_game_time); args.setU64("time_of_day", getTimeOfDay()); args.writeLines(os); os<<"EnvArgsEnd\n"; } void ServerEnvironment::loadMeta(const std::string &savedir) { std::string path = savedir + "/env_meta.txt"; // Open file and deserialize std::ifstream is(path.c_str(), std::ios_base::binary); if(is.good() == false) { dstream<<"WARNING: ServerEnvironment::loadMeta(): Failed to open " <<path<<std::endl; throw SerializationError("Couldn't load env meta"); } Settings args; for(;;) { if(is.eof()) throw SerializationError ("ServerEnvironment::loadMeta(): EnvArgsEnd not found"); std::string line; std::getline(is, line); std::string trimmedline = trim(line); if(trimmedline == "EnvArgsEnd") break; args.parseConfigLine(line); } try{ m_game_time = args.getU64("game_time"); }catch(SettingNotFoundException &e){ // Getting this is crucial, otherwise timestamps are useless throw SerializationError("Couldn't load env meta game_time"); } try{ m_time_of_day = args.getU64("time_of_day"); }catch(SettingNotFoundException &e){ // This is not as important m_time_of_day = 9000; } } #if 0 // This is probably very useless void spawnRandomObjects(MapBlock *block) { for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++) for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++) { bool last_node_walkable = false; for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++) { v3s16 p(x0,y0,z0); MapNode n = block->getNodeNoEx(p); if(n.d == CONTENT_IGNORE) continue; if(content_features(n.d).liquid_type != LIQUID_NONE) continue; if(content_features(n.d).walkable) { last_node_walkable = true; continue; } if(last_node_walkable) { // If block contains light information if(content_features(n.d).param_type == CPT_LIGHT) { if(n.getLight(LIGHTBANK_DAY) <= 5) { if(myrand() % 1000 == 0) { v3f pos_f = intToFloat(p+block->getPosRelative(), BS); pos_f.Y -= BS*0.4; ServerActiveObject *obj = new Oerkki1SAO(NULL,0,pos_f); std::string data = obj->getStaticData(); StaticObject s_obj(obj->getType(), obj->getBasePosition(), data); // Add one block->m_static_objects.insert(0, s_obj); delete obj; block->setChangedFlag(); } } } } last_node_walkable = false; } } } #endif void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) { // Get time difference u32 dtime_s = 0; u32 stamp = block->getTimestamp(); if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED) dtime_s = m_game_time - block->getTimestamp(); dtime_s += additional_dtime; // Set current time as timestamp (and let it set ChangedFlag) block->setTimestamp(m_game_time); //dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl; // Activate stored objects activateObjects(block); // Run node metadata bool changed = block->m_node_metadata.step((float)dtime_s); if(changed) { MapEditEvent event; event.type = MEET_BLOCK_NODE_METADATA_CHANGED; event.p = block->getPos(); m_map->dispatchEvent(&event); block->setChangedFlag(); } // TODO: Do something // TODO: Implement usage of ActiveBlockModifier // Here's a quick demonstration v3s16 p0; for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++) for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++) for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++) { v3s16 p = p0 + block->getPosRelative(); MapNode n = block->getNodeNoEx(p0); #if 1 // Test something: // Convert all mud under proper day lighting to grass if(n.d == CONTENT_MUD) { if(dtime_s > 300) { MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); if(content_features(n_top.d).air_equivalent && n_top.getLight(LIGHTBANK_DAY) >= 13) { n.d = CONTENT_GRASS; m_map->addNodeWithEvent(p, n); } } } #endif } } void ServerEnvironment::step(float dtime) { DSTACK(__FUNCTION_NAME); //TimeTaker timer("ServerEnv step"); // Get some settings bool footprints = g_settings.getBool("footprints"); /* Increment game time */ { m_game_time_fraction_counter += dtime; u32 inc_i = (u32)m_game_time_fraction_counter; m_game_time += inc_i; m_game_time_fraction_counter -= (float)inc_i; } /* Handle players */ for(core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; // Ignore disconnected players if(player->peer_id == 0) continue; v3f playerpos = player->getPosition(); // Move player->move(dtime, *m_map, 100*BS); /* Add footsteps to grass */ if(footprints) { // Get node that is at BS/4 under player v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); try{ MapNode n = m_map->getNode(bottompos); if(n.d == CONTENT_GRASS) { n.d = CONTENT_GRASS_FOOTSTEPS; m_map->setNode(bottompos, n); } } catch(InvalidPositionException &e) { } } } /* Manage active block list */ if(m_active_blocks_management_interval.step(dtime, 2.0)) { /* Get player block positions */ core::list<v3s16> players_blockpos; for(core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; // Ignore disconnected players if(player->peer_id == 0) continue; v3s16 blockpos = getNodeBlockPos( floatToInt(player->getPosition(), BS)); players_blockpos.push_back(blockpos); } /* Update list of active blocks, collecting changes */ const s16 active_block_range = 5; core::map<v3s16, bool> blocks_removed; core::map<v3s16, bool> blocks_added; m_active_blocks.update(players_blockpos, active_block_range, blocks_removed, blocks_added); /* Handle removed blocks */ // Convert active objects that are no more in active blocks to static deactivateFarObjects(false); for(core::map<v3s16, bool>::Iterator i = blocks_removed.getIterator(); i.atEnd()==false; i++) { v3s16 p = i.getNode()->getKey(); /*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z <<") became inactive"<<std::endl;*/ MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block==NULL) continue; // Set current time as timestamp (and let it set ChangedFlag) block->setTimestamp(m_game_time); } /* Handle added blocks */ for(core::map<v3s16, bool>::Iterator i = blocks_added.getIterator(); i.atEnd()==false; i++) { v3s16 p = i.getNode()->getKey(); /*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z <<") became active"<<std::endl;*/ MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block==NULL) continue; activateBlock(block); } } /* Mess around in active blocks */ if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0)) { float dtime = 1.0; for(core::map<v3s16, bool>::Iterator i = m_active_blocks.m_list.getIterator(); i.atEnd()==false; i++) { v3s16 p = i.getNode()->getKey(); /*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z <<") being handled"<<std::endl;*/ MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block==NULL) continue; // Reset block usage timer block->resetUsageTimer(); // Set current time as timestamp block->setTimestampNoChangedFlag(m_game_time); // Run node metadata bool changed = block->m_node_metadata.step(dtime); if(changed) { MapEditEvent event; event.type = MEET_BLOCK_NODE_METADATA_CHANGED; event.p = p; m_map->dispatchEvent(&event); block->setChangedFlag(); } } } if(m_active_blocks_test_interval.step(dtime, 10.0)) { //float dtime = 10.0; for(core::map<v3s16, bool>::Iterator i = m_active_blocks.m_list.getIterator(); i.atEnd()==false; i++) { v3s16 p = i.getNode()->getKey(); /*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z <<") being handled"<<std::endl;*/ MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block==NULL) continue; // Set current time as timestamp block->setTimestampNoChangedFlag(m_game_time); /* Do stuff! Note that map modifications should be done using the event- making map methods so that the server gets information about them. Reading can be done quickly directly from the block. Everything should bind to inside this single content searching loop to keep things fast. */ // TODO: Implement usage of ActiveBlockModifier v3s16 p0; for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++) for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++) for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++) { v3s16 p = p0 + block->getPosRelative(); MapNode n = block->getNodeNoEx(p0); /* Test something: Convert mud under proper lighting to grass */ if(n.d == CONTENT_MUD) { if(myrand()%20 == 0) { MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); if(content_features(n_top.d).air_equivalent && n_top.getLightBlend(getDayNightRatio()) >= 13) { n.d = CONTENT_GRASS; m_map->addNodeWithEvent(p, n); } } } /* Convert grass into mud if under something else than air */ else if(n.d == CONTENT_GRASS) { //if(myrand()%20 == 0) { MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); if(n_top.d != CONTENT_AIR && n_top.d != CONTENT_IGNORE) { n.d = CONTENT_MUD; m_map->addNodeWithEvent(p, n); } } } } } } /* Step active objects */ { //TimeTaker timer("Step active objects"); // This helps the objects to send data at the same time bool send_recommended = false; m_send_recommended_timer += dtime; if(m_send_recommended_timer > 0.15) { m_send_recommended_timer = 0; send_recommended = true; } for(core::map<u16, ServerActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { ServerActiveObject* obj = i.getNode()->getValue(); // Don't step if is to be removed or stored statically if(obj->m_removed || obj->m_pending_deactivation) continue; // Step object obj->step(dtime, send_recommended); // Read messages from object while(obj->m_messages_out.size() > 0) { m_active_object_messages.push_back( obj->m_messages_out.pop_front()); } } } /* Manage active objects */ if(m_object_management_interval.step(dtime, 0.5)) { /* Remove objects that satisfy (m_removed && m_known_by_count==0) */ removeRemovedObjects(); } if(g_settings.getBool("enable_experimental")) { /* TEST CODE */ #if 1 m_random_spawn_timer -= dtime; if(m_random_spawn_timer < 0) { //m_random_spawn_timer += myrand_range(2.0, 20.0); //m_random_spawn_timer += 2.0; m_random_spawn_timer += 200.0; /* Find some position */ /*v2s16 p2d(myrand_range(-5,5), myrand_range(-5,5)); s16 y = 1 + getServerMap().findGroundLevel(p2d); v3f pos(p2d.X*BS,y*BS,p2d.Y*BS);*/ Player *player = getRandomConnectedPlayer(); v3f pos(0,0,0); if(player) pos = player->getPosition(); pos += v3f( myrand_range(-3,3)*BS, 0, myrand_range(-3,3)*BS ); /* Create a ServerActiveObject */ //TestSAO *obj = new TestSAO(this, 0, pos); //ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1"); //ServerActiveObject *obj = new RatSAO(this, 0, pos); ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos); addActiveObject(obj); } #endif } // enable_experimental } ServerActiveObject* ServerEnvironment::getActiveObject(u16 id) { core::map<u16, ServerActiveObject*>::Node *n; n = m_active_objects.find(id); if(n == NULL) return NULL; return n->getValue(); } bool isFreeServerActiveObjectId(u16 id, core::map<u16, ServerActiveObject*> &objects) { if(id == 0) return false; for(core::map<u16, ServerActiveObject*>::Iterator i = objects.getIterator(); i.atEnd()==false; i++) { if(i.getNode()->getKey() == id) return false; } return true; } u16 getFreeServerActiveObjectId( core::map<u16, ServerActiveObject*> &objects) { u16 new_id = 1; for(;;) { if(isFreeServerActiveObjectId(new_id, objects)) return new_id; if(new_id == 65535) return 0; new_id++; } } u16 ServerEnvironment::addActiveObject(ServerActiveObject *object) { assert(object); u16 id = addActiveObjectRaw(object, true); return id; } /* Finds out what new objects have been added to inside a radius around a position */ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius, core::map<u16, bool> &current_objects, core::map<u16, bool> &added_objects) { v3f pos_f = intToFloat(pos, BS); f32 radius_f = radius * BS; /* Go through the object list, - discard m_removed objects, - discard objects that are too far away, - discard objects that are found in current_objects. - add remaining objects to added_objects */ for(core::map<u16, ServerActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { u16 id = i.getNode()->getKey(); // Get object ServerActiveObject *object = i.getNode()->getValue(); if(object == NULL) continue; // Discard if removed if(object->m_removed) continue; // Discard if too far f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f); if(distance_f > radius_f) continue; // Discard if already on current_objects core::map<u16, bool>::Node *n; n = current_objects.find(id); if(n != NULL) continue; // Add to added_objects added_objects.insert(id, false); } } /* Finds out what objects have been removed from inside a radius around a position */ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius, core::map<u16, bool> &current_objects, core::map<u16, bool> &removed_objects) { v3f pos_f = intToFloat(pos, BS); f32 radius_f = radius * BS; /* Go through current_objects; object is removed if: - object is not found in m_active_objects (this is actually an error condition; objects should be set m_removed=true and removed only after all clients have been informed about removal), or - object has m_removed=true, or - object is too far away */ for(core::map<u16, bool>::Iterator i = current_objects.getIterator(); i.atEnd()==false; i++) { u16 id = i.getNode()->getKey(); ServerActiveObject *object = getActiveObject(id); if(object == NULL) { dstream<<"WARNING: ServerEnvironment::getRemovedActiveObjects():" <<" object in current_objects is NULL"<<std::endl; } else if(object->m_removed == false) { f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f); /*dstream<<"removed == false" <<"distance_f = "<<distance_f <<", radius_f = "<<radius_f<<std::endl;*/ if(distance_f < radius_f) { // Not removed continue; } } removed_objects.insert(id, false); } } ActiveObjectMessage ServerEnvironment::getActiveObjectMessage() { if(m_active_object_messages.size() == 0) return ActiveObjectMessage(0); return m_active_object_messages.pop_front(); } /* ************ Private methods ************* */ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, bool set_changed) { assert(object); if(object->getId() == 0) { u16 new_id = getFreeServerActiveObjectId(m_active_objects); if(new_id == 0) { dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): " <<"no free ids available"<<std::endl; delete object; return 0; } object->setId(new_id); } if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false) { dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): " <<"id is not free ("<<object->getId()<<")"<<std::endl; delete object; return 0; } /*dstream<<"INGO: ServerEnvironment::addActiveObjectRaw(): " <<"added (id="<<object->getId()<<")"<<std::endl;*/ m_active_objects.insert(object->getId(), object); // Add static object to active static list of the block v3f objectpos = object->getBasePosition(); std::string staticdata = object->getStaticData(); StaticObject s_obj(object->getType(), objectpos, staticdata); // Add to the block where the object is located in v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); if(block) { block->m_static_objects.m_active.insert(object->getId(), s_obj); object->m_static_exists = true; object->m_static_block = blockpos; if(set_changed) block->setChangedFlag(); } else{ dstream<<"WARNING: ServerEnv: Could not find a block for " <<"storing newly added static active object"<<std::endl; } return object->getId(); } /* Remove objects that satisfy (m_removed && m_known_by_count==0) */ void ServerEnvironment::removeRemovedObjects() { core::list<u16> objects_to_remove; for(core::map<u16, ServerActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { u16 id = i.getNode()->getKey(); ServerActiveObject* obj = i.getNode()->getValue(); // This shouldn't happen but check it if(obj == NULL) { dstream<<"WARNING: NULL object found in ServerEnvironment" <<" while finding removed objects. id="<<id<<std::endl; // Id to be removed from m_active_objects objects_to_remove.push_back(id); continue; } /* We will delete objects that are marked as removed or thatare waiting for deletion after deactivation */ if(obj->m_removed == false && obj->m_pending_deactivation == false) continue; /* Delete static data from block if is marked as removed */ if(obj->m_static_exists && obj->m_removed) { MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block); if(block) { block->m_static_objects.remove(id); block->setChangedFlag(); } } // If m_known_by_count > 0, don't actually remove. if(obj->m_known_by_count > 0) continue; // Delete delete obj; // Id to be removed from m_active_objects objects_to_remove.push_back(id); } // Remove references from m_active_objects for(core::list<u16>::Iterator i = objects_to_remove.begin(); i != objects_to_remove.end(); i++) { m_active_objects.remove(*i); } } /* Convert stored objects from blocks near the players to active. */ void ServerEnvironment::activateObjects(MapBlock *block) { if(block==NULL) return; // Ignore if no stored objects (to not set changed flag) if(block->m_static_objects.m_stored.size() == 0) return; // A list for objects that couldn't be converted to static for some // reason. They will be stored back. core::list<StaticObject> new_stored; // Loop through stored static objects for(core::list<StaticObject>::Iterator i = block->m_static_objects.m_stored.begin(); i != block->m_static_objects.m_stored.end(); i++) { /*dstream<<"INFO: Server: Creating an active object from " <<"static data"<<std::endl;*/ StaticObject &s_obj = *i; // Create an active object from the data ServerActiveObject *obj = ServerActiveObject::create (s_obj.type, this, 0, s_obj.pos, s_obj.data); // If couldn't create object, store static data back. if(obj==NULL) { new_stored.push_back(s_obj); continue; } // This will also add the object to the active static list addActiveObjectRaw(obj, false); //u16 id = addActiveObjectRaw(obj, false); } // Clear stored list block->m_static_objects.m_stored.clear(); // Add leftover failed stuff to stored list for(core::list<StaticObject>::Iterator i = new_stored.begin(); i != new_stored.end(); i++) { StaticObject &s_obj = *i; block->m_static_objects.m_stored.push_back(s_obj); } // Block has been modified // NOTE: No it has not really. Save I/O here. //block->setChangedFlag(); } /* Convert objects that are not in active blocks to static. If m_known_by_count != 0, active object is not deleted, but static data is still updated. If force_delete is set, active object is deleted nevertheless. It shall only be set so in the destructor of the environment. */ void ServerEnvironment::deactivateFarObjects(bool force_delete) { core::list<u16> objects_to_remove; for(core::map<u16, ServerActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { ServerActiveObject* obj = i.getNode()->getValue(); u16 id = i.getNode()->getKey(); v3f objectpos = obj->getBasePosition(); // This shouldn't happen but check it if(obj == NULL) { dstream<<"WARNING: NULL object found in ServerEnvironment" <<std::endl; assert(0); continue; } // The block in which the object resides in v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS)); // If block is active, don't remove if(m_active_blocks.contains(blockpos_o)) continue; /* Update the static data */ // Delete old static object MapBlock *oldblock = NULL; if(obj->m_static_exists) { MapBlock *block = m_map->getBlockNoCreateNoEx (obj->m_static_block); if(block) { block->m_static_objects.remove(id); oldblock = block; } } // Create new static object std::string staticdata = obj->getStaticData(); StaticObject s_obj(obj->getType(), objectpos, staticdata); // Add to the block where the object is located in v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); // Get or generate the block MapBlock *block = m_map->emergeBlock(blockpos); /*MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); if(block == NULL) { // Block not found. Is the old block still ok? if(oldblock) block = oldblock; // Load from disk or generate else block = m_map->emergeBlock(blockpos); }*/ if(block) { block->m_static_objects.insert(0, s_obj); block->setChangedFlag(); obj->m_static_exists = true; obj->m_static_block = block->getPos(); } else{ dstream<<"WARNING: ServerEnv: Could not find or generate " <<"a block for storing static object"<<std::endl; obj->m_static_exists = false; continue; } /* Delete active object if not known by some client, else set pending deactivation */ // If known by some client, don't delete. if(obj->m_known_by_count > 0 && force_delete == false) { obj->m_pending_deactivation = true; continue; } /*dstream<<"INFO: Server: Stored static data. Deleting object." <<std::endl;*/ // Delete active object delete obj; // Id to be removed from m_active_objects objects_to_remove.push_back(id); } // Remove references from m_active_objects for(core::list<u16>::Iterator i = objects_to_remove.begin(); i != objects_to_remove.end(); i++) { m_active_objects.remove(*i); } } #ifndef SERVER /* ClientEnvironment */ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr): m_map(map), m_smgr(smgr) { assert(m_map); assert(m_smgr); } ClientEnvironment::~ClientEnvironment() { // delete active objects for(core::map<u16, ClientActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { delete i.getNode()->getValue(); } // Drop/delete map m_map->drop(); } void ClientEnvironment::addPlayer(Player *player) { DSTACK(__FUNCTION_NAME); /* It is a failure if player is local and there already is a local player */ assert(!(player->isLocal() == true && getLocalPlayer() != NULL)); Environment::addPlayer(player); } LocalPlayer * ClientEnvironment::getLocalPlayer() { for(core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; if(player->isLocal()) return (LocalPlayer*)player; } return NULL; } void ClientEnvironment::step(float dtime) { DSTACK(__FUNCTION_NAME); // Get some settings bool free_move = g_settings.getBool("free_move"); bool footprints = g_settings.getBool("footprints"); // Get local player LocalPlayer *lplayer = getLocalPlayer(); assert(lplayer); // collision info queue core::list<CollisionInfo> player_collisions; /* Get the speed the player is going */ f32 player_speed = 0.001; // just some small value player_speed = lplayer->getSpeed().getLength(); /* Maximum position increment */ //f32 position_max_increment = 0.05*BS; f32 position_max_increment = 0.1*BS; // Maximum time increment (for collision detection etc) // time = distance / speed f32 dtime_max_increment = position_max_increment / player_speed; // Maximum time increment is 10ms or lower if(dtime_max_increment > 0.01) dtime_max_increment = 0.01; // Don't allow overly huge dtime if(dtime > 0.5) dtime = 0.5; f32 dtime_downcount = dtime; /* Stuff that has a maximum time increment */ u32 loopcount = 0; do { loopcount++; f32 dtime_part; if(dtime_downcount > dtime_max_increment) { dtime_part = dtime_max_increment; dtime_downcount -= dtime_part; } else { dtime_part = dtime_downcount; /* Setting this to 0 (no -=dtime_part) disables an infinite loop when dtime_part is so small that dtime_downcount -= dtime_part does nothing */ dtime_downcount = 0; } /* Handle local player */ { v3f lplayerpos = lplayer->getPosition(); // Apply physics if(free_move == false) { // Gravity v3f speed = lplayer->getSpeed(); if(lplayer->swimming_up == false) speed.Y -= 9.81 * BS * dtime_part * 2; // Water resistance if(lplayer->in_water_stable || lplayer->in_water) { f32 max_down = 2.0*BS; if(speed.Y < -max_down) speed.Y = -max_down; f32 max = 2.5*BS; if(speed.getLength() > max) { speed = speed / speed.getLength() * max; } } lplayer->setSpeed(speed); } /* Move the lplayer. This also does collision detection. */ lplayer->move(dtime_part, *m_map, position_max_increment, &player_collisions); } } while(dtime_downcount > 0.001); //std::cout<<"Looped "<<loopcount<<" times."<<std::endl; for(core::list<CollisionInfo>::Iterator i = player_collisions.begin(); i != player_collisions.end(); i++) { CollisionInfo &info = *i; if(info.t == COLLISION_FALL) { //f32 tolerance = BS*10; // 2 without damage f32 tolerance = BS*12; // 3 without damage f32 factor = 1; if(info.speed > tolerance) { f32 damage_f = (info.speed - tolerance)/BS*factor; u16 damage = (u16)(damage_f+0.5); if(lplayer->hp > damage) lplayer->hp -= damage; else lplayer->hp = 0; ClientEnvEvent event; event.type = CEE_PLAYER_DAMAGE; event.player_damage.amount = damage; m_client_event_queue.push_back(event); } } } /* Stuff that can be done in an arbitarily large dtime */ for(core::list<Player*>::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; v3f playerpos = player->getPosition(); /* Handle non-local players */ if(player->isLocal() == false) { // Move player->move(dtime, *m_map, 100*BS); // Update lighting on remote players on client u8 light = LIGHT_MAX; try{ // Get node at head v3s16 p = floatToInt(playerpos + v3f(0,BS+BS/2,0), BS); MapNode n = m_map->getNode(p); light = n.getLightBlend(getDayNightRatio()); } catch(InvalidPositionException &e) {} player->updateLight(light); } /* Add footsteps to grass */ if(footprints) { // Get node that is at BS/4 under player v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); try{ MapNode n = m_map->getNode(bottompos); if(n.d == CONTENT_GRASS) { n.d = CONTENT_GRASS_FOOTSTEPS; m_map->setNode(bottompos, n); // Update mesh on client if(m_map->mapType() == MAPTYPE_CLIENT) { v3s16 p_blocks = getNodeBlockPos(bottompos); MapBlock *b = m_map->getBlockNoCreate(p_blocks); //b->updateMesh(getDayNightRatio()); b->setMeshExpired(true); } } } catch(InvalidPositionException &e) { } } } /* Step active objects and update lighting of them */ for(core::map<u16, ClientActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { ClientActiveObject* obj = i.getNode()->getValue(); // Step object obj->step(dtime, this); if(m_active_object_light_update_interval.step(dtime, 0.21)) { // Update lighting //u8 light = LIGHT_MAX; u8 light = 0; try{ // Get node at head v3s16 p = obj->getLightPosition(); MapNode n = m_map->getNode(p); light = n.getLightBlend(getDayNightRatio()); } catch(InvalidPositionException &e) {} obj->updateLight(light); } } } void ClientEnvironment::updateMeshes(v3s16 blockpos) { m_map->updateMeshes(blockpos, getDayNightRatio()); } void ClientEnvironment::expireMeshes(bool only_daynight_diffed) { m_map->expireMeshes(only_daynight_diffed); } ClientActiveObject* ClientEnvironment::getActiveObject(u16 id) { core::map<u16, ClientActiveObject*>::Node *n; n = m_active_objects.find(id); if(n == NULL) return NULL; return n->getValue(); } bool isFreeClientActiveObjectId(u16 id, core::map<u16, ClientActiveObject*> &objects) { if(id == 0) return false; for(core::map<u16, ClientActiveObject*>::Iterator i = objects.getIterator(); i.atEnd()==false; i++) { if(i.getNode()->getKey() == id) return false; } return true; } u16 getFreeClientActiveObjectId( core::map<u16, ClientActiveObject*> &objects) { u16 new_id = 1; for(;;) { if(isFreeClientActiveObjectId(new_id, objects)) return new_id; if(new_id == 65535) return 0; new_id++; } } u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) { assert(object); if(object->getId() == 0) { u16 new_id = getFreeClientActiveObjectId(m_active_objects); if(new_id == 0) { dstream<<"WARNING: ClientEnvironment::addActiveObject(): " <<"no free ids available"<<std::endl; delete object; return 0; } object->setId(new_id); } if(isFreeClientActiveObjectId(object->getId(), m_active_objects) == false) { dstream<<"WARNING: ClientEnvironment::addActiveObject(): " <<"id is not free ("<<object->getId()<<")"<<std::endl; delete object; return 0; } dstream<<"INGO: ClientEnvironment::addActiveObject(): " <<"added (id="<<object->getId()<<")"<<std::endl; m_active_objects.insert(object->getId(), object); object->addToScene(m_smgr); return object->getId(); } void ClientEnvironment::addActiveObject(u16 id, u8 type, const std::string &init_data) { ClientActiveObject* obj = ClientActiveObject::create(type); if(obj == NULL) { dstream<<"WARNING: ClientEnvironment::addActiveObject(): " <<"id="<<id<<" type="<<type<<": Couldn't create object" <<std::endl; return; } obj->setId(id); addActiveObject(obj); obj->initialize(init_data); } void ClientEnvironment::removeActiveObject(u16 id) { dstream<<"ClientEnvironment::removeActiveObject(): " <<"id="<<id<<std::endl; ClientActiveObject* obj = getActiveObject(id); if(obj == NULL) { dstream<<"WARNING: ClientEnvironment::removeActiveObject(): " <<"id="<<id<<" not found"<<std::endl; return; } obj->removeFromScene(); delete obj; m_active_objects.remove(id); } void ClientEnvironment::processActiveObjectMessage(u16 id, const std::string &data) { ClientActiveObject* obj = getActiveObject(id); if(obj == NULL) { dstream<<"WARNING: ClientEnvironment::processActiveObjectMessage():" <<" got message for id="<<id<<", which doesn't exist." <<std::endl; return; } obj->processMessage(data); } /* Callbacks for activeobjects */ void ClientEnvironment::damageLocalPlayer(u8 damage) { LocalPlayer *lplayer = getLocalPlayer(); assert(lplayer); if(lplayer->hp > damage) lplayer->hp -= damage; else lplayer->hp = 0; ClientEnvEvent event; event.type = CEE_PLAYER_DAMAGE; event.player_damage.amount = damage; m_client_event_queue.push_back(event); } /* Client likes to call these */ void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d, core::array<DistanceSortedActiveObject> &dest) { for(core::map<u16, ClientActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { ClientActiveObject* obj = i.getNode()->getValue(); f32 d = (obj->getPosition() - origin).getLength(); if(d > max_d) continue; DistanceSortedActiveObject dso(obj, d); dest.push_back(dso); } } ClientEnvEvent ClientEnvironment::getClientEvent() { if(m_client_event_queue.size() == 0) { ClientEnvEvent event; event.type = CEE_NONE; return event; } return m_client_event_queue.pop_front(); } void ClientEnvironment::drawPostFx(video::IVideoDriver* driver, v3f camera_pos) { /*LocalPlayer *player = getLocalPlayer(); assert(player); v3f pos_f = player->getPosition() + v3f(0,BS*1.625,0);*/ v3f pos_f = camera_pos; v3s16 p_nodes = floatToInt(pos_f, BS); MapNode n = m_map->getNodeNoEx(p_nodes); if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) { v2u32 ss = driver->getScreenSize(); core::rect<s32> rect(0,0, ss.X, ss.Y); driver->draw2DRectangle(video::SColor(64, 100, 100, 200), rect); } } #endif // #ifndef SERVER