From e7d0f8ec8bd589a62e2ef15fb1b719b0143face8 Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 14 Jun 2021 20:14:47 -0700 Subject: [PATCH] Resynchronized LLL puzzle pieces Created a timer based on area that is shared. The puzzle pieces will execute rapidly to catch up to the timer on level join. This keeps them in sync without constantly needing to acknowledge that a puzzle piece had moved before continuing. --- include/object_fields.h | 1 + src/game/behaviors/bowser_puzzle_piece.inc.c | 100 +++++------------- src/pc/controller/controller_keyboard_debug.c | 2 +- src/pc/network/network.c | 5 + src/pc/network/network.h | 1 + src/pc/network/packets/packet_area.c | 7 ++ 6 files changed, 39 insertions(+), 77 deletions(-) diff --git a/include/object_fields.h b/include/object_fields.h index a6d771ce5..0bfed2521 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -310,6 +310,7 @@ #define /*0x108*/ oBowserPuzzlePieceContinuePerformingAction OBJECT_FIELD_S32(0x20) #define /*0x10C*/ oBowserPuzzlePieceActionList OBJECT_FIELD_VPTR(0x21) #define /*0x110*/ oBowserPuzzlePieceNextAction OBJECT_FIELD_VPTR(0x22) +#define /*0x0F4*/ oBowserPuzzlePieceTimer OBJECT_FIELD_U32(0x1B) /* Bubba */ #define /*0x0F4*/ oBubbaUnkF4 OBJECT_FIELD_F32(0x1B) diff --git a/src/game/behaviors/bowser_puzzle_piece.inc.c b/src/game/behaviors/bowser_puzzle_piece.inc.c index f984dbb4e..088074fdf 100644 --- a/src/game/behaviors/bowser_puzzle_piece.inc.c +++ b/src/game/behaviors/bowser_puzzle_piece.inc.c @@ -94,6 +94,8 @@ void bhv_lll_bowser_puzzle_spawn_piece(s16 model, const BehaviorScript *behavior puzzlePiece->oAction = initialAction; // This action never gets executed. puzzlePiece->oBowserPuzzlePieceActionList = actionList; puzzlePiece->oBowserPuzzlePieceNextAction = actionList; + puzzlePiece->oBowserPuzzlePieceTimer = 0; + puzzlePiece->oTimer = 0; } /** @@ -114,69 +116,6 @@ void bhv_lll_bowser_puzzle_spawn_pieces(f32 pieceWidth) { o->oAction++; } -static u8 bowserPuzzleTimer = 0; -static u8 bowserPuzzleOnAction = 0; -static u8 bowserPuzzleServerAction = 0; -static u32 bowserPuzzleTxRxAction = 0; -static u8 bowserPuzzleRx[MAX_PLAYERS] = { 0 }; - -static void bhv_lll_bowser_puzzle_networking_received(u8 fromLocalIndex) { - if (gNetworkType == NT_CLIENT) { - if (bowserPuzzleTxRxAction != (u8)(bowserPuzzleOnAction + 1)) { return; } - bowserPuzzleServerAction = bowserPuzzleTxRxAction; - return; - } - if (bowserPuzzleTxRxAction != bowserPuzzleOnAction) { return; } - bowserPuzzleRx[fromLocalIndex] = bowserPuzzleTxRxAction; -} - -static void bhv_lll_bowser_puzzle_networking(void) { - if (!network_sync_object_initialized(o)) { - bowserPuzzleTimer = 0; - bowserPuzzleOnAction = 0; - bowserPuzzleServerAction = 0; - bowserPuzzleTxRxAction = 0; - for (int i = 0; i < MAX_PLAYERS; i++) { bowserPuzzleRx[i] = 0; } - - struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS); - network_init_object_field(o, &bowserPuzzleTxRxAction); - so->on_received_post = bhv_lll_bowser_puzzle_networking_received; - } - - if (bowserPuzzleTimer < 24) { - bowserPuzzleTimer++; - return; - } - - if (gNetworkType == NT_SERVER) { - if (bowserPuzzleTimer == 24) { - bowserPuzzleTimer++; - bowserPuzzleOnAction++; - bowserPuzzleTxRxAction = bowserPuzzleOnAction; - network_send_object(o); - return; - } - - for (int i = 1; i < MAX_PLAYERS; i++) { - if (gNetworkPlayers[i].connected && bowserPuzzleRx[i] != bowserPuzzleOnAction) { return; } - } - - // received from all, continue - bowserPuzzleTimer = 0; - return; - } - - if (gNetworkType == NT_CLIENT) { - if (bowserPuzzleServerAction == (u8)(bowserPuzzleOnAction + 1)) { - bowserPuzzleOnAction++; - bowserPuzzleTimer = 0; - bowserPuzzleTxRxAction = bowserPuzzleServerAction; - network_send_object(o); - } - return; - } -} - /* * Does the initial spawn of the puzzle pieces and then waits to spawn 5 coins. */ @@ -186,8 +125,6 @@ void bhv_lll_bowser_puzzle_loop(void) { struct Object* player = nearest_player_to_object(o); int distanceToPlayer = dist_between_objects(o, player); - bhv_lll_bowser_puzzle_networking(); - switch (o->oAction) { case BOWSER_PUZZLE_ACT_SPAWN_PIECES: bhv_lll_bowser_puzzle_spawn_pieces(480.0f); @@ -229,7 +166,7 @@ void bhv_lll_bowser_puzzle_piece_action_1(void) { * Update the puzzle piece. */ void bhv_lll_bowser_puzzle_piece_update(void) { - s8 *nextAction = o->oBowserPuzzlePieceNextAction; + s8* nextAction = o->oBowserPuzzlePieceNextAction; // If Mario is standing on this puzzle piece, set a flag in the parent. if (cur_obj_is_any_player_on_platform()) @@ -237,11 +174,6 @@ void bhv_lll_bowser_puzzle_piece_update(void) { // If we should advance to the next action... if (o->oBowserPuzzlePieceContinuePerformingAction == 0) { - // if we haven't received an event from everyone, do not continue execution - if (bowserPuzzleTimer >= 24) { - cur_obj_change_action(0); - return; - } // Start doing the next action. cur_obj_change_action(*nextAction); @@ -327,11 +259,27 @@ void (*sBowserPuzzlePieceActions[])(void) = { }; void bhv_lll_bowser_puzzle_piece_loop(void) { - bhv_lll_bowser_puzzle_piece_update(); + // make sure we're loaded and synchronized + if (!gNetworkLevelLoaded) { + o->oTimer = 0; + return; + } else if (o->oBowserPuzzlePieceTimer == 0 && (gNetworkLevelTimer - o->oBowserPuzzlePieceTimer) >= 650) { + o->oBowserPuzzlePieceTimer = ((gNetworkLevelTimer - o->oBowserPuzzlePieceTimer) / 650) * 650; + o->oTimer = 0; + } - cur_obj_call_action_function(sBowserPuzzlePieceActions); + while (o->oBowserPuzzlePieceTimer < gNetworkLevelTimer) { + bhv_lll_bowser_puzzle_piece_update(); - o->oPosX = o->oBowserPuzzlePieceOffsetX + o->oHomeX; - o->oPosY = o->oBowserPuzzlePieceOffsetY + o->oHomeY; - o->oPosZ = o->oBowserPuzzlePieceOffsetZ + o->oHomeZ; + cur_obj_call_action_function(sBowserPuzzlePieceActions); + + o->oPosX = o->oBowserPuzzlePieceOffsetX + o->oHomeX; + o->oPosY = o->oBowserPuzzlePieceOffsetY + o->oHomeY; + o->oPosZ = o->oBowserPuzzlePieceOffsetZ + o->oHomeZ; + + o->oBowserPuzzlePieceTimer++; + if (o->oBowserPuzzlePieceTimer < gNetworkLevelTimer) { + o->oTimer++; + } + } } diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c index 57d91dccc..484ef042b 100644 --- a/src/pc/controller/controller_keyboard_debug.c +++ b/src/pc/controller/controller_keyboard_debug.c @@ -13,7 +13,7 @@ #ifdef DEBUG -static u8 warpToLevel = LEVEL_BOB; +static u8 warpToLevel = LEVEL_LLL; #define SCANCODE_0 0x0B #define SCANCODE_1 0x02 diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 6fcd884d9..a7deed34a 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -27,6 +27,7 @@ struct NetworkSystem* gNetworkSystem = &gNetworkSystemSocket; u16 networkLoadingLevel = 0; bool gNetworkLevelLoaded = false; bool gNetworkLevelSyncing = true; +u32 gNetworkLevelTimer = 0; clock_t gLastNetworkSend = 0; struct StringLinkedList gRegisteredMods = { 0 }; @@ -91,6 +92,7 @@ void network_on_init_level(void) { networkLoadingLevel = 0; gNetworkLevelLoaded = false; gNetworkLevelSyncing = true; + gNetworkLevelTimer = 0; } void network_on_loaded_level(void) { @@ -228,8 +230,11 @@ void network_update(void) { networkLoadingLevel++; if (!gNetworkLevelLoaded && networkLoadingLevel >= LOADING_LEVEL_THRESHOLD) { gNetworkLevelLoaded = true; + gNetworkLevelTimer = 0; network_on_loaded_level(); } + } else if (gNetworkLevelLoaded) { + gNetworkLevelTimer++; } // send out update packets diff --git a/src/pc/network/network.h b/src/pc/network/network.h index fdaa127fa..cfcaadbb2 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -82,6 +82,7 @@ extern struct NetworkSystem* gNetworkSystem; extern enum NetworkType gNetworkType; extern bool gNetworkLevelLoaded; extern bool gNetworkLevelSyncing; +extern u32 gNetworkLevelTimer; extern struct SyncObject gSyncObjects[]; extern struct ServerSettings gServerSettings; extern clock_t gLastNetworkSend; diff --git a/src/pc/network/packets/packet_area.c b/src/pc/network/packets/packet_area.c index b91805fd3..a8f11b68e 100644 --- a/src/pc/network/packets/packet_area.c +++ b/src/pc/network/packets/packet_area.c @@ -43,6 +43,9 @@ void network_send_area(struct NetworkPlayer* toNp) { packet_write(&p, &gCurrLevelNum, sizeof(s16)); packet_write(&p, &gCurrAreaIndex, sizeof(s16)); + // area variables + packet_write(&p, &gNetworkLevelTimer, sizeof(u32)); + // write sync id removals packet_write(&p, &sRemoveSyncIdsIndex, sizeof(u8)); for (int i = 0; i < sRemoveSyncIdsIndex; i++) { @@ -129,6 +132,10 @@ void network_receive_area(struct Packet* p) { packet_read(p, &levelNum, sizeof(s16)); packet_read(p, &areaIndex, sizeof(s16)); + // read area variables + packet_read(p, &gNetworkLevelTimer, sizeof(u32)); + + extern s16 gCurrCourseNum, gCurrActStarNum, gCurrLevelNum; if (courseNum != gCurrCourseNum || actNum != gCurrActStarNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) { LOG_ERROR("rx area: received an improper location");