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.
This commit is contained in:
MysterD 2021-06-14 20:14:47 -07:00
parent 6aded174e9
commit e7d0f8ec8b
6 changed files with 39 additions and 77 deletions

View File

@ -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)

View File

@ -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++;
}
}
}

View File

@ -13,7 +13,7 @@
#ifdef DEBUG
static u8 warpToLevel = LEVEL_BOB;
static u8 warpToLevel = LEVEL_LLL;
#define SCANCODE_0 0x0B
#define SCANCODE_1 0x02

View File

@ -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

View File

@ -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;

View File

@ -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");