mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 13:35:12 +00:00
Created system to reserve sections of SyncIDs per client
This allows clients to spawn a new sync object after the level loads and synchronize it. Changed how un-initialized sync objects are detected Koopa shells are the first thing to use this new system Removed network_object_settings() command, instead explicitly setting the sync object parameters
This commit is contained in:
parent
ee35c999aa
commit
8c650a5b7d
39 changed files with 240 additions and 84 deletions
|
@ -90,9 +90,9 @@ static const LevelScript script_func_local_4[] = {
|
|||
OBJECT(/*model*/ MODEL_BUTTERFLY, /*pos*/ -1204, 326, 3296, /*angle*/ 0, 0, 0, /*behParam*/ 0x00000000, /*beh*/ bhvButterfly),
|
||||
OBJECT(/*model*/ MODEL_YOSHI, /*pos*/ 0, 3174, -5625, /*angle*/ 0, 0, 0, /*behParam*/ 0x00000000, /*beh*/ bhvYoshi),
|
||||
// TESTING BELOW
|
||||
OBJECT(/*model*/ MODEL_BLACK_BOBOMB, /*pos*/ -528, 260, 4664, /*angle*/ 0, 0, 0, /*behParam*/ 0x00000000, /*beh*/ bhvBobomb),
|
||||
OBJECT(/*model*/ MODEL_KOOPA_WITH_SHELL, /*pos*/ -528, 260, 3264, /*angle*/ 0, 0, 0, /*behParam*/ 0x00010000, /*beh*/ bhvKoopa),
|
||||
//OBJECT(/*model*/ MODEL_BLACK_BOBOMB, /*pos*/ -1028, 260, 3664, /*angle*/ 0, 0, 0, /*behParam*/ 0x00000000, /*beh*/ bhvBobomb),
|
||||
OBJECT(/*model*/ MODEL_NONE, /*pos*/ -528, 260, 3264, /*angle*/ 0, 0, 0, /*behParam*/ 0x00000000, /*beh*/ bhvGoombaTripletSpawner),
|
||||
//OBJECT(/*model*/ MODEL_NONE, /*pos*/ -528, 260, 3264, /*angle*/ 0, 0, 0, /*behParam*/ 0x00000000, /*beh*/ bhvGoombaTripletSpawner),
|
||||
RETURN(),
|
||||
};
|
||||
|
||||
|
@ -113,6 +113,7 @@ const LevelScript level_castle_grounds_entry[] = {
|
|||
JUMP_LINK(script_func_global_1),
|
||||
JUMP_LINK(script_func_global_11),
|
||||
JUMP_LINK(script_func_global_16),
|
||||
JUMP_LINK(script_func_global_15), // <--- TESTING
|
||||
LOAD_MODEL_FROM_GEO(MODEL_LEVEL_GEOMETRY_03, castle_grounds_geo_0006F4),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_CASTLE_GROUNDS_BUBBLY_TREE, bubbly_tree_geo),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_CASTLE_GROUNDS_WARP_PIPE, warp_pipe_geo),
|
||||
|
|
|
@ -60,7 +60,7 @@ void bhv_hidden_blue_coin_loop(void) {
|
|||
* Update function for bhvBlueCoinSwitch.
|
||||
*/
|
||||
void bhv_blue_coin_switch_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oVelY);
|
||||
|
|
|
@ -4,7 +4,7 @@ void bhv_small_bomp_init(void) {
|
|||
o->oFaceAngleYaw -= 0x4000;
|
||||
o->oSmallBompInitX = o->oPosX;
|
||||
o->oTimer = random_float() * 100.0f;
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oForwardVel);
|
||||
|
@ -70,7 +70,7 @@ void bhv_small_bomp_loop(void) {
|
|||
void bhv_large_bomp_init(void) {
|
||||
o->oMoveAngleYaw += 0x4000;
|
||||
o->oTimer = random_float() * 100.0f;
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oForwardVel);
|
||||
|
|
|
@ -180,9 +180,9 @@ void bhv_generic_bowling_ball_spawner_init(void) {
|
|||
}
|
||||
|
||||
void bhv_generic_bowling_ball_spawner_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_object_settings(o, FALSE, 0, TRUE, NULL);
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
so->keepRandomSeed = TRUE;
|
||||
}
|
||||
|
||||
struct Object *bowlingBall;
|
||||
|
@ -217,9 +217,9 @@ void bhv_generic_bowling_ball_spawner_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_thi_bowling_ball_spawner_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_object_settings(o, FALSE, 0, TRUE, NULL);
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
so->keepRandomSeed = TRUE;
|
||||
}
|
||||
|
||||
struct Object *bowlingBall;
|
||||
|
@ -253,8 +253,9 @@ void bhv_bob_pit_bowling_ball_init(void) {
|
|||
o->oFriction = 1.0f;
|
||||
o->oBuoyancy = 2.0f;
|
||||
|
||||
network_init_object(o, 5000.0f);
|
||||
network_object_settings(o, FALSE, 5.0f, TRUE, NULL);
|
||||
struct SyncObject* so = network_init_object(o, 5000.0f);
|
||||
so->maxUpdateRate = 5.0f;
|
||||
so->keepRandomSeed = TRUE;
|
||||
}
|
||||
|
||||
void bhv_bob_pit_bowling_ball_loop(void) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// breakable_wall.c.inc
|
||||
|
||||
void bhv_wf_breakable_wall_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oBreakableWallForce);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ void bhv_white_puff_smoke_init(void) {
|
|||
|
||||
void bhv_bullet_bill_init(void) {
|
||||
o->oBulletBillInitialMoveYaw = o->oMoveAngleYaw;
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 4000.0f);
|
||||
network_init_object_field(o, &o->oFaceAnglePitch);
|
||||
network_init_object_field(o, &o->oFaceAngleRoll);
|
||||
|
|
|
@ -147,9 +147,9 @@ u8 unused0EA1FC[] = { 2, 0, 0, 0, 0, 0, 0, 0, 63, 128, 0, 0, 2, 0, 0, 0
|
|||
u8 cannon_ignore_remote_updates(struct Object* object) { return object->oCannonIsLocal; }
|
||||
|
||||
void bhv_cannon_base_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_object_settings(o, FALSE, 0, FALSE, &cannon_ignore_remote_updates);
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
so->ignore_if_true = &cannon_ignore_remote_updates;
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oTimer);
|
||||
network_init_object_field(o, &o->oCannonUnk10C);
|
||||
|
|
|
@ -60,7 +60,7 @@ void (*sCapSwitchActions[])(void) = { cap_switch_act_0, cap_switch_act_1,
|
|||
cap_switch_act_2, cap_switch_act_3 };
|
||||
|
||||
void bhv_cap_switch_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &capSwitchForcePress);
|
||||
}
|
||||
|
|
|
@ -491,7 +491,7 @@ static void chain_chomp_act_unload_chain(void) {
|
|||
* Update function for chain chomp.
|
||||
*/
|
||||
void bhv_chain_chomp_update(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 1000.0f);
|
||||
network_init_object_field(o, &o->oChainChompUnk104);
|
||||
network_init_object_field(o, &o->header.gfx.unk38.animFrame);
|
||||
|
@ -514,7 +514,7 @@ void bhv_chain_chomp_update(void) {
|
|||
* Update function for wooden post.
|
||||
*/
|
||||
void bhv_wooden_post_update(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oWoodenPostMarioPounding);
|
||||
network_init_object_field(o, &o->oWoodenPostOffsetY);
|
||||
|
|
|
@ -45,8 +45,10 @@ void checkerboard_plat_act_rotate(s32 a0, s16 a1) {
|
|||
|
||||
void bhv_checkerboard_platform_init(void) {
|
||||
o->oCheckerBoardPlatformUnkFC = o->parentObj->oBehParams2ndByte;
|
||||
network_init_object(o, 1000.0f);
|
||||
network_object_settings(o, TRUE, 5.0f, TRUE, NULL);
|
||||
struct SyncObject* so = network_init_object(o, 1000.0f);
|
||||
so->fullObjectSync = TRUE;
|
||||
so->maxUpdateRate = 5.0f;
|
||||
so->keepRandomSeed = TRUE;
|
||||
}
|
||||
|
||||
void bhv_checkerboard_platform_loop(void) {
|
||||
|
|
|
@ -56,7 +56,7 @@ void clam_act_1(void) {
|
|||
}
|
||||
|
||||
void bhv_clam_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oTimer);
|
||||
|
|
|
@ -156,7 +156,7 @@ void (*sExclamationBoxActions[])(void) = { exclamation_box_act_0, exclamation_bo
|
|||
exclamation_box_act_4, exclamation_box_act_5 };
|
||||
|
||||
void bhv_exclamation_box_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oExclamationBoxForce);
|
||||
}
|
||||
|
|
|
@ -21,9 +21,10 @@ void bhv_sunken_ship_part_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_ship_part_3_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
network_init_object(o, 4000.0f);
|
||||
network_object_settings(o, FALSE, 5.0f, TRUE, NULL);
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
struct SyncObject* so = network_init_object(o, 4000.0f);
|
||||
so->maxUpdateRate = 5.0f;
|
||||
so->keepRandomSeed = TRUE;
|
||||
network_init_object_field(o, &o->oFaceAnglePitch);
|
||||
network_init_object_field(o, &o->oFaceAngleRoll);
|
||||
network_init_object_field(o, &o->oShipPart3UnkF4);
|
||||
|
@ -42,9 +43,10 @@ void bhv_ship_part_3_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_jrb_sliding_box_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
network_init_object(o, 4000.0f);
|
||||
network_object_settings(o, FALSE, 5.0f, TRUE, NULL);
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
struct SyncObject* so = network_init_object(o, 4000.0f);
|
||||
so->maxUpdateRate = 5.0f;
|
||||
so->keepRandomSeed = TRUE;
|
||||
network_init_object_field(o, &o->oFaceAnglePitch);
|
||||
network_init_object_field(o, &o->oFaceAngleRoll);
|
||||
network_init_object_field(o, &o->oJrbSlidingBoxUnkF8);
|
||||
|
|
|
@ -27,7 +27,7 @@ void init_kickable_board_rock(void) {
|
|||
|
||||
void bhv_kickable_board_loop(void) {
|
||||
struct MarioState* marioState = nearest_mario_state_to_object(o);
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oAngleVelPitch);
|
||||
|
|
|
@ -352,7 +352,7 @@ void king_bobomb_move(void) {
|
|||
}
|
||||
|
||||
void bhv_king_bobomb_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 4000.0f);
|
||||
network_init_object_field(o, &o->oKingBobombUnk88);
|
||||
network_init_object_field(o, &o->oFlags);
|
||||
|
|
|
@ -300,7 +300,16 @@ void shelled_koopa_attack_handler(s32 attackType) {
|
|||
}
|
||||
|
||||
cur_obj_set_model(MODEL_KOOPA_WITHOUT_SHELL);
|
||||
spawn_object(o, MODEL_KOOPA_SHELL, bhvKoopaShell);
|
||||
|
||||
struct MarioState* marioState = nearest_mario_state_to_object(o);
|
||||
if (marioState->playerIndex == 0) {
|
||||
struct Object* shell = spawn_object(o, MODEL_KOOPA_SHELL, bhvKoopaShell);
|
||||
network_set_sync_id(shell);
|
||||
|
||||
struct Object* spawn_objects[] = { shell };
|
||||
u32 models[] = { MODEL_KOOPA_SHELL };
|
||||
network_send_spawn_objects(spawn_objects, models, 1);
|
||||
}
|
||||
|
||||
//! Because bob-ombs/corkboxes come after koopa in processing order,
|
||||
// they can interact with the koopa on the same frame that this
|
||||
|
@ -917,7 +926,7 @@ void koopa_the_quick_force_end_race(void) {
|
|||
* Update function for bhvKoopaRaceEndpoint.
|
||||
*/
|
||||
void bhv_koopa_race_endpoint_update(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &koopaForceEndRace);
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ void koopa_shell_spawn_sparkles(f32 a) {
|
|||
}
|
||||
|
||||
void bhv_koopa_shell_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 500.0f);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ void set_koopa_shell_underwater_hitbox(void) {
|
|||
}
|
||||
|
||||
void bhv_koopa_shell_underwater_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 500.0f);
|
||||
}
|
||||
switch (o->oHeldState) {
|
||||
|
|
|
@ -212,7 +212,7 @@ void bhv_1up_jump_on_approach_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_1up_hidden_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oVelY);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
|
@ -260,7 +260,7 @@ void bhv_1up_hidden_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_1up_hidden_trigger_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->o1UpForceSpawn);
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ void bhv_1up_hidden_trigger_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_1up_hidden_in_pole_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oVelY);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
|
@ -318,7 +318,7 @@ void bhv_1up_hidden_in_pole_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_1up_hidden_in_pole_trigger_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->o1UpForceSpawn);
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ void bhv_1up_hidden_in_pole_trigger_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_1up_hidden_in_pole_spawner_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->o1UpForceSpawn);
|
||||
}
|
||||
|
|
|
@ -360,7 +360,7 @@ void (*TablePiranhaPlantActions[])(void) = {
|
|||
* Main loop for bhvPiranhaPlant.
|
||||
*/
|
||||
void bhv_piranha_plant_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oInteractStatus);
|
||||
|
|
|
@ -53,9 +53,11 @@ static void platform_on_track_mario_not_on_platform(void) {
|
|||
*/
|
||||
void bhv_platform_on_track_init(void) {
|
||||
|
||||
if (o->oSyncID == 0) {
|
||||
network_init_object(o, 1000.0f);
|
||||
network_object_settings(o, TRUE, 5.0f, TRUE, NULL);
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
struct SyncObject* so = network_init_object(o, 1000.0f);
|
||||
so->fullObjectSync = TRUE;
|
||||
so->maxUpdateRate = 5.0f;
|
||||
so->keepRandomSeed = TRUE;
|
||||
}
|
||||
|
||||
if (!(o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
void bhv_purple_switch_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oTimer);
|
||||
|
|
|
@ -9,7 +9,7 @@ struct WFRotatingPlatformData sWFRotatingPlatformData[] = {
|
|||
};
|
||||
|
||||
void bhv_wf_rotating_wooden_platform_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oAngleVelYaw);
|
||||
|
|
|
@ -21,7 +21,7 @@ void bhv_wf_sliding_platform_init(void) {
|
|||
|
||||
o->oTimer = random_float() * 100.0f;
|
||||
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oMoveAngleYaw);
|
||||
|
|
|
@ -13,7 +13,7 @@ struct ObjectHitbox sSpindriftHitbox = {
|
|||
};
|
||||
|
||||
void bhv_spindrift_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 4000.0f);
|
||||
network_init_object_field(o, &o->oFlags);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ void (*sGrindelThwompActions[])(void) = { grindel_thwomp_act_0, grindel_thwomp_a
|
|||
grindel_thwomp_act_4 };
|
||||
|
||||
void bhv_grindel_thwomp_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oPosY);
|
||||
|
|
|
@ -11,7 +11,7 @@ void bhv_wf_solid_tower_platform_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_wf_elevator_tower_platform_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oPosY);
|
||||
|
@ -55,7 +55,7 @@ void bhv_wf_elevator_tower_platform_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_wf_sliding_tower_platform_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oForwardVel);
|
||||
|
|
|
@ -147,7 +147,7 @@ void (*sTuxiesMotherActions[])(void) = { tuxies_mother_act_0, tuxies_mother_act_
|
|||
tuxies_mother_act_2 };
|
||||
|
||||
void bhv_tuxies_mother_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
network_init_object_field(o, &o->oAction);
|
||||
network_init_object_field(o, &o->oSubAction);
|
||||
|
@ -288,7 +288,7 @@ void small_penguin_free_actions(void) {
|
|||
}
|
||||
|
||||
void bhv_small_penguin_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 4000.0f);
|
||||
}
|
||||
switch (o->oHeldState) {
|
||||
|
|
|
@ -262,7 +262,7 @@ void ukiki_act_run(void) {
|
|||
|
||||
//! @bug (Ukikispeedia) This function sets forward speed to 0.9 * Mario's
|
||||
//! forward speed, which means ukiki can move at hyperspeed rates.
|
||||
cur_obj_set_vel_from_mario_vel(20.0f, 0.9f);
|
||||
cur_obj_set_vel_from_mario_vel(&gMarioStates[0], 20.0f, 0.9f);
|
||||
|
||||
if (fleeMario) {
|
||||
if (o->oDistanceToMario > o->oUkikiChaseFleeRange) {
|
||||
|
|
|
@ -29,11 +29,13 @@ static struct ObjectHitbox sWaterBombHitbox = {
|
|||
* Spawn water bombs targeting mario when he comes in range.
|
||||
*/
|
||||
void bhv_water_bomb_spawner_update(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
|
||||
so->fullObjectSync = TRUE;
|
||||
so->maxUpdateRate = 5.0f;
|
||||
so->keepRandomSeed = TRUE;
|
||||
network_init_object_field(o, &o->oWaterBombSpawnerBombActive);
|
||||
network_init_object_field(o, &o->oWaterBombSpawnerTimeToSpawn);
|
||||
network_object_settings(o, FALSE, 0, TRUE, NULL);
|
||||
}
|
||||
|
||||
f32 latDistToMario = 9999;
|
||||
|
|
|
@ -267,7 +267,7 @@ void (*sWhompActions[])(void) = {
|
|||
|
||||
// MM
|
||||
void bhv_whomp_loop(void) {
|
||||
if (o->oSyncID == 0) {
|
||||
if (!network_sync_object_initialized(o)) {
|
||||
network_init_object(o, 4000.0f);
|
||||
network_init_object_field(o, &o->oAngleVelPitch);
|
||||
network_init_object_field(o, &o->oFaceAnglePitch);
|
||||
|
|
|
@ -1196,6 +1196,8 @@ s32 update_level(void) {
|
|||
}
|
||||
|
||||
s32 init_level(void) {
|
||||
network_on_init_level();
|
||||
|
||||
s32 val4 = 0;
|
||||
|
||||
set_play_mode(PLAY_MODE_NORMAL);
|
||||
|
|
|
@ -999,8 +999,8 @@ void cur_obj_change_action(s32 action) {
|
|||
cur_obj_reset_timer_and_subaction();
|
||||
}
|
||||
|
||||
void cur_obj_set_vel_from_mario_vel(f32 f12, f32 f14) {
|
||||
f32 sp4 = gMarioStates[0].forwardVel;
|
||||
void cur_obj_set_vel_from_mario_vel(struct MarioState* m, f32 f12, f32 f14) {
|
||||
f32 sp4 = m->forwardVel;
|
||||
f32 sp0 = f12 * f14;
|
||||
|
||||
if (sp4 < sp0) {
|
||||
|
|
|
@ -146,7 +146,7 @@ s32 count_unimportant_objects(void);
|
|||
s32 count_objects_with_behavior(const BehaviorScript *behavior);
|
||||
struct Object *cur_obj_find_nearby_held_actor(const BehaviorScript *behavior, f32 maxDist);
|
||||
void cur_obj_change_action(s32 action);
|
||||
void cur_obj_set_vel_from_mario_vel(f32 f12,f32 f14);
|
||||
void cur_obj_set_vel_from_mario_vel(struct MarioState* m, f32 f12,f32 f14);
|
||||
BAD_RETURN(s16) cur_obj_reverse_animation(void);
|
||||
BAD_RETURN(s32) cur_obj_extend_animation_if_at_end(void);
|
||||
s32 cur_obj_check_if_near_animation_end(void);
|
||||
|
|
|
@ -8,6 +8,10 @@ enum NetworkType networkType;
|
|||
static SOCKET gSocket;
|
||||
struct sockaddr_in txAddr;
|
||||
|
||||
#define LOADING_LEVEL_THRESHOLD 10
|
||||
u8 networkLoadingLevel = 0;
|
||||
bool networkLevelLoaded = false;
|
||||
|
||||
void network_init(enum NetworkType inNetworkType, char* ip, char* port) {
|
||||
networkType = inNetworkType;
|
||||
|
||||
|
@ -29,6 +33,17 @@ void network_init(enum NetworkType inNetworkType, char* ip, char* port) {
|
|||
}
|
||||
}
|
||||
|
||||
void network_on_init_level(void) {
|
||||
networkLoadingLevel = 0;
|
||||
networkLevelLoaded = false;
|
||||
}
|
||||
|
||||
void network_on_loaded_level(void) {
|
||||
if (networkType == NT_CLIENT) {
|
||||
network_send_reservation_request();
|
||||
}
|
||||
}
|
||||
|
||||
void network_send(struct Packet* p) {
|
||||
// sanity checks
|
||||
if (networkType == NT_NONE) { return; }
|
||||
|
@ -49,6 +64,12 @@ void network_send(struct Packet* p) {
|
|||
|
||||
void network_update(void) {
|
||||
if (networkType == NT_NONE) { return; }
|
||||
if (!networkLevelLoaded) {
|
||||
if (networkLoadingLevel++ >= LOADING_LEVEL_THRESHOLD) {
|
||||
networkLevelLoaded = true;
|
||||
network_on_loaded_level();
|
||||
}
|
||||
}
|
||||
|
||||
if (gInsidePainting && sCurrPlayMode == PLAY_MODE_CHANGE_LEVEL) {
|
||||
network_update_inside_painting();
|
||||
|
@ -82,6 +103,8 @@ void network_update(void) {
|
|||
case PACKET_COLLECT_STAR: network_receive_collect_star(&p); break;
|
||||
case PACKET_COLLECT_COIN: network_receive_collect_coin(&p); break;
|
||||
case PACKET_COLLECT_ITEM: network_receive_collect_item(&p); break;
|
||||
case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(&p); break;
|
||||
case PACKET_RESERVATION: network_receive_reservation(&p); break;
|
||||
default: printf("%s received unknown packet: %d\n", NETWORKTYPESTR, p.buffer[0]);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ enum PacketType {
|
|||
PACKET_COLLECT_STAR,
|
||||
PACKET_COLLECT_COIN,
|
||||
PACKET_COLLECT_ITEM,
|
||||
PACKET_RESERVATION_REQUEST,
|
||||
PACKET_RESERVATION,
|
||||
};
|
||||
|
||||
struct Packet {
|
||||
|
@ -39,6 +41,7 @@ struct Packet {
|
|||
|
||||
struct SyncObject {
|
||||
struct Object* o;
|
||||
u16 reserved;
|
||||
float maxSyncDistance;
|
||||
bool owned;
|
||||
clock_t clockSinceUpdate;
|
||||
|
@ -58,12 +61,14 @@ extern u8 gInsidePainting;
|
|||
extern s16 sCurrPlayMode;
|
||||
extern enum NetworkType networkType;
|
||||
extern struct SyncObject syncObjects[];
|
||||
extern bool networkLevelLoaded;
|
||||
|
||||
void network_init(enum NetworkType inNetworkType, char* ip, char* port);
|
||||
void network_on_init_level(void);
|
||||
void network_on_loaded_level(void);
|
||||
|
||||
void network_clear_sync_objects(void);
|
||||
void network_init_object(struct Object *object, float maxSyncDistance);
|
||||
void network_object_settings(struct Object *object, bool fullObjectSync, float maxUpdateRate, bool keepRandomSeed, u8 ignore_if_true(struct Object*));
|
||||
struct SyncObject* network_init_object(struct Object *object, float maxSyncDistance);
|
||||
void network_send(struct Packet* p);
|
||||
void network_update(void);
|
||||
void network_shutdown(void);
|
||||
|
@ -85,6 +90,8 @@ void network_update_player(void);
|
|||
void network_receive_player(struct Packet* p);
|
||||
|
||||
bool network_owns_object(struct Object* o);
|
||||
void network_set_sync_id(struct Object* o);
|
||||
bool network_sync_object_initialized(struct Object* o);
|
||||
void network_update_objects(void);
|
||||
void network_send_object(struct Object* o);
|
||||
void network_receive_object(struct Packet* p);
|
||||
|
@ -109,4 +116,10 @@ void network_receive_collect_coin(struct Packet* p);
|
|||
|
||||
void network_send_collect_item(struct Object* o);
|
||||
void network_receive_collect_item(struct Packet* p);
|
||||
|
||||
void network_send_reservation_request(void);
|
||||
void network_receive_reservation_request(struct Packet* p);
|
||||
void network_send_reservation(void);
|
||||
void network_receive_reservation(struct Packet* p);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,22 +28,32 @@ void network_clear_sync_objects(void) {
|
|||
nextSyncID = 1;
|
||||
}
|
||||
|
||||
void network_init_object(struct Object *o, float maxSyncDistance) {
|
||||
// generate new sync ID
|
||||
if (o->oSyncID == 0) {
|
||||
void network_set_sync_id(struct Object* o) {
|
||||
if (o->oSyncID != 0) { return; }
|
||||
|
||||
// two-player hack
|
||||
u8 reserveId = (networkLevelLoaded && networkType == NT_CLIENT) ? 1 : 0;
|
||||
|
||||
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
||||
if (syncObjects[nextSyncID].o == NULL) { break; }
|
||||
if (syncObjects[nextSyncID].reserved == reserveId && syncObjects[nextSyncID].o == NULL) { break; }
|
||||
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
|
||||
}
|
||||
assert(syncObjects[nextSyncID].o == NULL);
|
||||
assert(syncObjects[nextSyncID].reserved == reserveId);
|
||||
o->oSyncID = nextSyncID;
|
||||
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
|
||||
}
|
||||
|
||||
assert(o->oSyncID < MAX_SYNC_OBJECTS);
|
||||
}
|
||||
|
||||
struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance) {
|
||||
// generate new sync ID
|
||||
network_set_sync_id(o);
|
||||
|
||||
// set default values for sync object
|
||||
struct SyncObject* so = &syncObjects[o->oSyncID];
|
||||
so->o = o;
|
||||
so->reserved = 0;
|
||||
so->maxSyncDistance = maxSyncDistance;
|
||||
so->owned = false;
|
||||
so->clockSinceUpdate = clock();
|
||||
|
@ -56,16 +66,8 @@ void network_init_object(struct Object *o, float maxSyncDistance) {
|
|||
so->ignore_if_true = NULL;
|
||||
so->syncDeathEvent = true;
|
||||
memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS);
|
||||
}
|
||||
|
||||
void network_object_settings(struct Object *o, bool fullObjectSync, float maxUpdateRate, bool keepRandomSeed, u8 ignore_if_true(struct Object*)) {
|
||||
assert(o->oSyncID != 0);
|
||||
// override default settings for sync object
|
||||
struct SyncObject* so = &syncObjects[o->oSyncID];
|
||||
so->fullObjectSync = fullObjectSync;
|
||||
so->maxUpdateRate = maxUpdateRate;
|
||||
so->keepRandomSeed = keepRandomSeed;
|
||||
so->ignore_if_true = ignore_if_true;
|
||||
return so;
|
||||
}
|
||||
|
||||
void network_init_object_field(struct Object *o, void* field) {
|
||||
|
@ -82,6 +84,12 @@ bool network_owns_object(struct Object* o) {
|
|||
return so->owned;
|
||||
}
|
||||
|
||||
bool network_sync_object_initialized(struct Object* o) {
|
||||
if (o->oSyncID == 0) { return false; }
|
||||
if (syncObjects[o->oSyncID].behavior == NULL) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----- header ----- //
|
||||
|
||||
static void packet_write_object_header(struct Packet* p, struct Object* o) {
|
||||
|
@ -256,6 +264,7 @@ static void packet_read_object_only_death(struct Packet* p, struct Object* o) {
|
|||
|
||||
void network_send_object(struct Object* o) {
|
||||
// sanity check SyncObject
|
||||
if (!network_sync_object_initialized(o)) { return; }
|
||||
struct SyncObject* so = &syncObjects[o->oSyncID];
|
||||
if (so == NULL) { return; }
|
||||
if (o->behavior != so->behavior) {
|
||||
|
@ -299,6 +308,7 @@ void network_receive_object(struct Packet* p) {
|
|||
struct SyncObject* so = packet_read_object_header(p);
|
||||
if (so == NULL) { return; }
|
||||
struct Object* o = so->o;
|
||||
if (!network_sync_object_initialized(o)) { return; }
|
||||
|
||||
// make sure no one can update an object we're holding
|
||||
if (gMarioStates[0].heldObj == o) { return; }
|
||||
|
@ -324,6 +334,8 @@ bool should_own_object(struct SyncObject* so) {
|
|||
|
||||
void forget_sync_object(struct SyncObject* so) {
|
||||
so->o = NULL;
|
||||
so->behavior = NULL;
|
||||
so->reserved = 0;
|
||||
so->owned = false;
|
||||
}
|
||||
|
||||
|
|
72
src/pc/network/packets/packet_reservation.c
Normal file
72
src/pc/network/packets/packet_reservation.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "course_table.h"
|
||||
#include "src/game/interaction.h"
|
||||
#include "src/engine/math_util.h"
|
||||
|
||||
#define RESERVATION_COUNT 10
|
||||
|
||||
void network_send_reservation_request(void) {
|
||||
assert(networkType == NT_CLIENT);
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_RESERVATION_REQUEST, true);
|
||||
network_send(&p);
|
||||
}
|
||||
|
||||
void network_receive_reservation_request(struct Packet* p) {
|
||||
assert(networkType == NT_SERVER);
|
||||
network_send_reservation();
|
||||
}
|
||||
|
||||
void network_send_reservation(void) {
|
||||
assert(networkType == NT_SERVER);
|
||||
int clientPlayerIndex = 1; // two-player hack
|
||||
|
||||
// find all reserved objects
|
||||
u8 reservedObjs[RESERVATION_COUNT] = { 0 };
|
||||
int reservedIndex = 0;
|
||||
for (int i = 1; i < MAX_SYNC_OBJECTS; i++) {
|
||||
if (syncObjects[i].reserved == clientPlayerIndex) {
|
||||
reservedObjs[reservedIndex++] = i;
|
||||
if (reservedIndex >= RESERVATION_COUNT) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
if (reservedIndex < RESERVATION_COUNT) {
|
||||
// reserve the rest
|
||||
for (int i = MAX_SYNC_OBJECTS - 1; i > 0; i--) {
|
||||
if (syncObjects[i].o != NULL) { continue; }
|
||||
if (syncObjects[i].reserved != 0) { continue; }
|
||||
syncObjects[i].reserved = clientPlayerIndex;
|
||||
reservedObjs[reservedIndex++] = i;
|
||||
if (reservedIndex >= RESERVATION_COUNT) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_RESERVATION, true);
|
||||
packet_write(&p, reservedObjs, sizeof(u8) * RESERVATION_COUNT);
|
||||
network_send(&p);
|
||||
}
|
||||
|
||||
void network_receive_reservation(struct Packet* p) {
|
||||
assert(networkType == NT_CLIENT);
|
||||
int clientPlayerIndex = 1; // two-player hack
|
||||
|
||||
// find all reserved objects
|
||||
u8 reservedObjs[RESERVATION_COUNT] = { 0 };
|
||||
packet_read(p, reservedObjs, sizeof(u8) * RESERVATION_COUNT);
|
||||
|
||||
for (int i = 0; i < RESERVATION_COUNT; i++) {
|
||||
int index = reservedObjs[i];
|
||||
printf(" %d", index);
|
||||
if (index == 0) { continue; }
|
||||
if (syncObjects[index].o != NULL) { continue; }
|
||||
syncObjects[index].reserved = clientPlayerIndex;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
|
@ -56,7 +56,6 @@ void network_send_spawn_objects(struct Object* objects[], u32 models[], u8 objec
|
|||
packet_write(&p, &behaviorId, sizeof(enum BehaviorId));
|
||||
packet_write(&p, &o->activeFlags, sizeof(s16));
|
||||
packet_write(&p, o->rawData.asU32, sizeof(s32) * 80);
|
||||
assert(o->oSyncID == 0);
|
||||
}
|
||||
|
||||
network_send(&p);
|
||||
|
@ -83,6 +82,10 @@ void network_receive_spawn_objects(struct Packet* p) {
|
|||
remoteSpawnIds[onRemoteSpawnId] = remoteSpawnId;
|
||||
onRemoteSpawnId = (onRemoteSpawnId + 1) % MAX_REMOTE_SPAWN_IDS;
|
||||
|
||||
// two-player hack
|
||||
u8 reserveId = (networkLevelLoaded && networkType == NT_SERVER) ? 1 : 0;
|
||||
bool receivedReservedSyncObject = false;
|
||||
|
||||
struct Object* spawned[MAX_SPAWN_OBJECTS_PER_PACKET] = { 0 };
|
||||
for (u8 i = 0; i < objectCount; i++) {
|
||||
struct SpawnObjectData data = { 0 };
|
||||
|
@ -101,6 +104,18 @@ void network_receive_spawn_objects(struct Packet* p) {
|
|||
struct Object* o = spawn_object(parentObj, data.model, behavior);
|
||||
memcpy(o->rawData.asU32, data.rawData, sizeof(u32) * 80);
|
||||
|
||||
// they've allocated one of their reserved sync objects
|
||||
if (o->oSyncID != 0 && syncObjects[o->oSyncID].reserved == reserveId) {
|
||||
syncObjects[o->oSyncID].o = o;
|
||||
syncObjects[o->oSyncID].reserved = 0;
|
||||
receivedReservedSyncObject = true;
|
||||
}
|
||||
|
||||
spawned[i] = o;
|
||||
}
|
||||
|
||||
// update their block of reserved ids
|
||||
if (networkType == NT_SERVER && receivedReservedSyncObject) {
|
||||
network_send_reservation();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue