From 5d833f6a0952c686a6b5b12efc766c9bc50f47f7 Mon Sep 17 00:00:00 2001 From: hgn Date: Tue, 11 Feb 2025 16:45:01 +0000 Subject: [PATCH] a different way of doing non-local links --- content_skaterift/maps/dev_heaven/main.mdl | Bin 897520 -> 897528 bytes skaterift_blender/sr_main.py | 18 ++++- skaterift_blender/sr_mdl.py | 6 +- src/entity.h | 9 ++- src/player.c | 81 +++++++++++++------- src/player.h | 2 + src/player_skate.c | 45 ++++++----- src/player_skate.h | 1 + src/player_walk.c | 25 +++--- src/player_walk.h | 1 + src/world.h | 5 ++ src/world_gate.c | 85 +++++++++++++++++++++ src/world_load.c | 32 ++++++-- src/world_render.c | 10 +++ src/world_routes.c | 25 ++++-- 15 files changed, 266 insertions(+), 79 deletions(-) diff --git a/content_skaterift/maps/dev_heaven/main.mdl b/content_skaterift/maps/dev_heaven/main.mdl index 6aadd05397506cb594eb2261b3ac9e26b02bc616..2adad981918fe04d61a849b16bdfa286b61e54c8 100644 GIT binary patch delta 328 zcmezH*zCt+vk5AaE^G`8j0_A6#U(|VdFjPK76c?rw3TKwm>4N78z9HPzz!6Y0OH(~ zocP?tlGLKi#2k>i9}_1^Gipp+E6o@&@uakDg**d;08qFAh*R@Q;&U?7GfIGL5U7~U z$SBRYVX`cc^q6ePC@nif17bA`P!^;*IXO24tQ1Hrm|O@{cVKcakeo4jB~Z173MT_c z1Oo#|HOLv6c`2F6sSx!ZlOF=rMQr}dXw9Ztx17VjxX8f3NH-@xIWb2!CABO*qcn-( zTYsVe(3gqj469bH+8oM}tib68)UE&w0E^~>8tn%)7=f4xh?#+y1&CRJm<@>8ftUk` TIf0l9h`E87XZt}7Uj0r0C#qMP delta 320 zcmezI*zCh&vk5Aa4r~kzj0_A6#U(|VdFjPK76e30w3TMmm>4N7>mkR$zz!6Y0OH(~ zocP?tlGLKi#2k>i4-+R!Gb&76E6o@%@uakDfjk3)08qFAh*R@Q;&U?7GfIGL5Ga_; z$SBRYVzMldbeL?(C@nid17bA`P!^;*IXO24tQ1Jhm|O@{w_|cIkeo1iB~Z133MT_c z1Oo#|HOLv6c`2F6sSx!JlOF=r1#JGyXw4>j`P95O#YF}NM!Grq$%#3-DXC@gC8Z_# zU^j1$tpv_lpf, cc->tpv_lpf ); + m3x3_mulv( transport, cc->cam_velocity_smooth, cc->cam_velocity_smooth ); + m4x3_mulv( transport, localplayer.cam.pos, localplayer.cam.pos ); + + v3f v0; + v3_angles_vector( localplayer.angles, v0 ); + m3x3_mulv( transport, v0, v0 ); + v3_angles( v0, localplayer.angles ); + + if( player_subsystems[ localplayer.subsystem ]->transport ) + player_subsystems[ localplayer.subsystem ]->transport( transport ); + else + vg_warn( "Player passed gate, but subsystem(%d) doesn't have a transport function.\n", localplayer.subsystem ); +} + /* * Applies gate transport to a player_interface */ void player__pass_gate( u32 id ) { - world_instance *world = &_world.main; - skaterift_record_frame( &player_replay.local, 1 ); + audio_lock(); + audio_oneshot( &audio_gate_pass, 1.0f, 0.0f ); + audio_unlock(); - /* update boundary hash (network animation) */ - u16 index = mdl_entity_id_id(id) & ~NETMSG_BOUNDARY_MASK; - localplayer.boundary_hash ^= NETMSG_GATE_BOUNDARY_BIT; - localplayer.boundary_hash &= ~NETMSG_BOUNDARY_MASK; - localplayer.boundary_hash |= index; - + world_instance *world = &_world.main; ent_gate *gate = af_arritm( &world->ent_gate, mdl_entity_id_id(id) ); - world_routes_fracture( world, gate, localplayer.rb.co, localplayer.rb.v ); - localplayer.gate_waiting = gate; - localplayer.deferred_frame_record = 1; + if( gate->flags & k_ent_gate_nonlocal ) + { + _world.travelled_through_nonlocal_gate = 1; + _world.copy_of_nonlocal_sender = *gate; + _world.copy_of_nonlocal_sender.target = 0; + _world.copy_of_nonlocal_sender.key = 0; + _world.copy_of_nonlocal_sender.submesh_start = 0; + _world.copy_of_nonlocal_sender.submesh_count = 0; + + vg_strncpy( af_str( &world->meta.af, gate->key ), + _world.nonlocal_destination_key, 32, + k_strncpy_overflow_fatal ); + + addon_reg *reg = get_addon_from_index( k_addon_type_world, gate->addon_reg, 0 ); + skaterift_switch_world_start( reg ); + return; + } + else + { + player__transport( gate->transport ); - struct player_cam_controller *cc = &localplayer.cam_control; - m4x3_mulv( gate->transport, cc->tpv_lpf, cc->tpv_lpf ); - m3x3_mulv( gate->transport, cc->cam_velocity_smooth, - cc->cam_velocity_smooth ); + skaterift_record_frame( &player_replay.local, 1 ); - m4x3_mulv( gate->transport, localplayer.cam.pos, localplayer.cam.pos ); + /* update boundary hash (network animation) */ + u16 index = mdl_entity_id_id(id) & ~NETMSG_BOUNDARY_MASK; + localplayer.boundary_hash ^= NETMSG_GATE_BOUNDARY_BIT; + localplayer.boundary_hash &= ~NETMSG_BOUNDARY_MASK; + localplayer.boundary_hash |= index; - if( gate->flags & k_ent_gate_nonlocal ) - vg_error( "Nonlocal gates are deprecated!\n" ); - else - world_routes_activate_entry_gate( world, gate ); - - v3f v0; - v3_angles_vector( localplayer.angles, v0 ); - m3x3_mulv( gate->transport, v0, v0 ); - v3_angles( v0, localplayer.angles ); + localplayer.gate_waiting = gate; + localplayer.deferred_frame_record = 1; - audio_lock(); - audio_oneshot( &audio_gate_pass, 1.0f, 0.0f ); - audio_unlock(); + world_routes_fracture( world, gate, localplayer.rb.co, localplayer.rb.v ); + world_routes_activate_entry_gate( world, gate ); + } } void player_apply_transport_to_cam( m4x3f transport ) diff --git a/src/player.h b/src/player.h index c7ded0f..6b10f65 100644 --- a/src/player.h +++ b/src/player.h @@ -47,6 +47,7 @@ struct player_subsystem_interface void(*sfx_comp)(void *animator); void(*sfx_kill)(void); + void(*transport)( m4x3f transport ); void *animator_data; u32 animator_size; @@ -179,6 +180,7 @@ void player__update(void); void player__post_update(void); void player__pass_gate( u32 id ); +void player__transport( m4x3f transport ); void player__im_gui( ui_context *ctx ); void player__setpos( v3f pos ); void player__spawn( ent_spawn *rp ); diff --git a/src/player_skate.c b/src/player_skate.c index e408b5f..c75b7cc 100644 --- a/src/player_skate.c +++ b/src/player_skate.c @@ -23,6 +23,7 @@ struct player_subsystem_interface player_subsystem_skate = .bind = player__skate_bind, .pre_update = player__skate_pre_update, .update = player__skate_update, + .transport = player__skate_transport, .post_update = player__skate_post_update, .im_gui = player__skate_im_gui, .animate = player__skate_animate, @@ -2222,7 +2223,8 @@ static enum skate_activity skate_availible_grind(void){ return new_activity; } -void player__skate_update(void){ +void player__skate_update(void) +{ struct player_skate_state *state = &player_skate.state; world_instance *world = &_world.main; @@ -2709,26 +2711,9 @@ begin_collision:; u32 id = world_intersect_gates( world, localplayer.rb.co, state->prev_pos ); - if( id ){ + if( id ) + { ent_gate *gate = af_arritm( &world->ent_gate, mdl_entity_id_id(id) ); - - m4x3_mulv( gate->transport, localplayer.rb.co, localplayer.rb.co ); - m3x3_mulv( gate->transport, localplayer.rb.v, localplayer.rb.v ); - m4x3_mulv( gate->transport, state->cog, state->cog ); - m3x3_mulv( gate->transport, state->cog_v, state->cog_v ); - m3x3_mulv( gate->transport, state->throw_v, state->throw_v ); - m3x3_mulv( gate->transport, state->head_position, - state->head_position ); - m3x3_mulv( gate->transport, state->up_dir, state->up_dir ); - - v4f transport_rotation; - m3x3_q( gate->transport, transport_rotation ); - q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q ); - q_mul( transport_rotation, state->smoothed_rotation, - state->smoothed_rotation ); - q_normalize( localplayer.rb.q ); - q_normalize( state->smoothed_rotation ); - rb_update_matrices( &localplayer.rb ); player__pass_gate( id ); } @@ -2791,6 +2776,26 @@ begin_collision:; } } +void player__skate_transport( m4x3f transport ) +{ + struct player_skate_state *state = &player_skate.state; + m4x3_mulv( transport, localplayer.rb.co, localplayer.rb.co ); + m3x3_mulv( transport, localplayer.rb.v, localplayer.rb.v ); + m4x3_mulv( transport, state->cog, state->cog ); + m3x3_mulv( transport, state->cog_v, state->cog_v ); + m3x3_mulv( transport, state->throw_v, state->throw_v ); + m3x3_mulv( transport, state->head_position, state->head_position ); + m3x3_mulv( transport, state->up_dir, state->up_dir ); + + v4f transport_rotation; + m3x3_q( transport, transport_rotation ); + q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q ); + q_mul( transport_rotation, state->smoothed_rotation, state->smoothed_rotation ); + q_normalize( localplayer.rb.q ); + q_normalize( state->smoothed_rotation ); + rb_update_matrices( &localplayer.rb ); +} + void player__skate_im_gui( ui_context *ctx ) { struct player_skate_state *state = &player_skate.state; diff --git a/src/player_skate.h b/src/player_skate.h index c234bdc..338658c 100644 --- a/src/player_skate.h +++ b/src/player_skate.h @@ -307,6 +307,7 @@ static void player__skate_register(void) void player__skate_bind (void); void player__skate_pre_update (void); void player__skate_update (void); +void player__skate_transport( m4x3f transport ); void player__skate_post_update (void); void player__skate_im_gui ( ui_context *ctx ); void player__skate_animate (void); diff --git a/src/player_walk.c b/src/player_walk.c index 2c78bb8..4a19079 100644 --- a/src/player_walk.c +++ b/src/player_walk.c @@ -16,6 +16,7 @@ struct player_subsystem_interface player_subsystem_walk = .bind = player__walk_bind, .pre_update = player__walk_pre_update, .update = player__walk_update, + .transport = player__walk_transport, .post_update = player__walk_post_update, .im_gui = player__walk_im_gui, .animate = player__walk_animate, @@ -671,16 +672,9 @@ static void player_walk_update_generic(void){ } u32 id = world_intersect_gates(world, localplayer.rb.co, w->state.prev_pos); - if( id ){ + if( id ) + { ent_gate *gate = af_arritm( &world->ent_gate, mdl_entity_id_id(id) ); - m4x3_mulv( gate->transport, localplayer.rb.co, localplayer.rb.co ); - m3x3_mulv( gate->transport, localplayer.rb.v, localplayer.rb.v ); - - v4f transport_rotation; - m3x3_q( gate->transport, transport_rotation ); - q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q ); - q_normalize( localplayer.rb.q ); - rb_update_matrices( &localplayer.rb ); player__pass_gate( id ); } rb_update_matrices( &localplayer.rb ); @@ -696,6 +690,19 @@ static void player_walk_update_generic(void){ k_runspeed ); } +void player__walk_transport( m4x3f transport ) +{ + m4x3_mulv( transport, localplayer.rb.co, localplayer.rb.co ); + m3x3_mulv( transport, localplayer.rb.v, localplayer.rb.v ); + + v4f transport_rotation; + m3x3_q( transport, transport_rotation ); + q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q ); + q_normalize( localplayer.rb.q ); + rb_update_matrices( &localplayer.rb ); +} + + void player__walk_post_update(void){ struct player_walk *w = &player_walk; diff --git a/src/player_walk.h b/src/player_walk.h index 56b8914..b740a8c 100644 --- a/src/player_walk.h +++ b/src/player_walk.h @@ -100,6 +100,7 @@ static void player__walk_register(void) void player__walk_pre_update (void); void player__walk_update (void); +void player__walk_transport ( m4x3f transport ); void player__walk_post_update (void); void player__walk_animate (void); void player__walk_pose (void *animator, player_pose *pose); diff --git a/src/world.h b/src/world.h index 5576fb6..662a3dd 100644 --- a/src/world.h +++ b/src/world.h @@ -235,6 +235,11 @@ struct world_static world_instance main; addon_reg *default_hub_addon, *switch_to_addon; + addon_reg *previous_world_addon; + char nonlocal_destination_key[32]; + bool travelled_through_nonlocal_gate; + ent_gate copy_of_nonlocal_sender; + enum world_loader_state { k_world_loader_none, diff --git a/src/world_gate.c b/src/world_gate.c index fb13999..6ab4c7b 100644 --- a/src/world_gate.c +++ b/src/world_gate.c @@ -325,10 +325,95 @@ void world_link_gates_async( void *payload, u32 size ) VG_ASSERT( vg_thread_purpose() == k_thread_purpose_main ); world_instance *world = payload; + bool found_nonlocal_reciever = 0; + for( u32 j=0; jent_gate); j ++ ) { ent_gate *gate = af_arritm( &world->ent_gate, j ); gate_transform_update( gate ); + + if( gate->flags & k_ent_gate_nonlocal ) + { + if( gate->target ) + { + const char *dest_world = af_str( &world->meta.af, gate->target ); + + addon_alias q; + addon_uid_to_alias( dest_world, &q ); + + gate->addon_reg = addon_match( &q ); + if( gate->addon_reg != 0xffffffff ) + { + gate->flags |= k_ent_gate_linked; + vg_info( "Linked non-local gate to addon #%u\n", gate->addon_reg ); + } + else + { + vg_error( "Reference in non-local gate to other world '%s' was not found.\n", dest_world ); + } + } + else + { + if( _world.travelled_through_nonlocal_gate ) + { + const char *key = af_str( &world->meta.af, gate->key ); + if( vg_str_eq( key, _world.nonlocal_destination_key ) ) + { + if( found_nonlocal_reciever ) + vg_warn( "There are multiple nonlocal gates that share the same key in this world (%s)\n", key ); + else + { + found_nonlocal_reciever = 1; + + ent_gate *gate2 = &_world.copy_of_nonlocal_sender; + + 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.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] ); + } + + gate_transform_update( gate ); + gate_transform_update( gate2 ); + + if( !(_world.copy_of_nonlocal_sender.flags & k_ent_gate_no_linkback) ) + { + gate->addon_reg = get_index_from_addon( k_addon_type_world, _world.previous_world_addon ); + + if( gate->addon_reg != 0xffffffff ) + { + gate->flags |= k_ent_gate_linked; + vg_info( "Linked non-local gate to addon #%u\n", gate->addon_reg ); + } + else + { + vg_error( "Error while linking to previous world.\n" ); + } + } + } + } + } + } + } + } + + if( _world.travelled_through_nonlocal_gate && !found_nonlocal_reciever ) + { + vg_error( "Player travelled through non-local gate, but no reciever gate was found. Player will default to start spawn or world save file.\n" ); + _world.travelled_through_nonlocal_gate = 0; } } diff --git a/src/world_load.c b/src/world_load.c index 9abcd14..2cb8419 100644 --- a/src/world_load.c +++ b/src/world_load.c @@ -284,17 +284,32 @@ void async_start_player_from_worldsave( void *payload, u32 size ) /* start entities in the world */ world_entity_start( data->instance, &sav ); - world_default_spawn_pos( data->instance, localplayer.rb.co ); /* start player in the world */ - vg_msg_init( &sav, data->save.buf, data->save.len ); - vg_msg player_frame = sav; - if( vg_msg_seekframe( &player_frame, "player" ) ) + if( _world.travelled_through_nonlocal_gate ) { - vg_msg_getkvvecf( &player_frame, "position", k_vg_msg_v3f, - localplayer.rb.co, NULL ); + player__transport( _world.copy_of_nonlocal_sender.transport ); + _world.travelled_through_nonlocal_gate = 0; + vg_success( "Successfuly consumed linked non-local gates composite transport matrix.\n" ); + } + else + { + bool restored_player_position = 0; + + vg_msg_init( &sav, data->save.buf, data->save.len ); + vg_msg player_frame = sav; + if( vg_msg_seekframe( &player_frame, "player" ) ) + { + if( vg_msg_getkvvecf( &player_frame, "position", k_vg_msg_v3f, + localplayer.rb.co, NULL ) ) + restored_player_position = 1; + } + + if( !restored_player_position ) + world_default_spawn_pos( data->instance, localplayer.rb.co ); + + player__reset(); } - player__reset(); } void load_player_from_world_savedata_thread( void *_args ) @@ -424,6 +439,9 @@ void skaterift_switch_world_start( addon_reg *reg ) return; } } + + if( reg != _world.main.addon ) + _world.previous_world_addon = _world.main.addon; g_client.unreadyness ++; _world.loader_state = k_world_loader_saving_current; diff --git a/src/world_render.c b/src/world_render.c index f30e97a..bf71a7c 100644 --- a/src/world_render.c +++ b/src/world_render.c @@ -900,6 +900,16 @@ void render_world_gates( world_instance *world, vg_camera *cam ) if( gate->flags & k_ent_gate_nonlocal ) { + world->rendering_gate = NULL; /* this is for jump prediction only. */ + + if( gate->flags & k_ent_gate_linked ) + { + + } + else + { + render_gate_unlinked( world, gate, cam ); + } } else render_gate( world, world, gate, cam ); diff --git a/src/world_routes.c b/src/world_routes.c index d677a70..68686b3 100644 --- a/src/world_routes.c +++ b/src/world_routes.c @@ -31,10 +31,15 @@ void world_routes_clear( world_instance *world ) route->active_checkpoint = 0xffff; } - for( u32 i=0; ient_gate ); i++ ){ + for( u32 i=0; ient_gate ); i++ ) + { ent_gate *rg = af_arritm( &world->ent_gate, i ); - rg->timing_version = 0; - rg->timing_time = 0.0; + + if( !(rg->flags & k_ent_gate_nonlocal) ) + { + rg->timing_version = 0; + rg->timing_time = 0.0; + } } _world.current_run_version += 4; @@ -489,13 +494,19 @@ void world_gen_routes_generate( world_instance *world ) &world->mesh_route_lines, 200000, 300000 ); - for( u32 i=0; ient_gate); i++ ){ + for( u32 i=0; ient_gate); i++ ) + { ent_gate *gate = af_arritm( &world->ent_gate, i ); - gate->ref_count = 0; - gate->route_count = 0; + + if( !(gate->flags & k_ent_gate_nonlocal) ) + { + gate->ref_count = 0; + gate->route_count = 0; + } } - for( u32 i=0; ient_route_node); i++ ){ + for( u32 i=0; ient_route_node); i++ ) + { ent_route_node *rn = af_arritm( &world->ent_route_node, i ); rn->ref_count = 0; rn->ref_total = 0; -- 2.25.1