From 6e96ba64e805ea8a39ca46171e28426c6bc86ab6 Mon Sep 17 00:00:00 2001 From: hgn Date: Wed, 22 Nov 2023 03:43:03 +0000 Subject: [PATCH] re-add non-local gates --- entity.h | 2 +- maps_src/dev_hub/main.mdl | Bin 214144 -> 221056 bytes menu.h | 11 ++--- models_src/rs_menu.mdl | Bin 3255960 -> 3267696 bytes player.c | 47 +++++++++++++------- player.h | 1 + player_skate.c | 5 ++- player_walk.c | 14 +++++- player_walk.h | 4 ++ respawn.c | 7 +++ shaders/scene_override.fs | 3 +- shaders/scene_override.h | 7 ++- skaterift.c | 63 ++++++++++++++++---------- world_entity.c | 4 +- world_gate.c | 90 +++++++++++++++++++++++++++++++++++++- world_gate.h | 3 ++ world_load.c | 14 +++--- world_render.c | 25 ++++++++--- world_routes.c | 4 +- 19 files changed, 232 insertions(+), 72 deletions(-) diff --git a/entity.h b/entity.h index 612ad61..c3b6694 100644 --- a/entity.h +++ b/entity.h @@ -113,7 +113,7 @@ enum gate_type{ /* v102+ */ enum ent_gate_flag{ k_ent_gate_linked = 0x1, /* this is a working portal */ - k_ent_gate_nonlocal_DELETED = 0x2, /* use the key string to link this portal. + k_ent_gate_nonlocal = 0x2, /* use the key string to link this portal. NOTE: if set, it adds the flip flag. */ k_ent_gate_flip = 0x4, /* flip direction 180* for exiting portal */ k_ent_gate_custom_mesh = 0x8, /* use a custom submesh instead of default */ diff --git a/maps_src/dev_hub/main.mdl b/maps_src/dev_hub/main.mdl index 9274c3f08d193bbf3fd803eb2381610689407a8e..43fb44ef1ba799ae38c64cf889b8f4f46a3a032a 100644 GIT binary patch delta 6788 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 V=emd6yQ8e<-3vC@^I${z{2$R9k>>ya diff --git a/menu.h b/menu.h index 0a49777..c986573 100644 --- a/menu.h +++ b/menu.h @@ -246,21 +246,16 @@ static void menu_trigger_item( ent_menuitem *item ){ vg.window_should_close = 1; } - else if( MDL_CONST_PSTREQ( &menu.model, q, "reset" ) ){ - - /* FIXME: Should only be availible in CLIENT WORLD */ + else if( MDL_CONST_PSTREQ( &menu.model, q, "map" ) ){ menu_close(); respawn_begin_chooser(); - - /* FIXME: Need a back to hub button */ -#if 0 + } + else if( MDL_CONST_PSTREQ( &menu.model, q, "hub" ) ){ srinput.state = k_input_state_resume; menu_close(); ent_miniworld_goback(); -#endif } - else if( MDL_CONST_PSTREQ( &menu.model, q, "credits" ) ){ menu.credits_open = 1; } diff --git a/models_src/rs_menu.mdl b/models_src/rs_menu.mdl index eb04eb092b8b909295dbecd5c5e1885849e6c764..590edc3837cc5de6150566b6e0443d292709351b 100644 GIT binary patch delta 32912 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%0D>L7O(DUjMGj1hxVeV$*}wda*Wvy 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 aXatsUERC^{AATowav!0~?;qWu+y4RA?m#yH delta 14798 zcmeHudw5J&+xK3RjMzyA2{AhuB(WvIBu+splc_^0Xi6$ULOP%Unp$c*I}1YC$^^Y(L8CgU zFfh|5Oi4@|m!3Q$b=(wH_REzkTWZcUTKQQE^?I^};S7YeV01!Bo|>MRG%hW9#yC|} z5cY7!T56kk2to|^VS3G(5dI2lG5kzO9XkM(YJYNa#>5#=Q>iM?a#0XEKjXcfJR@DD ztDlXd0)<0v8UcPf^irozNKJBR3BsHlzKcC@f4}d5CNq*}CZ`L#cJUpW3HzHlwPpKz zIZt2>HbCohSN@&WR~+9|5Y{6P-u$uFPZYcaAsk5Lasxlt@aBTh4x+j4{Kp2quHyj@ z0B&>V^8uUd1wjwl8h5^{fv;$k>V&8AXsAX5sYzO*;~E!VS1aHQz&$!11Q_fs2;T!< z((zF)z9MTO2(w|S6JPA&C(dbEXXqp^hoN;qsz?86#D9k7g;s*l0Gi_)^KjAE^$Or$ zkeJw*_h{(rdbyV%d;s`i8$KQ|HAWCF8w8;;n12Wu2@gD=Fs~2)95C)fK}Z2y8_jP3 z9^EAfC9oVdo_oUb2cOh6v~|3rp%s9igS%rqe+%3}p9(@Sa{pjFUjvx2M-U#t$+Z*s zzX7N3tAn`{`EP)!NLn`^LC8wsEnIzF*Ok}7FVp#JfTte_g1e_6JekM0yZO3aY{-P8 z7@D0I@%5^(8xyXg-AC{7lYp7-O!!)Laxs4Z*iXlVYQVLNxi54(H)29txbbK)e*l9ni^4Ae$~)`0RSIvQ^L5<k0~lMzgcRtW z{E9bf|-+@7GZkD`PJ~}h3{$FmNnsL zn_5^a-lv&`b>e$*4dW}lMu?yEpKHyn=x%Pv?|NB0MEH+*|Ncbs>CG+jePCCiF*v%v zIqD6<5zzfYbMQR)CeNl^(g!eC-bb(3>OhO(3Ho8ojqlY5Gl^f-o0&WJk@VWe;Em=c zN#(7SvV5+?MkCNP{|Ec-yoG*VSz194}e)#eVFk*xx}n!%5kqxS}P z8P97K&%F5ERu&JeDgWTFW3Mn>t%q2>0lc=+W?$x!8R5m*NxuiYdOIKGNKQFYIDr zJ^0-&S*$;w-qpfl_|>k7tS9f&ElUlxTO#YleY#s%C|}tVbXkan zy~3yC+JRpUNz(n2k{Mo^l35(ND$v|}QFM>&=pIao?xAsU$}SqKK~ZaG6fH^v6c?0+ zC?bk0iW`bMiVmd_N@J8JC>~1DSkF82wbvHC7hXk$mpwZ^yS3w%JtgsqXE3TzwYpEK zS3JA1dsJ}6vx?oKoU5M4n7b17AJ0h|@vpzK%4vAj z6QpR;4bKpEkqT~jDk@e+-1IDDFDd9MJ$EyvA?q!)siEpyp8m{(ysA8t&}K#zh_`4b zD($V;W}AP_wpV#7_Nu0H`_TKwW}RsyF4;xKW=fIKYv?WNB{lC%4ROg%k(w(hlD^eJ zwuu&(>btRZbhuQXsC~G>9=?MN-|79ue+P~?AK9=oya7dhr|-xjDC0YQyeI`_nI9>C zgxSfi3Y~^fgV6rnEu=fG_t)ydy-uO0A%B9BPs8rdlz$ql)d?z5Q46Ytn0N|Ww>Q{} zmyq#{zN2Yr_xWKyUW95Eow&-~g9H=B+U z%JlK9867Tz6OJaSQl*@wh#&NcY!Gczt6iimM`qsmIK_5>Qp+J4h1;!^U#<_z6V&^1h(&DE7N!Ena;j%@#>f7ohb!WnO^w7t}%(MnmYA&GEKNWWRtIekapKwD~%y zK9qV>>irm#$#4w@{UMMx!_9n) zqOKvtF_du)8J$k$*Yru+&^v3w_mk;5fDC~DdcT>MX z15<^S==&Gp>u&ucd=udFxNqr`5O?V<*u6@%w=gURQEU~A87N1so{+T)(lyFw*2z>^ z1!)~c{R(p>BfDA4!m`Znl=&;P%vAm>oEk7C-TX1>s^M)6g;rxMjXRKKK0^i72(dRE zuhtW5ND05ez-`{$wC}HZ<_{_NHyCI@6~95eN9Y$}6KLRV4CSJ3pPFoqvusbvep?@} zy>u+g_7$1#!1Pc`y@SqwgKF;RC$SGH;V$?yH4|)e$a)v14-NFU4nB}&E1>GTFg=nY zeuwG%yt{QD?fe}E+Ee-Oh*(3~d-{inzxEyw2K9Y-*^grHqkCM^$D4g$U1GXMx%c%7 zdzB(;&=#k{8pzC~@*2n-y`5zn*}WpvOu7fKs-w^cNSU6}fVAJ*(nDKN!2^9Z`z~< z)BXj$J}2E{$m>7K>@}B6kM%cME0X_!-3Rte+uZ7yu$z?o2l{I7mzlQnbodXX@YkjD z&HZmI=#@ZGegWR;zv#=p=Py zk15tk>c%cnj*5!upc8lvslrK06uql@TAPiUWqzHaoWYzx8O~A?b0WKn_K~QSmSYjm z*FqzTO4Mo;J=RL`V%MY~(>(+_Q%Ptb;psGjGF_l@lXkj5sGD-$MH+?Y3SGgxLv~jwTMWXpr&;s&idR#bn>0e}_H_0ECn|B1mTEO`pF7~B#JNjm4SPq) zZzT28upGtSM76kz0zF}4r4r{UeXC)ONcMt@>*=5us5hv>OX|ra#n4k+aPs5b!A~4Ms>lR2vKvK9t*8%4Xxqs|$#2m544t>;RQ^1r(Lqu2N%- z`tS)s=AGZ>;p%ksBoiRJq$G!^!bYXKhxDgL+r34Axi3|Rg4Ke&UXg6-bJb?2^RHk; zeM{Qj$RM8Pw)q<;nbOJB8(BXKflnzF9Q1uYD($%hp*tR`z0nW$Gv9XYM78SeCwSuD zBx4v1EulEIDxt+;(30q2n3SX)j$OnqGMLcxX^JqRA?#Ib_rBR;&7w>b4E%r%#e6CR zhpi?%^pi;wHdRd8=#d2zAABc zi0rST!3+}nNQtbHQu|0t*$%4d1LYwk_eCs2K29b|h`GkN!ei>g|0Y$h&IR6jVcs)bSpICx%c>j%4Ug0gabdGRM? zhkzIjSRQ}8xCiO_W4!bQ90T=6l-3{3gi~IB%qd^|Z z)lEy*NNEHsB(H&(!5=H-1Ero$EP-@U$cjeEkCLz>zC;6uV3?=Uwjr1?exw@;bdger zN=L-G$gC~$)PWUbj7HEZjHI||q~kT*2DTAHj!I;8shrv>vzkx9hClg{2d?784L6jd;MGT_cL0+-&riL@V&4^X|6uq{${dO1N!|7iizd@5(#0WpN3o;* z3;XknWQv28wv-l!Rt91wjBik^O zf+-h}HK&84VCxW7jFJ+yC1Bp6f$?~5tfInr_;?PKQzVYYtTbVMy-TLiFrx02@oG?f zoYF?ag%y}HfmEP!j)Suq<{6bjhy6jdDpj@XF|k zWAtM(*uKYPc#YD=!@+pUSF12OJ|3bbsu_>D;6cVD_QtIUSvH33#fQTYU{Q|kCnB2zLFF&O>5%CSXH1Jq))g>Rw!Wcc-hQ>qF^La++k z^b1s*j9#e|jGG8I0x4%AdhWr!gT<9f^+ZX}v;!b4lbC{lcPpk8Dc%Wt_58_jeHk5} zjEDC<%AEpaqr+-tp^7PRJ%S?Aq~+Rh?7+XL^J(bt9n;-xCelqs1dAwSszg{3OQ&KE z-laGT6ys>I1s=rFK?@RbfvPQ#Y)f9#KpagG)6{$@+oq|D!6-UD9qUtF=(W?I$EpO* zknrlTo1$i77}fPz=1k1H7Zbshj__aPGYt^=%uC0L^CCyaS^vmU!Yp`)#LPkvj>M34 z7FHWaUX+1vOG6m@h4N>k$?xz0I6@`rt-APQvxQsr_0)DCzi0RrGS0y?RF`>m1_hFJ z4r0nBLk0$i`V?D$fj@{cGeEsX_6)dombC9+1xTZ`chFDj^W`{|yn|5bd{l!IGw0B(~oXGW8CAvDcYu@GaU zk}}_g=2I$Et8HX|7k$zit9q{%0k%G*TLdHPV*_p5$+QS#Xcd(#g4`B*tX9|xzK0}j zp~LS9EF*Clp1e({U>W@M0V4!&tumDY zGGD4$h74s=LN1*9iE`DdoUFM>?L6}O5bI+qWqgR;OL0l>a%ioh9R8177*<2*MG~R_>msL& z)i57P+B|fisD$RJo9kR!yavPacdA$er!FX7ga+|?Rr`@t#a>Y=^C6@iQXU?XL7{7* z*PhbW!v3|(Ep3)*$E{naU@b<>0xD6fT~wpW{F?&TNmcF_&!6u;xhBP?8~8)D^v_yq}i@2L7_saT!WoJ+8#JH#$#95dpo_0H&ekLMEWNM?v?Jrnqi+BDWlZ= zXm%Ur?Z+tj`EpBh`gApb()~z~(X(6l2IcX7?Bm6;>8>Hu;P(T?a8Pp7XfMv5Zl0wW z6{)v|9j4U7@K)>_AM!3097cCuQ;eTW58d!0B7cold(6M@7w1s!*V0XK+U_^Qe=3`1 zUPPHEu=hxCwBk}K0AxQZCEut^TqCM3fjh;9{P0JL_etp* z!<%gFw-_jymAz~W$#@E#wV85HVTARhic^Thwx;-%Q`bh@@)biVmUVHFbLxSqaKBbD zeJ5o(WBImzFWqKGsIUw@?55bu@Z!PVR0{0sipv!1&uYDv?3eL2d5Q9`NL5;m=dLeS z;HVM<>!=~W`0=AD=C8@{A9Pn660hNXEmME(i#W=^hJemc?KLdLmoXxy&Nyx@z)>cq z#s#I~x@tFtv^UUfiV|`|dg#QsV!S0Ky0fWD?gNQF5(g)~<2V3qM#kmd*)O1CUG9yS zv;|bN()%8^;gzerm!rzy-tpq)r|%Z4uNH?DJNL#*(+h0O^LA;E-BbNZW&KHI{Yhp0 zNoD;>W&KH|`Vgu=sjNS#tUsx&KdG!gsjNS#tUsx&KdHp~Y5hrM{Yhp0NoD;>W&KHI z{YmBjC^xz;lQT*$@EnU^$mTo4)V7a41aPVNc+9BBcbvc^hR5&+Et~*q( zijoiG`_OG~$hTR6k~c)g_g;xqF;qULRc#1V7%lsQQXc&`rQl6DTReGo{(e=U2N{RS zN9w#8CI`MmH^kJ@m5VWIn<-=*E-T{T19$hSdTCTWT*lEb8Ac$;QB*hr8F<08k9g)^ z?~yP%dGt6(L?iE(6668uR};x& zpgEdi6XE-8sz{V=VjEuK@NqU3jzz|1Q~B7JsY<~(`7$!EWG2Zi9o?v`ouKBWJyj>8 zf8V2R6X8aCvQLz=U5?Kf+znZx$&=(ju<|C!w!dldDRP1%-$znpqrA3(`(#zoJeG1-Vc5Qa2L60*a5+v4uYG&J z8ru^pd``dkPr7Nfe3QA8oQH&bMvLO$C}HhCsMfW}<<3uQ>cU$qkAvq?>t3SGT~{}EX>!4{Y5!*dQv1Q= zO2-78Psa5K>;<&0N8etciuLg20?pchQPq?RH()RfB<)5AGHsMQI!4JdO4|tOft0sV z4tDuyNt9#MeY^45z*wr!Rtu~O1)aiEYbGJc$WRO6V(Nt6Z%W`SBMR0^4wn6;`( zG|5{Li$V!o5gC3#y%nNUsA4Ouwx+0U5Sc==wn1bX6>bBsHQ7~S5NWqNh^Fm8ttojs zctMo69o^bmso5^;8{$h`-EL6(k!d%mpHsnZw0}NH>u}DWN>!$TYE|ZNO4x%uz$N?r69LNmCjxsl$X-zvh|)n>QPy$YN*epGz$VnTO^~w~h(CLD zLl{mv?NcY<$}JKnJ?A wxcam_velocity_smooth ); m4x3_mulv( gate->transport, localplayer.cam.pos, localplayer.cam.pos ); + + if( gate->flags & k_ent_gate_nonlocal ){ + /* FIXME: Code dupe with world_load.c */ + ent_spawn *rp = world_find_spawn_by_name( world, "start" ); + if( !rp ) rp = world_find_closest_spawn( world, (v3f){0.0f,0.0f,0.0f} ); + /* TODO: fallback to searching for a safe location using raycasts */ + assert(rp); + v3_copy( rp->transform.co, world->player_co ); + + world_static.active_instance = gate->target; + player__clean_refs(); + } v3f v0; v3_angles_vector( localplayer.angles, v0 ); @@ -221,25 +233,10 @@ static void player__setpos( v3f pos ){ rb_update_transform( &localplayer.rb ); } -static void player__reset(void){ +static void player__clean_refs(void){ replay_clear( &skaterift.replay ); gui_helper_clear(); - v3_zero( localplayer.rb.v ); - v3_zero( localplayer.rb.w ); - - f32 l = v4_length( localplayer.rb.q ); - if( (l < 0.9f) || (l > 1.1f) ) - q_identity( localplayer.rb.q ); - - rb_update_transform( &localplayer.rb ); - - localplayer.subsystem = k_player_subsystem_walk; - player__walk_reset(); - - localplayer.immobile = 0; - localplayer.gate_waiting = NULL; - world_static.challenge_target = NULL; world_static.challenge_timer = 0.0f; world_static.focused_entity = 0; @@ -255,8 +252,26 @@ static void player__reset(void){ world_routes_clear( instance ); } } +} + +static void player__reset(void){ + v3_zero( localplayer.rb.v ); + v3_zero( localplayer.rb.w ); + + f32 l = v4_length( localplayer.rb.q ); + if( (l < 0.9f) || (l > 1.1f) ) + q_identity( localplayer.rb.q ); + + rb_update_transform( &localplayer.rb ); + + localplayer.subsystem = k_player_subsystem_walk; + player__walk_reset(); + + localplayer.immobile = 0; + localplayer.gate_waiting = NULL; v3_copy( localplayer.rb.co, localplayer.cam_control.tpv_lpf ); + player__clean_refs(); } static void player__spawn( ent_spawn *rp ){ diff --git a/player.h b/player.h index 63cd302..939033a 100644 --- a/player.h +++ b/player.h @@ -192,6 +192,7 @@ static void player__pass_gate( u32 id ); static void player__im_gui(void); static void player__setpos( v3f pos ); static void player__spawn( ent_spawn *rp ); +static void player__clean_refs(void); static void player__reset(void); static void player__kill(void); static void player__begin_holdout( v3f offset ); diff --git a/player_skate.c b/player_skate.c index 522ea30..63315a8 100644 --- a/player_skate.c +++ b/player_skate.c @@ -483,6 +483,9 @@ static void player__approximate_best_trajectory(void){ m4x3_mulv( gate->transport, co1, co1 ); m3x3_mulv( gate->transport, launch_v, launch_v); m4x3_mulv( gate->transport, launch_co, launch_co ); + + if( gate->flags & k_ent_gate_nonlocal ) + trace_world = &world_static.instances[ gate->target ]; } } @@ -2025,11 +2028,9 @@ static void player__skate_update(void){ if( world->water.enabled ){ if( localplayer.rb.co[1]+0.25f < world->water.height ){ -#if 0 player__networked_sfx( k_player_subsystem_walk, 32, k_player_walk_soundeffect_splash, localplayer.rb.co, 1.0f ); -#endif player__skate_kill_audio(); player__dead_transition(); return; diff --git a/player_walk.c b/player_walk.c index e269166..12d0706 100644 --- a/player_walk.c +++ b/player_walk.c @@ -432,7 +432,9 @@ static void player__walk_update(void){ if( world->water.enabled ){ if( localplayer.rb.co[1]+0.4f < world->water.height ){ - audio_oneshot_3d( &audio_splash, localplayer.rb.co, 40.0f, 1.0f ); + player__networked_sfx( k_player_subsystem_walk, 32, + k_player_walk_soundeffect_splash, + localplayer.rb.co, 1.0f ); player__dead_transition(); return; } @@ -1064,4 +1066,14 @@ static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){ &animator->pitch ); } } + +static void player__walk_sfx_oneshot( u8 id, v3f pos, f32 volume ){ + audio_lock(); + + if( id == k_player_walk_soundeffect_splash ){ + audio_oneshot_3d( &audio_splash, pos, 40.0f, 1.0f ); + } + + audio_unlock(); +} #endif /* PLAYER_DEVICE_WALK_H */ diff --git a/player_walk.h b/player_walk.h index 7d3c0eb..28e38a4 100644 --- a/player_walk.h +++ b/player_walk.h @@ -75,6 +75,10 @@ struct player_walk{ } static player_walk; +enum player_walk_soundeffect { + k_player_walk_soundeffect_splash +}; + static f32 k_walkspeed = 10.0f, k_airspeed = 1.2f, diff --git a/respawn.c b/respawn.c index b023520..d8c470a 100644 --- a/respawn.c +++ b/respawn.c @@ -190,6 +190,13 @@ static void respawn_chooser_pre_update(void){ } } + for( u32 i=0; ient_gate); i++ ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, i ); + if( gate->flags & k_ent_gate_nonlocal ){ + respawn_map_draw_icon( cam, k_gui_icon_rift, gate->co[0] ); + } + } + for( u32 i=0; ient_route); i++ ){ ent_route *route = mdl_arritm( &world->ent_route, i ); diff --git a/shaders/scene_override.fs b/shaders/scene_override.fs index 2ab8d8d..237fe6b 100644 --- a/shaders/scene_override.fs +++ b/shaders/scene_override.fs @@ -70,10 +70,9 @@ void main(){ if( uIsoAmt > 0.0 ){ float height = fract( aCo.y * 0.1 ); float lg = 2.0*length(vec2(dFdx(height), dFdy(height))); - vfrag *= 1.0f+(lg*0.4*uIsoAmt); + vfrag *= 1.0f+(lg*0.2*uIsoAmt); } - oColour = vec4( vfrag, 1.0 ); //oColour = vec4( vfrag, 1.0 ); } diff --git a/shaders/scene_override.h b/shaders/scene_override.h index b457233..74caeff 100644 --- a/shaders/scene_override.h +++ b/shaders/scene_override.h @@ -516,13 +516,16 @@ static struct vg_shader _shader_scene_override = { " float d3 = distance(p0,aCo);\n" " emit += vec3(fract(t*0.2-g_realtime+d3*0.2)*max(0.0,1.0-d3*0.2));\n" "\n" +" vfrag += emit;\n" +"\n" " if( uIsoAmt > 0.0 ){\n" " float height = fract( aCo.y * 0.1 );\n" " float lg = 2.0*length(vec2(dFdx(height), dFdy(height)));\n" -" emit += vec3(lg*0.1*uIsoAmt);\n" +" vfrag *= 1.0f+(lg*0.4*uIsoAmt);\n" " }\n" "\n" -" oColour = vec4( vfrag+emit, 1.0 );\n" +"\n" +" oColour = vec4( vfrag, 1.0 );\n" " //oColour = vec4( vfrag, 1.0 );\n" "}\n" ""}, diff --git a/skaterift.c b/skaterift.c index 7da7109..326e02c 100644 --- a/skaterift.c +++ b/skaterift.c @@ -443,6 +443,16 @@ static void render_player_transparent(void){ player__render( &small_cam ); } +static world_instance *get_view_world(void){ + world_instance *view_world = world_current_instance(); + if( localplayer.gate_waiting && + (localplayer.gate_waiting->flags & k_ent_gate_nonlocal) ){ + view_world = &world_static.instances[world_static.active_instance ^ 0x1]; + } + + return view_world; +} + static void render_scene(void){ /* Draw world */ glEnable( GL_DEPTH_TEST ); @@ -481,7 +491,14 @@ static void render_scene(void){ return; } - render_world( world_current_instance(), &skaterift.cam, 0, 0, 1, 1 ); + world_instance *view_world = get_view_world(); + render_world( view_world, &skaterift.cam, 0, 0, 1, 1 ); + + /* + * render transition + */ + if( global_miniworld.transition == 0 ) + return; world_instance *holdout_world = NULL; f32 t = 0.0f; @@ -490,32 +507,28 @@ static void render_scene(void){ holdout_world = &world_static.instances[ k_world_purpose_hub ]; t = global_miniworld.t; } - else if( global_miniworld.transition == -1 ){ + else{ holdout_world = &world_static.instances[ k_world_purpose_client ]; t = 1.0f-global_miniworld.t; } - else { - } - if( holdout_world ){ - if( holdout_world->status != k_world_status_loaded ) - return; + if( holdout_world->status != k_world_status_loaded ) + return; - t = vg_smoothstepf( t ); + t = vg_smoothstepf( t ); - glEnable( GL_STENCIL_TEST ); - glDisable( GL_DEPTH_TEST ); - glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); - glStencilFunc( GL_ALWAYS, 1, 0xFF ); - glStencilMask( 0xFF ); + glEnable( GL_STENCIL_TEST ); + glDisable( GL_DEPTH_TEST ); + glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); + glStencilFunc( GL_ALWAYS, 1, 0xFF ); + glStencilMask( 0xFF ); - shader_blit_transition_use(); - shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} ); - shader_blit_transition_uT( -(sqrtf(2)+0.5f) * t ); + shader_blit_transition_use(); + shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} ); + shader_blit_transition_uT( -(sqrtf(2)+0.5f) * t ); - render_fsquad(); - render_world( holdout_world, &global_miniworld.cam, 1, 0, 1, 1 ); - } + render_fsquad(); + render_world( holdout_world, &global_miniworld.cam, 1, 0, 1, 1 ); } static void skaterift_composite_maincamera(void){ @@ -569,8 +582,14 @@ static void render_main_game(void){ skaterift_composite_maincamera(); /* --------------------------------------------------------------------- */ - if( skaterift.activity != k_skaterift_respawning ) - render_world_cubemaps( world_current_instance() ); + if( skaterift.activity != k_skaterift_respawning ){ + world_instance *world = world_current_instance(); + render_world_cubemaps( world ); + + ent_gate *nlg = world->rendering_gate; + if( nlg && nlg->flags & k_ent_gate_nonlocal ) + render_world_cubemaps( &world_static.instances[nlg->target] ); + } /* variable res target */ render_fb_bind( gpipeline.fb_main, 1 ); @@ -592,7 +611,7 @@ static void render_main_game(void){ if( !global_miniworld.transition && (skaterift.activity != k_skaterift_respawning) ){ render_fb_bind( gpipeline.fb_main, 1 ); - render_world_gates( world_current_instance(), &skaterift.cam ); + render_world_gates( get_view_world(), &skaterift.cam ); } /* composite */ diff --git a/world_entity.c b/world_entity.c index 47b846c..2ba975b 100644 --- a/world_entity.c +++ b/world_entity.c @@ -118,10 +118,12 @@ static void world_gen_entities_init( world_instance *world ){ for( u32 j=0; jent_gate); j ++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - if( !(gate->flags & k_ent_gate_nonlocal_DELETED) ) { + if( !(gate->flags & k_ent_gate_nonlocal) ) { gate_transform_update( gate ); } } + + vg_async_call( world_link_nonlocal_async, world, 0 ); /* water */ for( u32 j=0; jent_water); j++ ){ diff --git a/world_gate.c b/world_gate.c index accdc06..be339cf 100644 --- a/world_gate.c +++ b/world_gate.c @@ -250,8 +250,11 @@ static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last ){ if( !(gate->flags & k_ent_gate_linked) ) continue; if( gate->flags & k_ent_gate_locked ) continue; - if( gate->flags & k_ent_gate_nonlocal_DELETED ) - continue; + if( gate->flags & k_ent_gate_nonlocal ){ + if( world_static.instances[gate->target].status + != k_world_status_loaded ) + continue; + } if( gate_intersect( gate, pos, last ) ) return mdl_entity_id( k_ent_gate, i ); @@ -273,4 +276,87 @@ static void ent_gate_call( world_instance *world, ent_call *call ){ } } + +/* + * detatches any nonlocal gates + */ +static void world_unlink_nonlocal( world_instance *world ){ + for( u32 j=0; jent_gate); j ++ ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, j ); + + if( gate->flags & k_ent_gate_nonlocal ){ + gate->flags &= ~k_ent_gate_linked; + } + } +} + +/* + * attatches nonlocal gates, to be called from main thread ONLY! + */ +static void world_link_nonlocal_async( void *payload, u32 size ){ + world_instance *world = payload; + u32 world_id = world - world_static.instances; + + for( u32 j=0; jent_gate); j ++ ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, j ); + + if( !(gate->flags & k_ent_gate_nonlocal) ) continue; + if( gate->flags & k_ent_gate_linked ) continue; + + const char *key = mdl_pstr( &world->meta, gate->key ); + vg_info( "key: %s\n", key ); + + for( u32 i=0; istatus != k_world_status_loaded ) continue; + vg_info( "Checking world %u for key matches\n", i ); + + for( u32 k=0; kent_gate ); k++ ){ + ent_gate *gate2 = mdl_arritm( &other->ent_gate, k ); + + if( !(gate2->flags & k_ent_gate_nonlocal) ) continue; + if( gate2->flags & k_ent_gate_linked ) continue; + + const char *key2 = mdl_pstr( &other->meta, gate2->key ); + vg_info( " key2: %s\n", key2 ); + + if( strcmp( key, key2 ) ) continue; + + vg_success( "Non-local matching pair '%s' found. (%u:%u)\n", + key, world_id, i ); + + gate->flags |= k_ent_gate_linked; + gate2->flags |= k_ent_gate_linked; + gate->target = i; + gate2->target = world_id; + + v3_copy( gate->co[0], gate2->co[1] ); + v3_copy( gate2->co[0], gate->co[1] ); + v4_copy( gate->q[0], gate2->q[1] ); + v4_copy( gate2->q[0], gate->q[1] ); + + if( world->meta.info.version < 102 ){ + /* LEGACY BEHAVIOUR: v101 + * this would flip both the client worlds portal's entrance and + * exit. effectively the clients portal would be the opposite + * to the hub worlds one. new behaviour is to just flip the + * destinations so the rules are consistent in each world. + */ + v4f qflip; + q_axis_angle( qflip, (v3f){0.0f,1.0f,0.0f}, VG_PIf ); + q_mul( gate->q[0], qflip, gate->q[0] ); + q_mul( gate->q[1], qflip, gate->q[1] ); + q_mul( gate2->q[1], qflip, gate2->q[1] ); + } + + gate_transform_update( gate ); + gate_transform_update( gate2 ); + + goto matched; + } + } matched:; + } +} + #endif /* WORLD_GATE_C */ diff --git a/world_gate.h b/world_gate.h index 2201f76..f1b4f02 100644 --- a/world_gate.h +++ b/world_gate.h @@ -29,4 +29,7 @@ static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last ); static void ent_gate_call( world_instance *world, ent_call *call ); static void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl ); +static void world_link_nonlocal_async( void *payload, u32 size ); +static void world_unlink_nonlocal( world_instance *world ); + #endif /* WORLD_GATE_H */ diff --git a/world_load.c b/world_load.c index e2c2bb3..78bd332 100644 --- a/world_load.c +++ b/world_load.c @@ -300,19 +300,19 @@ static void skaterift_change_world_start( addon_reg *reg ){ vg_linear_clear( vg_mem.scratch ); /* ?? */ vg_info( "unloading old worlds\n" ); - - for( u32 i=1; istatus == k_world_status_loaded ){ - inst->status = k_world_status_unloading; - world_fadeout_audio( inst ); - } + world_instance *client_world = + &world_static.instances[ k_world_purpose_client ]; + + if( client_world->status == k_world_status_loaded ){ + client_world->status = k_world_status_unloading; + world_fadeout_audio( client_world ); } world_static.instance_addons[ k_world_purpose_client ] = reg; network_send_item( k_netmsg_playeritem_world1 ); relink_all_remote_player_worlds(); + world_unlink_nonlocal( &world_static.instances[k_world_purpose_hub] ); } } diff --git a/world_render.c b/world_render.c index 1546429..281a6e7 100644 --- a/world_render.c +++ b/world_render.c @@ -763,10 +763,6 @@ static void render_world_gates( world_instance *world, camera *cam ){ for( u32 i=0; ient_gate); i++ ){ ent_gate *gi = mdl_arritm( &world->ent_gate, i ); - if( !(gi->flags & (k_ent_gate_linked|k_ent_gate_nonlocal_DELETED| - k_ent_gate_locked)) ) - continue; - float dist = v3_dist2( gi->co[0], cam->transform[3] ); vg_line_point( gi->co[0], 0.25f, VG__BLUE ); @@ -778,8 +774,25 @@ static void render_world_gates( world_instance *world, camera *cam ){ } world->rendering_gate = gate; - if( gate ) - render_gate( world, world, gate, cam ); + + if( gate ){ + if( gate->flags & k_ent_gate_locked ){ + world->rendering_gate = NULL; + return; + } + + if( gate->flags & k_ent_gate_nonlocal ){ + if( world_static.load_state != k_world_loader_none ){ + world->rendering_gate = NULL; + return; + } + + world_instance *dest_world = &world_static.instances[ gate->target ]; + render_gate( world, dest_world, gate, cam ); + } + else + render_gate( world, world, gate, cam ); + } } static void world_prerender( world_instance *world ){ diff --git a/world_routes.c b/world_routes.c index 5f6d283..33d84db 100644 --- a/world_routes.c +++ b/world_routes.c @@ -541,7 +541,7 @@ static void world_gen_routes_ent_init( world_instance *world ){ } if( (gate->flags & k_ent_gate_linked) & - !(gate->flags & k_ent_gate_nonlocal_DELETED) ){ + !(gate->flags & k_ent_gate_nonlocal) ){ gate = mdl_arritm(&world->ent_gate, gate->target ); for( u32 k=0; k<4; k++ ){ @@ -994,7 +994,7 @@ static void render_world_routes( world_instance *world, for( u32 j=0; jent_gate); j ++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - if( !(gate->flags & k_ent_gate_nonlocal_DELETED) ) + if( !(gate->flags & k_ent_gate_nonlocal) ) render_gate_markers( mmdl, i, gate ); } } -- 2.25.1