From de4de50aac8de80011fa7d2b9f11ee7fe59ad114 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Mon, 7 Nov 2022 21:15:50 -0800 Subject: [PATCH] Save world and red vignette on damage --- .gitignore | 1 + gamestate.c | 92 ++++++++++++++++++++++++++++++----------- loaded/low_health.png | Bin 0 -> 50888 bytes main.c | 21 +++++++--- server.c | 93 ++++++++++++++++++++++++++++++++++-------- server_main.c | 2 +- types.h | 7 +++- 7 files changed, 168 insertions(+), 48 deletions(-) create mode 100644 loaded/low_health.png diff --git a/.gitignore b/.gitignore index 4e2cb22..3666051 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +debug_world.bin flight*.zip flight_server flight.zip diff --git a/gamestate.c b/gamestate.c index 6618b6d..404e615 100644 --- a/gamestate.c +++ b/gamestate.c @@ -275,6 +275,7 @@ void create_rectangle_shape(GameState* gs, Entity* e, Entity* parent, V2 pos, V2 void create_player(GameState* gs, Entity* e) { e->is_player = true; + e->no_save_to_disk = true; create_body(gs, e); create_rectangle_shape(gs, e, e, (V2) { 0 }, V2scale(PLAYER_SIZE, 0.5f), PLAYER_MASS); cpShapeSetFilter(e->shape, PLAYER_SHAPE_FILTER); @@ -580,7 +581,7 @@ V2 entity_pos(Entity* e) } else if (e->is_explosion) { return e->explosion_pos; - } + } else { assert(e->body != NULL); return cp_to_v2(cpBodyGetPosition(e->body)); @@ -618,21 +619,24 @@ typedef struct SerState size_t cursor; // points to next available byte, is the size of current message after serializing something size_t max_size; Entity* for_player; + bool write_varnames; + bool save_or_load_from_disk; + + // output + uint32_t version; } SerState; void ser_var(SerState* ser, char* var_pointer, size_t var_size, const char* name, const char* file, int line) { -#ifdef WRITE_VARNAMES char var_name[512] = { 0 }; snprintf(var_name, 512, "%d%s", line, name); // can't have separator before the name, when comparing names skips past the digit size_t var_name_len = strlen(var_name); -#endif if (ser->serializing) { - -#ifdef WRITE_VARNAMES - memcpy(ser->bytes + ser->cursor, var_name, var_name_len); - ser->cursor += var_name_len; -#endif + if (ser->write_varnames) + { + memcpy(ser->bytes + ser->cursor, var_name, var_name_len); + ser->cursor += var_name_len; + } for (int b = 0; b < var_size; b++) { ser->bytes[ser->cursor] = var_pointer[b]; @@ -642,15 +646,14 @@ void ser_var(SerState* ser, char* var_pointer, size_t var_size, const char* name } else { -#ifdef WRITE_VARNAMES - { + if (ser->write_varnames) { char read_name[512] = { 0 }; for (int i = 0; i < var_name_len; i++) { read_name[i] = ser->bytes[ser->cursor]; ser->cursor += 1; - assert(ser->cursor < ser->max_size); + assert(ser->cursor <= ser->max_size); } read_name[var_name_len] = '\0'; // advance past digits @@ -666,12 +669,11 @@ void ser_var(SerState* ser, char* var_pointer, size_t var_size, const char* name *(char*)NULL = 0; } } -#endif for (int b = 0; b < var_size; b++) { var_pointer[b] = ser->bytes[ser->cursor]; ser->cursor += 1; - assert(ser->cursor < ser->max_size); + assert(ser->cursor <= ser->max_size); } } @@ -679,6 +681,13 @@ void ser_var(SerState* ser, char* var_pointer, size_t var_size, const char* name #define SER_VAR_NAME(var_pointer, name) ser_var(ser, (char*)var_pointer, sizeof(*var_pointer), name, __FILE__, __LINE__) #define SER_VAR(var_pointer) SER_VAR_NAME(var_pointer, #var_pointer) +enum GameVersion { + VInitial, + VAddedTest, + VAddedSerToDisk, + VMax, // this minus one will be the version used +}; + // @Robust probably get rid of this as separate function, just use SER_VAR void ser_V2(SerState* ser, V2* var) { @@ -728,9 +737,21 @@ void ser_player(SerState* ser, Player* p) void ser_entity(SerState* ser, GameState* gs, Entity* e) { + SER_VAR(&e->no_save_to_disk); + if (e->no_save_to_disk && ser->save_or_load_from_disk) + { + return; + } SER_VAR(&e->generation); SER_VAR(&e->damage); + int test; + if (ser->serializing) test = 27; + if (ser->version >= VAddedTest) + SER_VAR(&test); + else test = 27; + assert(test == 27); + bool has_body = ser->serializing && e->body != NULL; SER_VAR(&has_body); @@ -785,6 +806,7 @@ void ser_entity(SerState* ser, GameState* gs, Entity* e) SER_VAR(&e->is_player); if (e->is_player) { + assert(e->no_save_to_disk); ser_entityid(ser, &e->currently_inside_of_box); SER_VAR(&e->goldness); } @@ -824,6 +846,8 @@ void ser_entity(SerState* ser, GameState* gs, Entity* e) void ser_server_to_client(SerState* ser, ServerToClient* s) { + SER_VAR(&ser->version); + GameState* gs = s->cur_gs; int cur_next_entity = 0; @@ -844,11 +868,14 @@ void ser_server_to_client(SerState* ser, ServerToClient* s) ser_V2(ser, &gs->goldpos); - for (size_t i = 0; i < MAX_PLAYERS; i++) + if (!ser->save_or_load_from_disk) { - ser_player(ser, &gs->players[i]); + // @Robust save player data with their ID or something somehow. Like local backup of their account + for (size_t i = 0; i < MAX_PLAYERS; i++) + { + ser_player(ser, &gs->players[i]); + } } - if (ser->serializing) { bool entities_done = false; @@ -869,7 +896,7 @@ void ser_server_to_client(SerState* ser, ServerToClient* s) // are loaded in the parent body is loaded in and can be referenced. BOXES_ITER(gs, cur, e) { - bool this_box_in_range = (ser->for_player == NULL || (ser->for_player != NULL && V2distsqr(entity_pos(ser->for_player), entity_pos(cur)) < VISION_RADIUS*VISION_RADIUS)); + bool this_box_in_range = (ser->for_player == NULL || (ser->for_player != NULL && V2distsqr(entity_pos(ser->for_player), entity_pos(cur)) < VISION_RADIUS * VISION_RADIUS)); if (cur->always_visible) this_box_in_range = true; if (!this_grid_is_visible && this_box_in_range) { @@ -928,7 +955,7 @@ void ser_server_to_client(SerState* ser, ServerToClient* s) } // for_this_player can be null then the entire world will be sent -void into_bytes(struct ServerToClient* msg, char* bytes, size_t* out_len, size_t max_len, Entity* for_this_player) +void into_bytes(struct ServerToClient* msg, char* bytes, size_t* out_len, size_t max_len, Entity* for_this_player, bool write_varnames) { assert(msg->cur_gs != NULL); assert(msg != NULL); @@ -939,13 +966,24 @@ void into_bytes(struct ServerToClient* msg, char* bytes, size_t* out_len, size_t .cursor = 0, .max_size = max_len, .for_player = for_this_player, + .version = VMax - 1, }; + if (for_this_player == NULL) // @Robust jank + { + ser.save_or_load_from_disk = true; +} + + ser.write_varnames = write_varnames; +#ifdef WRITE_VARNAMES + ser.write_varnames = true; +#endif + ser_server_to_client(&ser, msg); *out_len = ser.cursor + 1; // @Robust not sure why I need to add one to cursor, ser.cursor should be the length.. } -void from_bytes(struct ServerToClient* msg, char* bytes, size_t max_len) +void from_bytes(struct ServerToClient* msg, char* bytes, size_t max_len, bool write_varnames, bool from_disk) { assert(msg->cur_gs != NULL); assert(msg != NULL); @@ -955,10 +993,17 @@ void from_bytes(struct ServerToClient* msg, char* bytes, size_t max_len) .serializing = false, .cursor = 0, .max_size = max_len, + .save_or_load_from_disk = from_disk, }; + ser.write_varnames = write_varnames; + +#ifdef WRITE_VARNAMES + ser.write_varnames = true; +#endif + ser_server_to_client(&ser, msg); -} + } // has to be global var because can only get this information static cpShape* closest_to_point_in_radius_result = NULL; @@ -1083,17 +1128,19 @@ void entity_ensure_in_orbit(Entity* e) EntityID create_spacestation(GameState* gs) { -#define BOX_AT_TYPE(grid, pos, type) { Entity* box = new_entity(gs); box_create(gs, box, grid, pos); box->box_type = type; box->indestructible = indestructible; box->always_visible = true; } +#define BOX_AT_TYPE(grid, pos, type) { Entity* box = new_entity(gs); box_create(gs, box, grid, pos); box->box_type = type; box->indestructible = indestructible; box->always_visible = true; box->no_save_to_disk = true; } #define BOX_AT(grid, pos) BOX_AT_TYPE(grid, pos, BoxHullpiece) bool indestructible = false; Entity* grid = new_entity(gs); grid_create(gs, grid); + grid->no_save_to_disk = true; entity_set_pos(grid, (V2) { -150.0f, 0.0f }); entity_ensure_in_orbit(grid); Entity* explosion_box = new_entity(gs); box_create(gs, explosion_box, grid, (V2) { 0 }); explosion_box->is_explosion_unlock = true; + explosion_box->no_save_to_disk = true; BOX_AT_TYPE(grid, ((V2) { BOX_SIZE, 0 }), BoxExplosive); BOX_AT_TYPE(grid, ((V2) { BOX_SIZE * 2, 0 }), BoxHullpiece); BOX_AT_TYPE(grid, ((V2) { BOX_SIZE * 3, 0 }), BoxHullpiece); @@ -1321,8 +1368,7 @@ void process(GameState* gs, float dt) } if (sqdist < (SUN_RADIUS * SUN_RADIUS)) { - entity_destroy(gs, e); - continue; + e->damage += 10.0f * dt; } cpVect g = cpvmult(p, -SUN_GRAVITY_STRENGTH / (sqdist * cpfsqrt(sqdist))); diff --git a/loaded/low_health.png b/loaded/low_health.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d1c906b315a24478297e8d9876b08fca1521bf GIT binary patch literal 50888 zcmXtfcR1T^)PIH$5v{!`MQLrSs1>wm>3p6dR_v&)_Ks0nv$Uv9wNHmF5?f+biP=_+ z7*TC$t!Rx@j5q!L-uKFt{PDeV-QRnh^Esb$&gXu7`=%KuOaul1064FiU%3kafQbMA zNDRu#e4^tp5Cs4LAKo`HxqZ#VL^9xkzsG$acK|>>J0@G-ycZ$XkNW4;3w|~Q^S}?c zOB5faK6?6Z161I;UBx}Nrxu1u=QyvWrd3jH18A-dKdE1;s}idup|Ke4%R1-V%padv zz?59{v^NLZqq5q=Ft=4SCf9|)|Bk5N-G2Ujq~=k)^^PP4I4r5C_Rp=Cg6cFe)IM!{ zS9u8AF?OUAncFc4C^Oe11^1qHlq;QW3La(jNm=FaeF^$Ikb}1$%RQD(eRrqpNeFVOqaUecjr?7D_^`VJU;O>@h*V$0BbFR4 zsmfH&XUdwsa;iQUt_1PtEVG>?F3uM|d>p8CUI=^{<->3l zg06!y3Vq|wP(qhkXog^GTN3Im_*2=-DO=mG&{Ybna;;rq2b=vSAn{h4n|bEf*XQ|Q zM22w8Kc`j+kT&c2g+hjQ3_$(!)|we?R4&ub(oXum_kUg8%>y-oIZUps-ko`H(I6+KsDh-#MTV4n8CEq+$R- z5^(K`(ZAud>zz}1--bSxR4f)+x?= zZI-k(&bEnhQUV34JqqgOCkg`FZbOgZ#M~uoj<-m~E{Smx=3a7$R@$Ui<*p#4d)W6$ zc^YO`aa@$MV@8p1$7)f|E=pgj@IGg)7ke$B3;G0yxBw35G@9m(ox!ZJzqe8dyvS!} z7pG6O2EV&66;2tT$2|)WWhYpc<3K+5rdD9&h0u7s?*I#0Mc&k?R=~cdc0?GXRrSr9 z<2C$^1NXD$D~$Ajm`seLKW!3p0pv45sH`UDZB!BcFRi*KG`^nH0wvc_R53cdET}fb z$s&ZR)zjZvL)-v~bH0BQquQ-CbdXlhTIpQC*(qYahjA9*l15zQ_~13_YVlyR==WZM zV)v|XXARN(%_K&F$4?lu2JDfj{j>op;mx#eJhmlH!TM^sIyPJnQJJ(NHK3IYR0H!I z*r_1Xm1FE3y0$fJaGSAjJ3t@tdCHlj@6`O%sYdpeWkP?_muhNSf{j8)qf3-;IppdM*= zOLdf`$A`KhV}mP?u!v26E!#Z=>rx!Q+M@&x$d*h$X1rA%hawyY`DaOI?R7*i!V{Wf z(oe8UTE2Vei$try_`UiAkAV15csHCDld!AhO`G*!Ysd2 zgav-_T^k#fw}~#@k+!cHG5UE{u^1&dclqpa2a_9c!jEQCkCww#b}h zZy=Ad&T}2^F~AsUtUh)~@@jm*ImuC2yRcJ>)HGXkb^|fnDIK%mspXlqyYM89l_H1v zmFE_BCyxr9T9re_Z|zNNj^n6dA*;IyUnaeQ-WV$mEEjZPPwlwbIV|3>fmM|^Qy7t+ z#I(s+0TwJps^U3&E7C|?0d5h$%`W>yFH`uA#Ch-YFK6%tlBWqW=r}yspN}Q#a0KAC zgRk~&#HfOk_2X^8MKeQ^_t?HGEp<^~#o%b1su&W+4t!(9l^LA9=`)VAFGmv7K+Cz3 zHgkI#0BNUY&|zZ@(MOUD@Il9oivDI?p*g6r3&0{N2c*Pt{NX`DkX?KPNxGWo0J|SU zk2$+@wnDp-BlsL`H34Lp=Z;jciK}{lWWfHc zS%%@-2e!t7tT9WT3IXUu$7a49t#$SCY0}v_<#F}#P9Fx4D1Kts3n_%WSLjg%C1^f5 zNLn8&_!5InP=!6IbQ0oh=O!x25 z(B0z|I6@0thfX_}7Rv3;GlC%0n!G=)HG~MG z*oBsCK2wYa<`v8lUSyn6muGqKzh^o`hu362WzD38Rv&E;#7bG74|%W<-* zbAiOG_T?x1+_4%70WyaMO2=9zVyYtHy2n$jUEJh_(c@t@mrHz=6<8&L-lJMK2y>%s zn6UBd(_9&rSSMgRGtPt!q-wF!scGJXe_9YHRoh~Mt3EVFAAM2rRhCGCccOnXeNlcD z2k_pbFT%)+!?X^5ZB`OYOq@*&(&_Ud1F-lyk@nA0K4-h7{HPe)p$t@jX}Vg8Yaj>i zB#mDGfs5;qF#n4~uUb*7ff zEY>V2cD|Dzpd*zt0K$h2k7gr~THB2fAu`^`BtTZu)IX7B@tu3t2p(tZtNWiEc zWK)}}Ei`H`@OBxadn#O3$n-tXOs3Zb90(I!jnh$89`j^68o_aw! zO2l)VxC>I|F!X4#_QXy&y8T!sR=h2P^`h>vmSCTHR)d#Vz!cbz%L7!$YNbK+XPtI8 z-X0pPzs>YF)-RwV6wo=J9cM`$VIg>89P~G}q*>4qmrz}QT1+Y>XzK5TQfb4P;9C3B z^dFn!+>*uIsaTstEYY9uFWgwL%bXj&zL$-^_>m1z=}?OO%y2mW`*-SK-HWGABY3ol zx>vhAf(exCeq-kK8}RW4CyId6u-awbivj^rWi*VQH^4bNCxpw9x6=Wi@PK8hypVKrj(Yy^2`5sLvwxMUNM6}pp7VCXFRN)J zz>4qZF=&Qmbgp=UGkXI*COu99+RjNBGmq`Ro`B$MUO%|FR-*5Z!;;v80*+Kol4!EPt@iI z9sUsL9>9gX2$%OrRN;M4gJC3z5EbQ3iEjm`Jy=(3h=I>*Ckm8^OveD#3OGpZSrGi-ur z>-N##2;qu?D24O!c^;CW41vvX{KUBLxGB0lm1ZUV0 z_huA{rNS@TW$u=;*v!NWa^h@hZt)7R&`RfUO=xW%dt@{#^+XKbp8FGE$R4ZvCs&0f z%GfVSQ(F{TDYefo;B=7|*$31>{2t7sDoq?WzCW?Wv?vj`sYQ?g>7|yZ&Ncb$k@ujX zHQ>XtY^P=o!~m1af;vlpmj$_`XWhYzuX7Dt(2=8{_IowN^xxAt_9Q0Y6@*sr-cow} zxpw@RNTC&-N!Dc-V2z%bVC^4fJh9W5j{&4T9bH$RD=+0RtVbs2VZj~914aFl|<8;A0g)~vl?qPSI54#w5 z6)rMj{gV=tgP58$Koq$VvyW>Z5Fg|Nrxi7~JHn!EYnY7U`0Pcz zB)!v!mnRVin_+IPb9nJg|<*0uJ3$;>w8)f<;UDOp7-gp3= z{hL?iy#prG$0q`Nm~bR5^_;V>;#&Rj;D;g>Z;zz2_-NO#>@NTKU;Sfi&|9Am?w9~O%#=dPzdAZrCiQ-2ED@LFx)0=*Bd*nV#50pp z>oNLpCS;Grg-=YQ*(^b2xtWb_MPkXYQ32|yFsBytFI%bB>y0+CoHIL-@w87vQdjLT zuV{a+&~d~70j3Xdk!0D)aeCxi3GTk$Gyg4VX|Z7A!zPog`4Q8N;#gl(NhZ`iBLxZ6 zUo9TU`)d1wIf6{@5KD*R>Q&>-pHy$i*Hrd;kyvk&fXO7ATILd^!E+w(7!*xRP_IAp z7}JT2re9``RLWr8VTBDiO4veDzx!;5?A(^A520;W5ZLPr9KCbut(WQQYck8GEzzJp z4Ya7TW&qF*T37kKmAr^HQVlAQ`-+EXpNiJ~!+$1yLUq<}bi3aEE#F-hnpMIAO!Dvw zM?J((y1V7Vp@DdU1~Pe)IS~^ndaXTp8vKZ9h*bzx&;x9bG8XU8M^~RKz{(MRCA)C? zgtEUB0g&|G50O!v#7Gk+GHb-Eh=f*3SvNZL`v0W{p@E6aeDq_Nnu&=-ui(E!K! zBOQ}$Q&h=T5Ge;U^B|;MOAl?CoC|z} zZ8x@Nb!L@8V*z&Y`H(h+ZWZRpo8z}qA^+JWGINl)xauFr9bU|VSFiS{f@3M5^oR52 zT%(|YkKd}=45En2Dt{(n2vP8G_F%oxZ6={qdtwKS)^z#_!8;PuSR4e1FDeAtd&N2I ziJXzlJs4nZ8TprWkT+8_wv4UYHekdLI11`14Or*wg|Ci4I~v&QX#wqbJ5=|+N2h$9 z;YKoPi#G zt`BEk%Mxt|cXj+hin`QLkfMsyG3-MLl*C#OZK(nE2!BbGuIZjsBwE?vFhBm0(vDIL z5cd8HR$J`dVVe6Zum%D@wONVSsz`)SZ_E<9Nc!bkD3GG~s(~g@fYqim^FG`1&7^+d z*HP#OxWzGGPJp^%q}qF-qfvCH43Highi9fohEqw4K3vR1;}zp~!k1x5G2noYP$tO5 zO_Y9c51^Vyq`O2qZh1?He#cgPF;4rRD{l10KK59iQt#)QfCyV`N#njQuB zq)|W4%xZ8oo0&!H9g0~;Ts9N z9H|f5l$F z=?X($GBeplh0F9X6SO$|E%VT!Yz3qBZqJ{!Wmh`|-k;uF9y9093+|gBin4bqa&2C* z2_%wOmtP|>IMp-^^&P_URuYcMhjhV301}gRt1kz&8`k*(GXXB2LzxK(yoaASr7@9P zxAt3~7TK%Jt6JtJzL2vidb&Sca`f(L8_=6ukR|xz`f(>w_7143WB1?fxHnfW93Xc0 z^j~Lh<_w_h#s%466na&p2Pb(gBpWCZiK;x&HL683u=E5+0h&iZj9>GLSb1@!L_Pdb z6;Tx&i9-|tlXSVQGVYp-(CqmWbh-1ypIm*yBnh`HF*w_!MP}SkA^|#(JWj~wtG=!? z%CP9=wG)^4{qwbB1@Vyz;T_YF#NUX+q)4K9`6NP-H@K?1mW`_!!elTrKY{K2;J;-Q zGUxM9P<8U+P0S>Fz51bP;@0(ovO89e%o0g(jNe*7o-GmYtAxfV}2<){^?!@>7EKKxWNGnHmC{8L@<>8rhg?M71= zl)!3Z{FG?u2$iwDj|OV~nuMB8AHlyJ#}SE3Ct+U)?KjFj5Q20nqJvE^O)xGk^5Wm)*l()SZ9yUxD)vA>r1wpPI18;_g5R z7?*qZtJkv6JAL_9@eBm=}?b?SDZh!dPRJ2aJv&z+egBr+Unl0H5uO*irtAFH9Mu( zXS1>?pz0s~)*F6PM=kM`3VU=&8rk-5KE*np%B2VE_P_F@5`S=z=r`Yj>P-86o$Ms@ z+ygS_r97^&(hYE&9V7^d7e1YGQTz3jev55L9gJ~xp$QL*h^?Jy@cPKXaG!W{)v>=GL zD(r6AS5Sst*2q!^ms5587auDWC)}>OXF@W)k;|@ox>uz7em>-pbtc5aHYueSZ_?lg z$iIdO-z)ia{J*d1V*R*!#pY4?f-}H|gjaZf{KDXKIYNN5$6VE;`)@VTHcG$z`NSzm zKndjX_gSqTwM)GQ&k-HMdnpOdN%w4WKBoeEG=! zB!03b*n4wINbOpK$C3?03zX_V)#*pYD-p#6?Nzi^=ilr^*k)NLpf*wpXHFYnDHc*Q zAFX~dd`>hdHr4&@PBWI2s&8kgQ7i;T-*GL1(s855x)9mH(X2xmRrlDS#u#uv z3wynyZoZZK{b+%cfvq-lZ1#=&dcJdh1(4;qJ~MZJALD$nHmA-D@58Mee)Z& zw5Y$r?kVVbvK;>5dob!kJA%;c-fm=3-Q%LW2*?C+Q7f10RkKQ?o2O|zJ zo8Em3;~qh%#XmjNr!)`QVeXKf(kw2*a&S(193S|lgeI-9eryKT8|`0qwO*9uPv-kV zOqD+=oz(BeK13zq!i1(Ot2>};C48AeR&z1G7O#H^8F_TnxTxW#ONyMCrm5kJ?H+QI zW=I{?1gN*_?Ap*L@ZHLj(ecqy+H#_Iib08 zJL|#Q*74%%g-<|f}CWI|)naT=!{t3Us zo5UT2+0(i^hD%VfSi${Nvy#5O*1a96Y9VKu0(xOH@p9!@6%M^4;IvWReKTpYWf6d&VXHpqG4wOD17 z(OKs&r@sY^RS{MmA2x_399CU@uC+IqFE#&SYptLhgS;CC&iDbzNGEL3#~q4W}!l2*66_yzw#rsxw1uywEe3)%Hw8h?#konHG}un zF@y(UcrvSL%XM!JL)1oZ;rYu!dn*M5>=ei#GK))jRD+Qb9A@gCY+$FwDkt6ab>8Si zpLK%&AZ5v-kUtb_6Jz~0#sm1zrJcr2>rnbGW;V5ffV_UDq`AL;-;|ja8@z)wF06EA zXPvyvF;CwOYiQela_B9lo64K1{M7C7(IjR=Q3l%`29FsOQsT0hLdz$*0d3F0?Z!wN z%HbXb-&_ap*=;O(${TD{)pdsnJKH5G2<*3)MH0H~W^i^sl{MOw>KHG&2p|yhqjQ z1z-w;Yk0fvO*r)(KOpW;|4d^+C4qc0jz$Fb*X|v>k)4XUns>z*zyA|Weu)g_GR-K^ zTg64&#N2hD-up#uGKgM0m#8NHkGkRyw%7iIIQSXn;SSav^xazhKP`YzAi=TZ?57iO zumd=}E*nfVR|mjdbuH|&7Q0B_U8Ad75f+W+X$SUnRJ^ItyZ z&Fh0&EGKhschA~5ZERU8Ppr~W78InGjepqc2W?cAwzF>$cH=!Y-=xhe?U?bd?yW%Bqg<~~qGm2_6maZrOVzYC;MI&zy&njO~6L_FE&9*5man|*si&&l8(QYB-P9$3| zZ*79(dc_$uIW4Rw>dDMe#6jf4B`Y*hf|?JToXIYU<-!}a>Y|etvpu;GZ6+4v z`|p#Yzh!;55D8gV`A-QHUNBDn_9S}CSKvTm23B5g)p7>ZU%=`)AD4T&0cIduMc zBX94~rI}sVL409|aE7s>wWqHoEq_r3K!0(QFYup<)1j{<P06T+kDFtrAYveYW<>w{hyoy~n{KlR-~vBa*u|*n9SUzddfe=&GfA>3R0LCQmf7 zE!|D@S*<_`AKAokG)IO!gn&x822|P%#ALHRtQI%4_@%(77|Obe&NXbri}o&ln|ZhM z;hCac@m7gT0ef`&roZCXP4<(kDBTBfijtYt9P6Atz1o||FNswx2#fE1>r_!-cM1D! z-A4{^?5lLXw;a71Mua9&(B-ISYZ{Di6CLz>8uRY!bLsK14`&JO4Zc^tD5SM(^zgix zIql+bNz3y_6oWE~mK{HNMmA^+Lb>Sy(jSV2J}Y zTY^0f&Qo-st1V#Ga=dP7jrF5&xf-g&)CuhoU6J;4uArv#jX_HBI*x!;9zR1%`)6~V zG*M8FCR;o~&{_VzzKs1amL<+H0S z(=Tc|1JVN)bzxVek(n;G|R~siO zt$8ri-eq{qO=m2_9;Bxxn{-CUr3_4uR zugKwV@ddxVR`BewANGb{Tyssx{N$oZ{m9B*p{wuE?jxq;h|%AE{^*R_F*3{BS0ifc zeV_UogL`|wzLv2B?b2QHCkduL3f`Jrju1&)wm~V zz_yX>^BV(~yOM+I7m7EfVX2x3X0VshmW)tktjRMk9{LMs z8C{mKg#RF>oyTUV(_b7d${1WehQzo}2>MkJipga^sGCdtSkUO9-7bELA2Ej$;DS#q zX+>3gDhu<%KR$~6VAZFXe%uVQQwdw$-}n>w#&Gd1YKuHU;QzWlYk-P77ILZ!%UL=* zVlyT|(3^ju>6`3an_A26Gn4GV_PoOT{*G5oploGn`nx9yUwN&BWmwnl%#|4enB7y? z&w(-cV81cTFl3HX#CssNrdxpS9vb}lQt9LRa9rH373#+Ol?znThdnXmiQpOQNVXQG zuqV-w4->bGYa{}4wVi&@*NnL6-q0um5YkF(HQJ;%b}Gd z8BYig|E!4(Z2_)#NF<(mP+t7w+04?^$Fi4e9S$!ltGle+v+se}?|hdB?=;4{`^BN3 ztf?rF5B0%crBzKA4L9%;s(R)}hL@$tmJ~SINkzUCDd;X^+=RoZ*`}Bpo%;th`h+E| zV3+x>^ST<9@VmJx_6vaofp5K$_M~0TkCNU;FoE6vGzdZd8wS#QhNfGE8O&|ern#RV z<o+Rg$x@Q@ZGUO z{U;mFlBi-Fft~`86Mk(QgqIhMwH2N&)^SRQxCmU?dKoLoOo6cjC6P=P4o^^ZvYlQM>y&_%u*ga-Yn>r==$4YK}wRD>R{@kk3O_MBX9>}kL*Kq1l zsDLW@nB1l}b^&Ge!Tmz|0yT|=)n8$&RaE2jFWVQJXUH+L2idIbbN6^%MwF-QVzctZ z?GiOwu3#O?%U+09O3|+!JV=h#;SY9&R(0`URDLNK&z*39{4I$Y%;okQ{DeTK(pwukU*s_#d$eJu29!VYnr#f}Us~6FZkN!a=?!^*6S> zV_IXyXp;s#2ztsdZz1*V+?{hFhbqdMKuttBtIBD~ydK}LFZ)5xJNN@%nicBtU3uiF zZHkSGIEUU(K$bsD#ltc+nQ);|wne2eDEtJvhl}0*Pp^z~&e2vQT)KAZGrNJU98$SP zy!x$Zb)&D2kd} zNK)3U#X?x%8GVa{T-ohhi2dc`drc~R&RxN`T5Z*eE6kSodjEP zgXLTIzL;weVK65>l~+s?y#_Rsuk1}{9xeZ`^^nUoU5Hf z`}l60S^Z=fCQrjc3YqJ1Lsw4-0RYdB}CQt&gcBB=~Nxn96p&bDS&M&3(5Vx3c*9!!_9CsQO!P zzSL#kE(MKTCRDWG-AG~sue$$wWgev?C&n{v zr@?LAQ`#vD>;326z$dVjjq3(Y7}`=>es8|=XKNL=bE}!?aKA$pm$NpIST=ey`CEig zUIQi^f4cnHT~kp`glB~y#DH6M>RP=Qq9NKaQfTjHa{uvkGRV!F((W#7|DvoI&QWm- zx6o0#u-@$@pIPj<52ocRsX!yiowqk zQX1yV2q=@SQ#n$2DGnC9u31S3?P?hN@><^Bu?;5t$zoCRV%6gQcGs=zv6`O@rRORL z1_~vwtaZuticdlnR;E7cPMxT;Z*}M^4(QT5bLLc%?+ML#Uqyx73#WwMj;Zf_hf5`Sn%sR>>yvtPMBgr)Lw+ld&B|Y955Y{V7y=UC2n379M$mMV zD3W>Zmaz}*vmT@zPwp|yU`*rbsTJodlYAaU%@v;INEVjO2^~-~#*VfX7s1z7_ggK3 zO#&nYJ(K*V4zL-TRw*c!ve>uabeZ)>nIpq4f(1h*+mO^iMV6h&&;?87@d;WxN8A{( z?$Ux_#lP;EK-21}_`2a)?|3ecvoBj?4uG4H>~%Z)eqrHzdO~>Q!pu^Dk%tX}vGkDv_XlmG- zJ&n4H_mm^PLb~pH*PZs1tYACc#^0zkP>kJl96&!L_XfB{yj;@0)KJ}xU2YOf*BNZM z{oB(N8k@iooNqkz+HeeXQ3Jg5W4Gg(t{eH%RbXH~;!E7T?L4GVU#CI0<<-WVe@w>~ zK!qd$Ugzk#?9CLRj2iKr3br2HDPBHsA9I)M)SC50*ZGEUW!AG&h|_Y)HWaH$IgMTT z70NnORx7`8*Ic{VQ{mIZd<9Bckp9B&@(W%=om>VWjQmb{+>*=GpBG3lY00>{oxOg# zb*}ByJq{bzF1>J?0=oCw!VceujEAmqlHUnqm$^(o1NMfmXEm~p*_-9IIE5l*1XwhJ zH~8(#nVq3MS2jvo4r`B!OUkGKQ}n|drQnNnD6b)LA-v~D!Li(aqdfGIBUn~&BDra| z@xWH2V{~)bT33f2X{;g|F8W}Zsx8fB=WGM&`Ea>=Hs;?!XhyMMQ((6M)Z;y{G6eEI z^n*Ln;<44|%2)f=Sj)CjZe!?F0ZPOxloj>eq*0mlZ0LxcX#rMFBW~TLEV64hOp9Y6 z6iLN@W?sN8x~)Z0gn^yr)REKeIXPE8GJ%8{Jv*Ij1mZSV_VifClxExJ45fD%>L>7t zoDj!0O!LhRT90I`EZHlW876*DC*4&^bRKWwWGS8hC5uO646 zk*qK>q>Civ8rRxbDbS^CcCT?G#BaDkvS>prYwXAIm9VK#bNwsyScid?_Ox1I>`^S` zc&c?Pu6W;LPR^w>cz(t}lT<*;%w$xJ;4>Pw7(XHpxBmLOHDyuXZo@!xZ7Xj?Z?S-> zrq_tU91*@xlh+7#at_J%S;tXA43U?oRImToPj=d9{IEV&I4IHJdv1#J{0ENz}E-lxRk!kG&?`Hxs^td1VY>WdU`7FL+$Ux>Si3Bl~YDA7v1`n=#sxN{LG z@$5FDgLg4oj<^*wve;@lW)gnN>f5zX0_^=7F<|Z$U5>81lGNO%6DD&*^NA=9unrkUSC)u~&WOVAX`Xj!?B+81+OFgU-D!`e=q^y~bwV)A|Dhm#mT z()#ahpli%L`V@S5cG*Zs|6E0N_qKa>W-N&$gDhv>JFwgJ*-+04r{?b7za?qfA%{fJ zDQ$w0DeO|yUgG4~8kZ1O6k^6YFNA9;AejQ)Vo@?_v_u2+Ocx8IJ3k_si?o`N$+oevm_bzki~{DI~-pZ{AKdy^gycKR*UPemcW1_ z4c_0B`LK3*!%0^J@&2rrNtWNe>l-%&_enAjYjhh^0H`rM4)nnBsK<-jp4i+eBd@+L*!|(7JkGC3@ao+--FGv`z9}>Y zBIsFn>j2qkc$%i}mQAnlOjD+o2**l0l;YF^z#V?EJn7B!(sr$&Os#X71Bvzv&xKPv zXpDI5SppdP(Ky<_q7(nOs}Y(;8)%Jbw!EG-*vM*8(}!g&Jwq_t28%p;e3bjw&s@7M z6Y=cIN98p6jHapq%Rlra<$M{3urSnCbxSY3_9Y%fU_G}`?@+$R_R~;_q4BGiBeHBg zM1($XRx0FlUVepi9DQbm)I?vfi)t7UeLdie4EGfnbD-S{Q?^l1+Kb-U_usT{5cu+k z#Wv@dI$_wb-Q9a%Ed6?trf#zuNv2`y>Q9N;-70iqZ6Oz_@|mZs0<%_PcvFOVSEKfO zR%s_+FExT1Qu<)x9XOuSi?2UXy18mrnQhkHj zv(-3z+hxzK1Ag_cFu>?jao*|%I6Cd51P6*k?!)L0cKHN7uZZFmE-tU-HjO;})Z9z( zJdc>8;1}x?fAm9f2t#4aF|YipIVQiS49Lfokv6j(^<$8m_P0ovTHE zZ&D{7x)ra=gQ$G!|D#)Iceuk@n*(aW;xp2CX#dM>*0jGu%=~SFH~F5f&Dojjja^}wOk+FAAxQwK`R0y z<_RIVn?DcqOrKT#wiIpEz1S|3qv@Jvh8KSB9KAhvl;?-9Kt~!opEyD@U3?8881UnHLd5^04a*mh-5qD|MSY%>KjX zyo$6c8T$!yxJHP*elM3#dEC%+3Sb&G?4^lO8gL7qlM3(3TC0D&6!s*)0#ShTV~y5) z`mR=qG@B-G?RKrr9e9^-*dy8H?Y*6aj|z*&bJsiO{ZyKN#@Zxn{Wfs3a?ZFKu7OL# zvZ9cIV|ivW14C}?rq!fEK5uCApvzIokFeDfrGd{2MeQL~cJW)YM>-z&?aQ%7EC&h# z8o)e=&;1MkG}hhIr3zaCoChPm@HkB-p-$(cLz7qT5t-?!HgyCr7&aANb|<2;u>^Gb^Wh(7oOfYp4lHq&wD)+?FhxVr5(dU`8AW!Fe zr5A8)AyIA$B!FX7BvEc++}XN^HA$@W!&ht7B=v;)@8Ngp^P;if>t~$HHO|mY5p`@d zTYLW*_P5n%F2n+7|7$ze_55t(vw{&i-FpzeWGN};%;{Jo!y}R)Z1u%lQX*-0*8O9M zrTktKOv5z+mq!=Y9`%4o@R%Q~(fsnOnAav`h$5K`TODAYz}*RA6@;0bw`d(65Vw94 z^Eo@K@rD%X9L%3V;m;#|X`765ZJBGXKcr?)Cs!rZr)WMeVDXlPO7t9AOho`1JmRWk zdp`c`TaR(Sk@S#mp3@II{I;LP`>-RG^GgFcI4GcYfAP0&0e{?0DGf1`=nir~_tgkD`!v3;V}Z4wdp{wvm%c?7_% znpY)o^>4~0(;s=fyZt*RwZL@sa>0r3n+}9U11%_%M&`i1-*5a`Jzg-{=C)y$D`K3V zGu!nw-Ps|``(rq=^W*kk+ta^x9neg<3b^6>+->AToT|_LLIg zSF5>v9=dI)-?H|s`(*|-N883%8VQ9Maz9Z_K^3eqRhy>t5zelz@hH{~+v%&A01pdQ zj_A6n5wO~+9V4OpoS6ZSnHS1}yji@R`6?>^4StAk+P)C?65{(K#9$ugJ$FJe~gJ0c(_ctc%47*Oy8?Q(; z7<+Ea7L^W5m%Sa$(zm7DYA)1;g^}hfbtH$etY$4&Dka0=j^9_HQ1YC$_uXokX1r4E zxX3ig?dWPTFUO+-E2m4)B1#OCFD_k@rrYxUhOYTP7kR0z^4%;E7)@sKz}>aOr7%os zS!e_~9OWSTY*LV;iy1<7sz>c2WQl3Xt_p{?KWUB|L2{O7%xF=kyU-*9aD!O#QB98k zmq*K0tiy{tgAIBlnfrVFNz~M94KFdu4u;ra?4|nVUBN)dnQG#MB>cYCGDx4}gE^G! zGf)q$oKho6-m3>iwU|gdlx4d=9e0Xm^My`N>Se)e$7g*vsak|dEuQE*E-J1G01j>Ij9g$uMuIZUOZPeX}!G3%rHyGy@7V;_?Qx8(7Xu zyE?QXu#(}Xt^2hQF-R}70meW6#L7vD%X`*33n+o<3T2arTWlSC%krU#7JW?xcG*&~ z2o+eu3{{V#!(5*HjPG({yEL@a;lGEA5eRZG&0bNBHOcTN^!MBgrZl3-;^GC9U;!rV z`8H`LR86u-B=2G=;c|UB2{l*8YMmf>WmlU}wk3T7hkcWZXf){Yg~#<5Z!RS!{=7gEZo7MR+R4K{ zz=LUe)=K9Ebnkz9>VlaeqrPr8BI7mkjMQb{9{@2FOKKHR_7dE?+=in@xQ3YPis@up zcz9X@isPd7LsSz#r5?eZ58YB{^*y&KSX6-U~x*N$UpeHdp>KJNr9SnHWXlMw>+W-x z7Gred@!8CFV|YN{fT+cpgRV@}<{S0H+Ld4F4NO>=;`MnLXI;PAmblG+xJ5X^&l_*g zFWL%u*gjN}91cp$413&lEAwIMQAQF~YVNecdGgP1Pa59?qU_?h2i$Gq(OW0Kb}{H7 z$qN3X3%hYRq5|-yOm(CU^V$&C6Fu{-ELNLr3f3h--!)ou-_4gk;=Fq`aqAS&?tC9? z_R_jYH=TNX#NICtH2~YQ%f~^Mwjt)@lJ+DKv23w4NcZe%_BqROb*IT%teZfd-byvO329(=(%w#);Nv6_r|~%Aflli6<{xWdJ=o1_JY_5pRAC0Y+@T zvlEKLQMan<*yz`*J1xh3sW*WA`G`aQH~&M_o5w@>z5nBOC2NK3vLuFVsq6{KQlerI zBfISTZfsH6vS%BFQkJogeeAL?W$cFR24fq;F#K+>_v7>Zoj?3D59dDTx~_9w=UmJ4 zT5a=1T@P&8DSq>aJ;D#Q5aZS+dgUn~z>)ABlZX``Mtqe&t;8$zQ=`zD$AJ^`(xfc^ z%rX{yX#Lm(u93XfiV&>vCEVa__`h6$ytm(KzBF0Tma}BM#4>Cu)>Jo!*U_@&8b(11 z`laVLewOVJ^k;ERhvZlH zj5jC*kR*@GIfmwv?x>_|Y-gX{>C3E0fKb+U5GKlrX?{+G+0#f+puke^BbD8!QY_ zY;!W4ss8k=Drrw$GHw$#p|Y!e-B02~X^Lfdpz7;v=7uy{3IVd{Q7cm{m|`Cvn^5>j zrF?B^X%nbpcSa+|1+~aVl0pJ!jwp2=oty*|n5Sy_ma0mvuenR^<8aCAV^q1ZX*l2p zKQ5)huRQRT*NB}w>-NbT+mIdFkyM=7&Pw8ve>d^HIV)WQrq#u}*oER)q@>B_F8bt-waJxiwhKmYnd{%0#o$E65^WbcO*$W7lcjDLw4nUX0gE zZ7@wc4`Uz|+{1as(V@Ika60jJgA@hBV-A}$7eE?%TZ|T>N#yAi-UAv3XLti1J8+Xb zgXkCdne=I+f~{t7O7Hd*S>12A?)1`|(u;oYDUG8P`LC+&;ozAJ4F0ZT><$3doChIXmy;6~9gngRD%TL1-OHm^#cW2^-U zu?QJ;1-%Jl>al2eqK&eyAv1YwH1j}}2wA0OFB1f>5*$B__Tiuot=N)&>AuZkH=o)N z7n1;!XS`=Zw9rTe&5Z&OqtdT83fJ029m=}|{e!NQ=`kF0hgIEa+mAc7Zrhcp9&dN2 z!oX{FHA2ddxT-iY+KoIm>ZT0TZ!ALirB(8iqAN;}#*@D8M96lKN!~g9Q0e}eRA~!c ziqUVyI1 zpX>v3OhP|jX)DW!&6YH~KlN_&#w~No1u%(b#+g>Jx%6Dt)MmTy1u>=0Q=wCZ!gsSx z?su?ffn*JsuawBlpJZWY$Be7(k znWa?Fp=E1^LK}X-Geb1S@u6LJb4s(e!o(V_8orF8p0pVB=0mucXR#y>c4#w29EnH#`x|@L%s2l zXeCCJNP|{VFV|6db6MZPycZ>lw|kCR>T$7zn{}{nQ}Sa;jHQIXPmwrB}BUh zrM_rQ)pR;ivi*JhmNeK$=8Ri-#CG=-hgYI&N`%5E#CM6OXpTUW&Cp%+MGH^!@Sls- z5MNf@1UAT&yzMlc_twu&hnd{9iS*ipr$XM>jSKQ3R$|$HM&;AK;$Hmtn?`g%DnDx5 zj7pu08IoR4F~;lJT?Bvm+X`F)e^KO=FPB>;J!Ar{vI?!eO9AS@dSzmV{c>I>#xr9X zRssy(v9`O0yY##BmekNd#AkFZ0k@8G5Yg2e6&$Sd_G*~oD*v#bH|qe0C>Mo&$mg*G zV}`YjMVPFwg72Q^9OxviNC%Q5mHgNOMOSt>e)VKtLXKA}{c(Hwk?*KXh*9~@HROcW zh}S89+8Vz0N-0**sxBE9a%-Gzy-PbtkEolt&Nb)Hec3qbv_yBcsG#G4!m@ zFB!5G2piuC40?iA=4B-^3LB`l#da;>co2*XjNSLA!kZqFw;H&5e z79&v;%I5X8@n&KUw{xk9sOgUlZ4~Wj5uQ1fjv#~bfhDEaMM&@zjO*S`DN!{vf9xC<`!p z513x%N|tiZ)1_K8mf_ora`hj*?|%6vfyn| ztarB4WQTJDyf^s&Mv+m0t!vML@Oa-#a`3s5zg1uv1+vPZNP69=*hRZv@e0}~T!x4x z@}qQ+7Yzf$*JA*We2>?LWaR{z%>dqs5>=|Yxy0>Xx01n#@!khB^~Rv5n_FoD-{5Vn zG*pel^*-J5-hZ6XOOU^kO((B%BG@vvg)ZKrsC-dSGpl#+I7r;>aK8KHd{NTdn(8do z-82Csmb7(jkhfvITELTX4LHW~@Xt`$l?<{2xtU`_mzjGD>G0 zs04qf8~A}>QJ}cPJv-X;s$7~%)@DHbbV|)jVeX_;u;sIB(24buRq$hQbpR;m&D_0P<~2z>(cbP)=_G(uuWbMbr4`GzYbHFK zQ`!Q(2rvmUF^*ttA`-Eu_BnqJhqD+5MB^iLK6k-#z`X+L9>xZs@*hfZVgKG7x(O`# zt}oG=Wwp#tsA-h#j`#i{PEEIcOEkY-IjZi{MB~g_MG~nKC^)AyhVx_L;|Nx{HykT1 zCg#r=S+DkxLVHNwBKV1~o;?Dcf>(Ni+#BnuX=qppSF2VU($Q-C#Zi4^s`xzY&0g`V zg2oRx>)0$>h1q*wwwbW%ou`}DM0KO^Ak&<5yrcDTGs$8kI+aC=f(O^-bsH=%B)vus z|4bQk!sGGoj(v8y>{w%3a=}Wvb>I=;z?$ya!iVmM~0&@9)#p>y!if zMPx$sAmLOSb87Htk?@F!KSsxMnmy>j(|4`dQvzEwmh|SsGAoipd1P?!ON)R{XBtNTRa}sle0`U=#P9Q&}Omo!+~Temwns0;ys=DT){8I zxs;F${Hl(J=|CNtgU+X)5^4L{yHNpAy&SsG7@R>Fc9Nc#aFCe>^8D_1>mB9Mn2*#r z+0j^kBTG5a^rKZzvSxV+gj~Urp=mD1Xd#BskeqkOv~(@;h|88vM-K&YnOJLbLo)3K zP<6T>If6}$$!;H)K+SL~O^jO{3|m;5Si7VtngNuLRI7xx_;68te%UxbtF9XO+Y#4` zB#P)2=Y-qq!C&P5lK4D(-E(l>w>-Y+ndEAQfosghsbBqrT%WD(p3FG2aO};lIVOo^K6b-AY(%E155C?fa{_+>#L-ds@l@VD=Ja! zmLZ(e{_$j1oxzo0sG)1nQ=}^AN;D}_gZE5B3I>QyDg|R;GAE`?IiD9SFaDl)(zdB~ zKpb|pLJAyOwJt~7oaL5dEZ#HQKP{+v@nvG9-rYvGxg|-iB<)n1pj0_0_AMtGe=6%U ztAIj(T=J_|LK`WKu;r|!yka>!CvBlaiiyec9{*+EA_dYOlAO<~V&FiuCVfr)gjnCQ zChM7v>NgRGcf|hDEa%g{ZGW#^OKhQUhoyu*?e;G0yi2p947kuUWK9ztt~bqc@e7|l z@UE_2CSSB*EaA{_-D@p5$pi2+{Oi}G-#07RdZjx0pV&91SuY9P9}fHq>n*pD57$7| zJ95$2&#!UeD$aLa%sfNPsPwPJFWtb)|0v*U!;TUz=@7ZVe?^I1Szu}C%y)%}fm2e~ zx87EIZFkGS+~wBOa2J{8*^Dz0ZOt*!tvY0kI2h_w$uLp^e>pWPIx@ns*L79?=Nx<{ z7XK-Gg^kIhJ7e7<(JZ?SUeV&x0qE#(-eYIZdY_v-D%9 z=$#N4;K~3GuAdJO7#9;hUANzBCS;hk5&B==^G=E0AE>~crt}bpKp~fG17Jt4C~-vF zECp`wwFZ}s>_>p-8{(17$ES+#j3N^7Lnb_je}gLPl%;*|gyUETV*#5&_3-@RuW%!? zLt1B+l5aCb^aygS(`$``ucE)KgUh}g_W>wTz9(K|#q}5Q=g!AY_I^|p`Q5SU=qg6e zHJZVUhYF)0b17_g@OI4j@v%526`;Ad1^6`%}>3~td+AER|^MWdQyD2N5e5SNG1roPQ)JIvFp($mCrNqb2xo>D8~ z2YLfmJmH+v3aD!Gu3Cv3N}lFV`<c zC7W3&cw#9vpgb4IUm(xUGs|?9KHTV{>NU<_mnmR!`uXl zS3z&h9f9pJ&hJs`><<33Vam3db05e)M$c$x+hDSs94Y!z_olwO0{cXrTK6Oep2H)QV@o+Cp$kFaeqPNgq<6J~af=fJ z8G>!~cw)4cH&oJ8KG$iMw7HDm#}xOls?BN-e-c;S2Ym{A-9ZQ#fANnHc<2MDTfeM!)4STo}3>)`g!-Lvfh41qDk7f%-3zx+K94z z^-tAuM(2_MuYCuuzOb-RUA@QCaDBYAbs+KCz=_;6om_ZJWS~Lmk5hd5y>N;xSDjl= zOD(%u?PeT?ZfjF>g!p_o`0&$t9~76E8suJar=@{>UfQ~*6i}#QKB~_nK!>Bg;2xT$ zp)>nYE?)pR0q2QP4EzP#NhtUJDfJ8%-u9xQH!C#i^g2J>UN>0zWw?Ez=*JAp<>$d& zzKA*$ddYIu=*{%y+PXNxfCyN|-p>2LAxp}#4BBG3A_Q#S-`_?tD8m*~kTkepmT-Hp z!AHX)OQUn5;2D1Hx5`xh&71RL&FvG%{DL}3$D3uQjY^2>>X+-jOF;5Q{gbsSGVL-@ zfKSa3a2yTapdZ^bN#amF)95*_;0uPh5+IhTWttH|7mkHX>Ut)N7) zs`Fq2gBb!K*nDh}J8$!bySY7|loY#7qiIUgbwvjAYfn84d+H-$Lr7g&nD~v4`3jl=J=L4tuQx2~2m&iETmR8Fv}dR~c?*S~`g>^za4{Us%U+=sTXW3VOdZmUOUsM^b8 zsZQI5wT!!eJ5^yqMGWK$s~@sFk3;EA5;D@}7n!IBM*irD{_A}{k1br!xO5R~!mA&$ zP31MwIM{A2|MoH)R=Dxiy1_8Zp+^u|Np`QF5J12J~l2!va$2?~>bxsmO>1B<6 z|BZhkKJALbzx5Ine*PlQ%BwQidC5#F+>cX7yI=tfot@!YCqu+}i};e!D`Q|tETJ5Y z3TjGPl{{eRrr3K?)t~Pf7{$jnq1k8+0%`+}`8>~_J+wQzww6s2&7^Ezf2Xqr)P3vXs8c?!Yg`u~ z?Bnh8Krf!AVW+#WKLfQ=7_6;zbrPhex>}-J+R3P(%5Bg=VP!)X^rAw*!)$8Pdmd{lB_N|xsLv+P~34m$@GiY zd)yk`<_aCe6X3e`$!Pjg&aZ2=(SRh}v(~^y(t})6bGgMEa%OVxgi1<#U*!Ea#Y)%Y z)$AYc=0P9gKFs^z2*~1(Ij7PyT{~Jv3dTyAhnse+PDCerdzAxtH%*`n%rrKN9aPT! zT^fLjfE9aWcfbw_24fTa*HJda->v~AtjB5~n;@8?*=s)0jSD8O{*E`oN>y)Lj?o|E zB?DSLTI~&@ z3Q?TR&EWNN-7Ms~<* zv+<$Fu`$oF$g1q8S>;BH=(Lt8f?Q6%_YeGgMAIvH!jG287Y+4BRP9A-;1Zn?Hkft| z0h#g^!9SN%f$y~tte*yOlmQ0J3i~D*h1vGVY%5iJ=)QQkzUATB<=b^XC5Jo{3x#7*dgmzzpvJFp`?2ffK=8m?$%*T zxN%LVQ5jH#BT@B$yK~$CC~xvfrY%+`^B+d*z@@O0=#Oe(kU&{!pX^WV+szU3zrbWa z_05CS8Hcirxma~uy{V&TAf0I~oPEiHCvUWYVXQ^39cj%L&OggH5kuZW59&)qL1;3;$2n z{`JQ47?>|U!W}^)IPUwKed#2%C40zV$`{~Xx><%uAo$lt)CdAgdulets?1Gp&M)1k zD6_LFOccT&d}&bT|L+)8tHlNc_m+#)t00v2XV>%uZ+I4vVy*^yfyCSUB~Ksjuf7ou zT_(0;i<^o*4N13`+7|XAx@)RWJ%9~)Jt}(`S*kFxeGQFF!98^e;&OUk`jVzMTo4Z; zIf^5nPx9m*PTnlm5z%AI#arR|L|z@UvoQ#+#7osF=Ln?O;{k^p3x4rnfR4~7Ett>Y zsgPy+E2a%4Q@IIFmr^nOJA)6KxYe6@DoTV6M$|K2P%BNR>NCK9>c-Y9qPynul|XA>`P7h}F6gH%Cj z_*S|2@z3OD_DU{upq(?3`?ORb)&Jy zG;345ZesI@-{cUkm)CdY60a6GhTo!!svJiYz1MO~Ot22k@%@YeV?K8%bz2g>e~GZP z(#Uju8y0JzNF0pigHo--z+Qc$Z%^{^UjNY`k@?uBv{`B8i~sp&C5Y*r^`bB8;_-v1 znVc@CMwSpm_Ctf>E)K7^DAvMF`y&&BdidCM24H!_j8p)89RHSeKVM2NrxfE>Hb3in zr4zol0uA1iEzdN5-QUG6zrri_U2MI)T0T-EB7Y9p7V9^6YvVrcKLFin@4KIafT84E z4+EBg2)@)xFm-DQs{>?x<^9*d?x5gb6OZS7y7Vs$zv+6P0lG_@rA0kX12aw@%zoeY zPb|T7<8*+;^Z?g#-4k$G?QYg=9kulAO#ETX6`o#FCrht#e|EXbscy+$-#0#-#jvY{ z-uVxu6J>DB&KuZ_cHQ2MmgVaHPelLX)PntBJg5N#&%FyXiH84!0+9-1<6j}=R)MDq z_sYD*jS)q@#AiVjxFego4sUoDRT%9;jrdVw^>Q;jK>1RRfuS)_p_qf1->G+@QZB5Y zfbY19b;M?mr2avLY@o6b66r6xtbQS+!F2INgTbjVqJKHelpS@S-Q31Nm&3<&e@W_nU zT=oyW>sXe9c6#ej2Wm=i-1VO7>S|HlHu@z4+c2}GY`bP2x+WODp3X2N;AqpQj`2$k zcn5PH5`e}s>B~OqE1Dh~8`HPf@erY#AWZ8|REqmI6S-?%lK8To4+iTUQG16px8kgW zQx$n}1qY@oTeKqpamRVV51nzGlOE>FZX&O*8JW7o+eqBeenRStjYAGZREWE8DUQ~| zi*)|h7F>v&xV4l4hsN6aQEE)IB7-$*P-;V7cU(5p{_}jep-(~KkqNO0ApHLg7if2| z>hZyw1vL|619mlOdSil4|0PcW*;^4&#mVjd^$*aF-c`g3fE`#Rv1Hqrrl=sOWlCXA zG4!H2M->p7p+$^y;AVWrC1>XS1CUWaN$RM>Q-h(#`cE!}N;^J4Osv$WrsUwfnz9a9 z-TxaaO!`bAc%}Fj;Od{&UhZ7oRRH|f(~_Es0-c_xB9ZVYljF+9AGv~DG>TGtkh{GW`aqD+hl=Q1RCvGusW0LT7s%#M%% z>TLfnspmDtD8-ReJD1@fz<+cVtbS#eXOQ_=U9G?!5ZQi z@y5nuxStcBS;xr@(CAcyd9AIgOBw(hr8>LZX@gedV?b>G|Do`tlEl^I)R;iD|CCVc z4E%6dH!(KmZ`f}+p93J9DMggROV#}@2>EEl4Xda|Jh{XKrXPydn^+8c1P#-MwSLEj3kWt)l2lPa}j*^Qg#b(_5N|F=`% zL#OPgbc@4=6-h(BNrs{AP6?K_gfCV9sKZMSYl6Y#aV2C%*#Hh<6qBixE{` zlchO0oD5PVdn=rK;larTz+e49sd?w=P3hNAXO9W9T;3fh(E)h?h)aE>L2sP^8$+Sx z_UUnOGw~@oE>+_R-Alw^3F0A~ba~}0th%~nB;mo@_AgW0Z46br`z3YbO%yK_)R60h z9x-dem_tGww5HkTC9$?WdQ|^ki!(9ne`k+dvgasp-oJ6Jh3zbP)eIRSRIS*=@2GgU zVDs5HHSBBx`K`tSJ!}~{oa%LF9oP{2(#(mkmnoUO$-Y^&v)&#dfnb5z9&`obwO8dP zk8)o$kNG(T#m~W`PPQ0{<*NrkrL{-0UX2QH-ULC%Lve;)J(8Vg9cR23_a82#c(#>d z-88?y+Fo1n-Ax($1*h2#%JEQa4E8C&_x)V%IiGPMIs)?RUM}vgkinrEa28O@Ju2r~ zMRj0o`h>wOBKw<4+KJ4zW*M2HdDrZW*q#Ud7%EIkMSHq7<H97a?3E7l%64W1B=ILni?ro*-_>&e z7A~@DO>ZCWk1AJ1)G9uAfqa^&1(6ITlKN{C7HTcTouINosLsCl6kn-bQ-LoVj~0M$ z@7~@-plc~_m{u$Tp8RQl2qx%l{tL482)=C4qvU8&5&D!=c%$0T)D8qf$vR{JbeI(1<|2mEnU$@C1rB&7x;Ie{S zeRKpk)M=s$*xaohA_nqsu-VK{lZ_nY##etR5;r zudwK-kM}kFN@F2+Im)^mP*PnfA=%xP88~Rbi@1q+5u>J@k{Ls~+cLeN#pnvJC=t3O zwm(}gkq>~}34Wxz*83fs81in#j$-#`+f;LaQlbolcMJTT?8#xR0r2M^J+vB|m=*N# zWXoM4=+SXixR>CxsETz&PbfoV$jLX=%f7~z=tq6#F3Q)w?f1AAD8uTe&fs)w^;r3G zFS#FR2r@SIPbm;)4Q(MjT6=X~WPIj=1JJ9lUsq3gY+OiHE@Wx-PTVDRcAoUs30Z(p z>ol2s@~Yr=hJ_dPj~5Yd0`wC){7n3TQ`pDk-Ye<2Qt!M%0R~}W=LvG`fksrI)S5Kd z*`}&lbaT1~m0A@$~yPIwX(TJvBwvPvQHbJ`;von0;r*i$mMAJxP{d%!g$WR&j={m+N6|Lg?)c)(fb=|HA+sYU5HZ9?C zy@_NXgLY-AYALxgFfZ<_t2_Am7q-`zdS#5!JwfM4118_%ua-Kg3Bb9=ncak6L$nNy zPfQJTE&R5J1u@;bwT+ys3Gwh2K-Fk;Gpo_I+By{?O$wYxs`?gUI6O^4fvFTC>lrZc zZlaOgIRIKYl&gDt&E-2OpK1$ttyw+U73DlCi6njogda0hSYSiTCxAoE5oF6f1b+->49}|`NVqmqU)g!%weW||9rJ|rTz=}U_2WYt@|UZcIi!u5 zt|lf@C6d#Z)c^3X3GiVxEgKd$D8tz<`e%@a>tGC~{?N<&s(=e@c8KH_E-_b5`}^y; ztw&*WhZk4YpG}cr3bD(xjlWJCfPM^b$LXfUIjRNO4E`h9>=m&23GR9DN;XmUPhcA8 z+~-`j{GTY`TR=?&9eTNBC+xl8c0QnCe|-x=KLU~XCTH-0HK`d(^Jy4nz7g#i-fh-V z5&-07_13%lRmRtn0at?7DZJxb+33?|j^VQIj{IdqyDu7`YH$1+ZgunRTDf3zOA4@F znJ?B_yv^jheT84X$#v4O{hCTeJGBLHp5UCW`O{C4av_HQo2~AKL?@v!Jq}54{(i0X z_eo<$*;3(+vW)UtzW8L}&_nuG)Qx@v8ez*j>!mL>e%<1!O2AIBoat23PIDseYf6c- zSFz21?hd{4OAP_CewRs0b`!fk@W*-C_VA_bkcB?D4WlHh21qKUA(^+(F zz?^rEn~P7QtIxUXmH9nHs!yd&G$ubopeqqIIzd6?rmt2xwRW6G;0e;}X6^}Z{z0oW zsZmQpd*0zkN)L5GyV+w?z)k4i)1D_+y5mha1Q&BXGrgfojSR(I7X}lS{8*pJM+=_L zBjPL1KYK&VIKe!`>z?L{6WV!WtsC1^rZY4O`M&=VjIs@3jKTirGksHaZoHP8qGj?F z^CY|cK^hE}lF#SoE>CVg*k$DgEn~Up-?1z4T^RotlD_tJ!_2KL$P2WqW4cgPa6g;2 z7+~rD^Xu0B=hsEwwS)%y{x)N`H#s(YGY)ult7MftSai8-11P<`|E7^%TX2pT>Ub7W zNL1Dqf(X)2HdcqEaa2zne0udr)L=p0r%L+TuF1@Q(x<~<#DhZ1-)eF9NsY;L#JI$r zgvn0$4WLKmXiOjnWAa}bDu2M@ESPki_k+dNCl00NN%}wdH7EzLqK5SGtbPy?O4I>b zJDAfoQnSxJX3!H_(8oGK)5Il`*U{vebOjZ7W)BD`hq(htbenHh$BsbpU@oC|;pt!K}C3 zU6_v@v>RBm>$3~^AMHaE_sYnpPTa~;aS!jEF#E&e+@a2j&A7vH++qK=m{-UYjdKrk zr)R;s%G6k|ND9ego#X-9j|1XGekHAjsVVS&YlDRsAIAabzqOphR6aijZqwAro35$VbND6Ikmq=DNdqXI+~ZgCF{Bz+>GEjZMium2 zwAeUq0AvBwj%t1!X9S)m7NKZ-#WH=ES4id*p^>eu_&RvgGYa$TD(9S#nJ!|!PyO#IscP@Svd1-&9|K=1u4&ssD;RTab4p*Gpq)W@nkqr}#8i!*(l{5M`qy@K7BCBF5&2`f3 z{xtgwo0Y8-tT`&A)l-$HpIrpJAWI0vt;elwPz6oYzK|;EGcac`T#vlGAA*jX+2uu- z5y*4OE%40uKYJ&o?aQ>YpG@oaF8R>dx9bOO{=^tcPO|EZaDEqZIij5%Q)q zEFteq?*YR0sK#pO&k~FTBTZtf8Ns~xKGc6t#It&xU}1Jc|MM}~l8npH%+iixKTY8F zj&%^X$JGj(w|Vm1z{D%gk5s#eTHT;nOjR}Asw(6G#%1+HHj{pt&P2D2{H>&}E=$~& z)U(zX$-?wsx9JCKskCb~IUtW=BvJw$`!!@Up?=QIWLujM;;SXR~d)nN3l)1sD%6j7#LQ;W_{z-=M1$^yLlpBYj;s zYTq=uuK%4Lu$`8zHUN02Ck(mnhyb91`Ct^6e9K zaMZs`mf5yrPrfM`=I#0zMZD ziDMg+d?wcdBzDxf`FYd21(3RIJLMk`Guh|mn_tu7;u31?+ab)NASY)f zr60f4=m?)KMI23)mgKlt?OJcFai1NR&h<|Ur-#3`;*@yLs1f|!f@;|(!)r!^ZMkvi zi*SESIsMER+PHy0 zHs{pBCAA(l-*5@?kIi!SjYiMninSxXCTc60ee=0;ury-gvG+4?7T*SBY!Oc%Ea--; z5{&;~kqxyTcxwTiEQtM&>=B3i|?>Ty6I>ErMO+=nL( zhQ48C%W@AEnq%FoZsiVj`=;^T5nVp05P7Bmk^pgoQ|obojhB4HEwaiw51e(k!6E-Z z15F9zg#J30QGea))2g)KI8?t8K{hk$*4auQ3`n;~pumog0-kh@WR=emMPe${RXz`1 zXbNlund|N++J1QP(QA#&uF?Cs!tUJ3pbgL(%-P?g&(I z?vGJIoq$aUA1SF|R3hJ%)_ulDGT?C;Te(2_%EPD^HO8_9v41P13R;Gf zX~}T6DeFr$WI-1cLV;<`2fhpG1>j4wM2BQKP7!Dx>n6JQjDGAigrOj)x6U$J>g!6d z2HxqHDbJM=wYZNLbI-6#PXlccJ|w8w>UICtfv7(2M-Sbp2R3agm|#B*2PKapQoCpd zo)J<&w^>BE>n@ofC=Zmv1=$F;Sddj9ajf~#5?*eRW>IFW8|N{9PuWllB?jip@~2MO z_pep|AY)0V^nX>x(fXo_?ZP(5?dP%$6F$yDi;u3o#y>FjK+Dd;`c+V1nWI-Ol&^_2W0Br4%Ij<>zfece*92f>}1p(HzX54vc8opM>MmQ6ebmXgm#;;_oLsC5Rt!sg2 zmac$-vgWh7SysR}%R4)kNFI2t9qY)^fBe}qC@!mtFD`A4FyrrsS(!R?m+WsL30JYf zh+_)Pg_@@yUog1#ShRA==aKy)uVn_GD~w>t_PH|NG+6;nC>Ef{QMFWvYJm{+FmaSC zSnPoB;SOtkwhYJNpHd`u1HG!a?d%U!za(BNpBWtJV)i++jn}^b(?u1$4m9G)b{azd zq0?WJQ|?hPSfF#gP)rdgHZI;^P)NIZjk1mPf*sI*WQ+J6o*Ti6NoKwOf@R8v&Bm#0 zR+X?PzTWo^o<&$wE{nRg>i!&Rr-CdW47JBYDj)M}@j6}etV=&K+hIviN9avtNS;3| z$R|bl0hJHKHs8gjnF(e_B|zj~;_Rpq5Dr1c;9EOURo;PLTlqv(2HOXLB<4wn zZ~N{ZiFd=iczwtCW&svnCqYURtLe{%;{7DQ!>@FaoGnJS= zDkLpXV7;x8OyR)qrL?T{AZn;4gTu4SV&->T_t)PBwPg9X1D@WF{zMJ4U!!ZwVcx7l zURno>1$-IQCKQ6+^Kh1jOxS`XBv;>6HJJKGZis}pyzxu@>}zXJfb*?f5jvi!F$CBx%0%V?t<*{60*yPo8 z-wuG$6&EYw*|!@CDQR0yA?KA`cN!Zi$sjmO<>PFpB;lR3MM6x7>FQZ@`MLl41N|Vb zQcRxLn_?yB@qU>#0jDJ=%K4AjJEAuwwXcg(tQ-84iEPn;L2~%QcBu3CpEkkoPDn(I zvrg$UmW^=WV3Pkr*%$+V+|L1xZeO1pdlCWh3M+QF2DEEhjXv!X!xz7c&w*AMLzxJ^ z5za-U?~2z~w(!3zMU8pHb10&5)+&vn?R3))ys9SQib%Qf7tK4ilqj9Cgt8IU4H~Cd zYBTaM`FnMRT|B{pENH@RG_fukPf*!nAiCB6!aa;uDjOdcqPiBD_jfGEfgcY)V6Uy_w*hXBQ?yL~;zbhx0O0nB##ywp{ zb&$jV67+34gSGB)4|6K$0qObMCz?CM-@zxWSAC6^<8I|PvPcByntR{>+bF>)mxUuw ztPv}wO?2ThZvx$4CGJHmFch9hPYylVWv0D&H~Jp1Fefxf1PkQ(#p!IkbceXNqWsRp z3@+X1=t}mM2;a5)1U5<9S670X97tx+AD-Eqp>}$H@SJu%JymN=cM>>FbQCgDuA;4X zo~=%CjAk5kvz^wO$V=5kN$>1!og-^!@Ij85tMi(KSet+AVR z1JkEKp@ir$0Mc1DtG8MQq1v(_!JiU;>XSbL`a-|M;YK=YdJycnQVq&cw{px>b4aHf z<8CxcOUdVI&{gWl^zc!s^{Z_rQL$s^I$nIlrEyaAW?v)EvygDrI)0BCu`6Jr(@{n&@EJB|F> z6%$D603`FvTKIrknj#|)vBgI7V_~+HA6u@IR`z)oAMddiX-n9`RGoPja_HvVzQC^H zz;4NNZ(Osu@xLJcMb@hUcE{?&noOU{ZPvnmi;kq1B8$c}KpTsW`SUhg4tgbzy5Qm< zm2lnb<7|a9YW0w3$Or0M;wDFHqHK9gYYXX&AXNjqxyF+4*Uo+gSFW7DEK?5OVLH=l zI~IH88SdI&xd7_j4IGajN;CQwl)uQDX{nO>S5w->w?WBcb>=i+nTtB+@6XBMGMsA+ z_t0@&!aVUrngqT{6;$*5wSgT_@3{qk34qR4D1Dc}-$-H94p6B5_fGGT>pi!r+h2`D ze$IU};U+=;t9**Ot^w4x9!?Iz(k3g~QfrNH={hJhs>99yQOC%w-k3Cl#Wc_GT>9gJ zg@Dw58!2HyBs&#eCTfn?DtBr+Y2LOmPybq9j;02XF|flYa;nvxg6!6G&WQEYu2#e4 zoxpL(P}*Fh0@~Jp-g%}6NGPm>Y@e-e5C(L-Kg8kHji5|3wcJC0Iutt?6@B-lsJ^EA z4ds*jhq!hc{`i<1&|gEh8&r0T(VtPR9 z!^yHG$*%+idF?0C&5qt8&-60!{z(EBQh2E&+V{BIxb?1e5g7#ppMmvK|Zi5%#=*1pwmw6J0e_`)q!J>_;j3-I}VF|3Ck=v5+gh;#tt05 zIdS)nU0|S8Hxcrs4JuuzvP4c$pU*p=F5%A$w@=YkxbXP6y&klwa-ASQP{)d)T{lzN zVJf#PX}NNojYZHQmCB35EweBlCQwPIf{?dA1vXYke5Cx$KGW7KKkjRyC=p-?J_2iC z#CTUoJK67A2YpC{#j^md-UTppcJswib>|FZA6EW~hCjbluDp1=c$7o6@g@t3J<_)hgLJ^z2XrA6$ z_A9kvQkzSv0u;lhJ)#s)YSS#4;{&+@>pGRojSrEPQ-nc-z;aPqapOLe$Lc^h#IdG4 za|$Or_76kaJdMAZPU~=EKK!%bms|C|4|?!#9GTB0f3EwJh?5ylwtlERHx{BfQmS#1 zHVPHPio7>r%RQ-o;y{|Rcq9sBm*4gc3?0FK5&5tnDT-RicgU)u>Yx3F4LLq&@QL09 zY<;Yg1Ecd|7*>xH&g@&WAWz*j9klU(xd2GHVmL+O_CkLcBqHTu0ML@J#n2$+u~RWA z=dx6(HTaLgwE?r!w>396#w1(Gn}AaL+On!T^`#PP!qV$k(Cn3LYcvYm-k_CEE_gTq5%wfDMktmrCxY6_4b=Q z)mM_Hl3NQ?orX+oxd{vGKqr@yXjkZv^+`7M#QVM0soTD^01V}XlODihYai#)yNtog zHNY3LRIojb>vSzT$0>D^Ynt9E%)yv0;yhx|>T2rN40%K;Mu5bgazzJ7Ws`gTq@+@^ z)woch;ZC`alxS~*4hqugR%H}w#PSY1-FkiGGtereK?5k`Kk;{nT+iW62O0rUE~XzS zogm-UBedYJhWr9L-&yyZ<2eA&+1O1n# zT{Kywfo#~#`xF<9!YLmAUrpy7)zsGf{SXoey+|*iiK2jjNC#W#!@U_?zLFGsFgp0Js(n{og1jJ5A* z$pY(z8g~ticHoM~HB>j=IGb`||O_AqK4o^s(BnfNr^msX&4L36`O^!1nfhjm1IX0Erpz3$JR20H+x zh?lZKLE7jq1=ko5U+0143eBp!SzYcs{NVm>2Hjpg*lXblYEJBDq~{;2P{r|GR5ZYG zGJC!1IBn~kKp1K?x~)%R&8TC-4CaYS4;==vvvsxOj|8LKQKQTa-qaK9Jr3-)4+Y7? zhBb?G#2w<^H#+(i4}rq!4{;glGjdA!sYC>yz#NKV_SSny7jjGUD&K>WH_CR7)&PA- zwSeiZI~1O{|Awi{VH5v0x}3S)<#ABzDN}e?4`(Q|PejU?AZ!3-nG^^1=?<{@OhKMCxoD*7ub`W1Eaf>U|rV(`LRSHd!6 zyr>78L*h{z@My+P?)#Po)FTZs{mmcBcVoW|ML}EUkdfnK=b}C-3cK%)b}9@8^RwY( z(4uK4HwY(^AKC#h@tW!+aPhDlZ%X#tWgS`wz!jaH<_N@SovRf=SOJ_39Y?c?-2upY z5lwD%fO-stNCW_sBjtip z8)+MGJ~4{zl6gmW2n4f$dNgd|&B9?h)Ks?7t>)B5_X-+6PPT`C->&XDwh^~yX$LgU z1;r7Eb2E1zV*nS2o+*(RkE+X-<;=q?3cn$WAN-}6_-{Qq;J<&}lU`!>rPnEX{#M-m z7FNbu&D8;VteDF)(Wva~K47B)uA?bo`ND3@n)#KXe@9*J0Rd<&d4kaQqa@Ra_SGeVm&=UWO z%0U+}+bvT~O_%5>M6hsmP(-sI%D$x|&e=*D7@ z&(|Eic-<~^e`Rey^zr^yecq=>kHBySR?mbU95!0+d$6&3fdrws-1DzNO2T3CXpcC1 zEjgDDubHq@KK}Cnn zd?Q2Bd_JJ*#++;74S-$XyC@)TlKL*CBhT<=cbL(M_c~bp8pI2f3vGAlUCdFjTr543 zfj%fup)q53e1~Ji`{SK19ZTvR9Ba&w5(LrBQ)5CLqR^hL`mogs5LT6zS##()7Cs8u zBZA~{*|5;N*M``aLq=Ut75?NL@xIQ(^mw}+M&8Hel#ua_XCVK!c{N)dq?xRu)}uo0bG|1)xU@2$tSZPVXkhePnuYx^V)Pcrw#uLb4~Yvc}eTvA8_F zOHD^TminA6aHPD&Z{9>ly>O6la!L}IHE`bEwa|o7p zM}2R2tF+Ic{)8u6eLPi#b-JQsoZQe5+yaZD%)f^Am^(v}?Baf}0(0W4_>kuFvPnUX z)XYRu#!a*wwXChmQf-x43C|bm!M5rOxctFXXlKR^#2@lm%(2oESduWdp_!Fy$`hL85oz&1bn)Hi;GT8Wc zExWmNZ#X)H*BgbN_cH-^ipd>Suj}~#EmhPLXv)ZCnwnIm{=9l87Ikg!G@|xUlykRtn;FiQm(a=W{JGi zAAzr~Wt-xi^5k;sqAz{v{6qpF#L*ArXvg2rTZ6(g0F4HUn3}ivF>ks2^xUPO2!Wp3 z*(>GkEkbC-r%Z&uw#%?9eHB9lCa!8v=$DVIZFJiL6BF*;(=!h>k5{?eOdWjcW6jq& zT!m$S)f8K^bPHDCtgp}9d2KY(3_wIlO5ugv2xmmxuu}VjA)}4H>BGMAeQkPiE+sq$ z)m6^bpNJ&?kDgq5^fm7OzbZ7Z>7(XaCGmdLg7U<3L~7ME>5^6p4Z(HQtJ}!#+3)6) z;!q!|4{bM*^kD)QRPZbbfzeIYs^xhh@1Noyyf?xBH$p{BByyy$ITy9T9?fve}Xy!u$%Bq1Eq;@KY>7>KAKU(T^c6DedELyF3@=}cjE zQJv6Th3xHMQmfo2)jp-C?=ptoL8GdsC)=&)Ys``z>!sBVS^XJ8J%R=t*-*ykyPP}F z-I8|S4qMnzEY}P)9J`t2=oY^&KcBeY|1_!6;anJO@FBQ;9AwKM&j`w@Luu1j!@T_O zah^7l);U+vih%M=SN+Jz%%vK^*^-0jtz6kH`ujP&QA$*@6Bi&)4PAg^8r}aW3c;X$?c^msAMsFs%W-brDg{1>1yh^V3(0CPp zZH77NL!lQ+W5}B=0-UGJorlqgI0X13pQ4+d8$-22-|pVK&bArQkrO~SjcKxUyi{9~ zXO%!22(Sm5-g51V00lIWjD{`>;J4pM=k(G}1*JlVP*vBi^bY6gi5q_LF-MQaU8^RurQ;jaM z=?V-{(*D1pO_sFo`u0wRkx@Z5=*YU|ZB(6L4=W|w)f8nha44HbAH(Lt8Sny^Qy{Qg zcNsuXF4V-W)|UTVf18?mV8N_GH#NN|-#(>kvc&Oq-6AqQUcDh^u36*9+1l8}nS=MT z>##oRc=Uk5Wb3ClJ_~Ia?5)%AqS9a3slv&V?ON-ImAOCLCj{##7yH6b^WTM*tm6Lz zi=HP8mlMma+<#U9a?m-Su-u3=mx82J6T97Es9Dfl)lzZ8F z@qu(-$x)Q+~;6TOn;42Aj*T9K!qhcUC(?@|&G zn1cLu=FBUZAOAgTd7$d?WaP3!s7KG$^(`d<>6{H^qq7bhD_#sCtd8Pcn-lltn#?oJceRVK8g+QAfsG}8oR zVIN&GSUSepGAI@CH-Y&bV`fjn6Ae>+@$NFLUTrMC}z(@E7%i02UD8esgk@-+3H?40%7dYn z2YYsKe)|3-V2!W~3TL342O`#M0KBT)(z&VLpI3%fV$(qfNfS3;;8e)Njui~Wfs&e! z9)ab0qSHer^`dix(tNJ1%lYUQ_d6;zIrd!1?E<>xa53~3{~19%0EokDVG9_St8!iA zgfdYUkw|$t7RqsCNOb?egzlOT?n0w;r_ZB5Qnf0L;Ny~&;M&vblIs=2X3FFr_Vg2% z=*9qWs?v_DZO<3cGp&1-fp@&qFQ@2edn=|}lJqei(;Rm-;HD6ijhrfsoO@V>isR4+G@*D;lDdv++jdn!@A18=bEI?&9nXZg^Nvk>2wE4Gm~F< z&-$_+BD+ChmsN+Mt!)^6leY1ckluPRPVa}B$9W%K2V(R|yKP4_V0f&jV&~knEPk&P zGy1ii_zwRhwA7mxErgP<@WreYE$mk7l(z-0R|jCND}dlgrAD`O%Gf5ZsN5{FSr4d3 zD~aQLk^K5IWuN^Vl_c`&&bgOC-}6REi6d+-B1+Z6P)f{Mb=Kwpmo8V2CUn8uHP!zq zq?@e=HZh4JlJp$eD(}kx!ucZKalWLrrz<= z5$0LU#yU7Ni#{u==KG5P1440HTSjEgv; z<<1t|On*;Rq<6DE$UYCYHuMV5?dnCi{0r>ZJ^Zt2+%gJqbHE?Yj+*bhFk$*=an5PrLc<|yzGds?i)i>= zPNB=qbEl$i8@D+`Rj7RiDje%0WapxX4C4Du<7?Y5a&4ycj@BTEZSlh!w1V*Zd{5AA z2|=bdKE(>5TQbqtEtXIN$tAB7^WrXANF4A={juoon7zaA(WAWi7d>(_&3a$qr8J_l zb~Vr9O8VnEfiusG*)6#;r`mngXEm1_41R}N7s?xcJa~OBWSQu4+DxN-2obi{ka|Rl zy){{yJ3s!ApE~yMr0;Nr$@GMa5zM$&tAak`@M$+_PTtyN?=Wq-;#YW+p0d3f;w3ba z+Yoi-YW)+w__}Y^Zn+|stcrb^oDapq;EC27!yYhw`T#Z=2g99xYsS{XAuW;`)?L(O zZTu>{csv}aSFI!s2*%WXb1n_~pUe;I((uDwk3T27C?o@CXYlXW$#3cP1SWIT^cd@+ zas-p_O;rj9j5+SSmQ#h;PI-!lxxJfoHCMtXpxJX}(s?fe8jWzhC>67@YNeQFBhlwOA*--Y0W9246qZ>hR2lcf8>fs!&7#zw3|J1 zS=;R^>@$w=tDPQn5XNTrj2^jWfB51$9!NL{{072#q+5(N<1oZp`{HVClpD`uV-KDm z!}w6h7~R~3Q#k5f=IV?!MjykYV(dN^Gc44@o_Z*0Ap!KeaoBzk;N>q5jvWM`upEie z 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 nATH)veLwtP03-nP5uGvWH>rkdamage); + sgp_set_image(0, image_low_health); + draw_texture_rectangle_centered((V2) { width / 2.0f, height / 2.0f }, (V2) { width, height }); + sgp_reset_image(0); + } - // UI drawn in screen space - ui(true, dt, width, height); + // UI drawn in screen space + ui(true, dt, width, height); + } sg_pass_action pass_action = { 0 }; sg_begin_default_pass(&pass_action, (int)width, (int)height); @@ -968,7 +977,7 @@ sokol_main(int argc, char* argv[]) { bool hosting = false; if (argc > 1) { - _beginthread(server, 0, NULL); + _beginthread(server, 0, "debug_world.bin"); hosting = true; } (void)argv; diff --git a/server.c b/server.c index 8c954e1..5c1ffe9 100644 --- a/server.c +++ b/server.c @@ -5,13 +5,14 @@ #include #include // int64 printing #include +#include // error string +#include #include "minilzo.h" // started in a thread from host -void server(void* data) +void server(void* world_save_name) { - (void)data; stm_setup(); @@ -21,6 +22,36 @@ void server(void* data) initialize(&gs, entity_data, entities_size); Log("Allocated %zu bytes for entities\n", entities_size); + if (world_save_name != NULL) + { + size_t read_game_data_buffer_size = entities_size; + char* read_game_data = malloc(read_game_data_buffer_size); + + FILE* file = NULL; + fopen_s(&file, (const char*)world_save_name, "rb"); + if (file == NULL) + { + Log("Could not read from data file %s: errno %d\n", (const char*)world_save_name, errno); + } + else + { + size_t actual_length = fread(read_game_data, sizeof(char), entities_size, file); + if (actual_length <= 1) + { + Log("Could only read %zu bytes, error: errno %d\n", actual_length, errno); + exit(-1); + } + Log("Read %zu bytes from save file\n", actual_length); + ServerToClient msg = (ServerToClient){ + .cur_gs = &gs, + }; + from_bytes(&msg, read_game_data, actual_length, true, true); + fclose(file); + } + + free(read_game_data); + } + #define BOX_AT_TYPE(grid, pos, type) { Entity* box = new_entity(&gs); box_create(&gs, box, grid, pos); box->box_type = type; } #define BOX_AT(grid, pos) BOX_AT_TYPE(grid, pos, BoxHullpiece) @@ -43,12 +74,12 @@ void server(void* data) entity_set_rotation(grid, PI / 1.7f); cpBodySetVelocity(grid->body, cpv(-0.1, 0.0)); cpBodySetAngularVelocity(grid->body, 1.0f); - - BOX_AT(grid,((V2) { 0 })); - BOX_AT(grid,((V2) { BOX_SIZE, 0 })); - BOX_AT(grid,((V2) { 2.0*BOX_SIZE, 0 })); - BOX_AT(grid,((V2) { 2.0*BOX_SIZE, BOX_SIZE })); - BOX_AT(grid,((V2) { 0.0*BOX_SIZE, -BOX_SIZE })); + + BOX_AT(grid, ((V2) { 0 })); + BOX_AT(grid, ((V2) { BOX_SIZE, 0 })); + BOX_AT(grid, ((V2) { 2.0 * BOX_SIZE, 0 })); + BOX_AT(grid, ((V2) { 2.0 * BOX_SIZE, BOX_SIZE })); + BOX_AT(grid, ((V2) { 0.0 * BOX_SIZE, -BOX_SIZE })); } if (enet_initialize() != 0) @@ -81,8 +112,10 @@ void server(void* data) Log("Serving on port %d...\n", SERVER_PORT); ENetEvent event; uint64_t last_processed_time = stm_now(); + uint64_t last_saved_world_time = stm_now(); float total_time = 0.0f; size_t player_to_latest_id_processed[MAX_PLAYERS] = { 0 }; + char* world_save_buffer = malloc(entities_size); while (true) { // @Speed handle enet messages and simulate gamestate in parallel, then sync... must clone gamestate for this @@ -132,12 +165,12 @@ void server(void* data) break; } - + case ENET_EVENT_TYPE_RECEIVE: { - //Log("A packet of length %zu was received on channel %u.\n", - // event.packet->dataLength, - //event.channelID); + //Log("A packet of length %zu was received on channel %u.\n", + // event.packet->dataLength, + //event.channelID); size_t length = event.packet->dataLength; if (length != sizeof(struct ClientToServer)) @@ -195,7 +228,7 @@ void server(void* data) int player_index = (int)(int64_t)event.peer->data; Log("%" PRId64 " disconnected player index %d.\n", (int64_t)event.peer->data, player_index); Entity* player_body = get_entity(&gs, gs.players[player_index].entity); - if(player_body != NULL) + if (player_body != NULL) { entity_destroy(&gs, player_body); } @@ -220,6 +253,33 @@ void server(void* data) total_time -= TIMESTEP; } + if (world_save_name != NULL && (stm_sec(stm_diff(stm_now(), last_saved_world_time))) > TIME_BETWEEN_WORLD_SAVE) + { + last_saved_world_time = stm_now(); + ServerToClient msg = (ServerToClient){ + .cur_gs = &gs, + }; + size_t out_len = 0; + into_bytes(&msg, world_save_buffer, &out_len, entities_size, NULL, true); + FILE* save_file = NULL; + fopen_s(&save_file, (const char*)world_save_name, "wb"); + if (save_file == NULL) + { + Log("Could not open save file: errno %d\n", errno); + } + else { + size_t data_written = fwrite(world_save_buffer, sizeof(*world_save_buffer), out_len, save_file); + if (data_written != out_len) + { + Log("Failed to save world data, wanted to write %zu but could only write %zu\n", out_len, data_written); + } + else { + Log("Saved game world to %s\n", (const char*)world_save_name); + } + fclose(save_file); + } + } + if (processed) { static char lzo_working_mem[LZO1X_1_MEM_COMPRESS] = { 0 }; @@ -233,21 +293,21 @@ void server(void* data) Entity* this_player_entity = get_entity(&gs, gs.players[this_player_index].entity); if (this_player_entity == NULL) continue; // @Speed don't recreate the packet for every peer, gets expensive copying gamestate over and over again - char* bytes_buffer = malloc(sizeof *bytes_buffer * MAX_BYTES_SIZE); + char* bytes_buffer = malloc(sizeof * bytes_buffer * MAX_BYTES_SIZE); char* compressed_buffer = malloc(sizeof * compressed_buffer * MAX_BYTES_SIZE); struct ServerToClient to_send; to_send.cur_gs = &gs; to_send.your_player = this_player_index; size_t len = 0; - into_bytes(&to_send, bytes_buffer, &len, MAX_BYTES_SIZE, this_player_entity); + into_bytes(&to_send, bytes_buffer, &len, MAX_BYTES_SIZE, this_player_entity, false); if (len > MAX_BYTES_SIZE - 8) { Log("Too much data quitting!\n"); exit(-1); } - size_t compressed_len = 0; + size_t compressed_len = 0; lzo1x_1_compress(bytes_buffer, len, compressed_buffer, &compressed_len, (void*)lzo_working_mem); #ifdef LOG_GAMESTATE_SIZE @@ -268,6 +328,7 @@ void server(void* data) } } + free(world_save_buffer); destroy(&gs); free(entity_data); enet_host_destroy(server); diff --git a/server_main.c b/server_main.c index 689b8ce..d5758cd 100644 --- a/server_main.c +++ b/server_main.c @@ -5,6 +5,6 @@ int main(int argc, char **argv) { - server(0); + server("world.bin"); return 0; } diff --git a/types.h b/types.h index 8f66513..dfffdd9 100644 --- a/types.h +++ b/types.h @@ -31,6 +31,7 @@ #define EXPLOSION_RADIUS 1.0f #define EXPLOSION_DAMAGE_THRESHOLD 0.2f // how much damage until it explodes #define GOLD_UNLOCK_RADIUS 1.0f +#define TIME_BETWEEN_WORLD_SAVE 5.0f #define TIMESTEP (1.0f / 60.0f) // not required to simulate at this, but this defines what tick the game is on #define TIME_BETWEEN_INPUT_PACKETS (1.0f / 20.0f) @@ -142,6 +143,8 @@ typedef struct Entity EntityID next_free_entity; unsigned int generation; + bool no_save_to_disk; // stuff generated later on, like player's bodies or space stations that respawn. + float damage; // used by box and player cpBody* body; // used by grid, player, and box cpShape* shape; // must be a box so shape_size can be set appropriately, and serialized @@ -263,8 +266,8 @@ void destroy(struct GameState* gs); void process(struct GameState* gs, float dt); // does in place Entity* closest_to_point_in_radius(struct GameState* gs, V2 point, float radius); uint64_t tick(struct GameState* gs); -void into_bytes(struct ServerToClient* msg, char* bytes, size_t* out_len, size_t max_len, Entity* for_this_player); -void from_bytes(struct ServerToClient* gs, char* bytes, size_t max_len); +void into_bytes(struct ServerToClient* msg, char* bytes, size_t* out_len, size_t max_len, Entity* for_this_player, bool write_varnames); +void from_bytes(struct ServerToClient* msg, char* bytes, size_t max_len, bool write_varnames, bool from_disk); // entities Entity* get_entity(struct GameState* gs, EntityID id);