From a55f05005144e11da149c89317820c3e65c8de09 Mon Sep 17 00:00:00 2001 From: MysterD Date: Thu, 6 Aug 2020 20:28:21 -0700 Subject: [PATCH] Synchronized teleports (e.g. flowerbed) and star collection Fixed infinite packet_level_warp sending --- src/game/interaction.c | 21 +++++++++-- src/game/level_update.c | 3 +- src/game/mario_actions_cutscene.c | 5 ++- src/game/save_file.c | 1 + src/pc/network/network.c | 1 + src/pc/network/network.h | 3 ++ src/pc/network/packets/packet_collect_star.c | 39 ++++++++++++++++++++ src/pc/network/packets/packet_level_warp.c | 20 ++++++---- 8 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 src/pc/network/packets/packet_collect_star.c diff --git a/src/game/interaction.c b/src/game/interaction.c index 48900226..c6607594 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -812,10 +812,17 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O m->usedObj = o; starIndex = (o->oBehParams >> 24) & 0x1F; + + if (m == &gMarioStates[0]) { + // sync the star collection + network_send_collect_star(m->numCoins, starIndex); + } save_file_collect_star_or_key(m->numCoins, starIndex); - m->numStars = - save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1); + s32 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1); + for (int i = 0; i < 2; i++) { + gMarioStates[i].numStars = numStars; + } if (!noExit) { drop_queued_background_music(); @@ -859,6 +866,11 @@ u32 interact_bbh_entrance(struct MarioState *m, UNUSED u32 interactType, struct u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 action; + if (m != &gMarioStates[0]) { + // don't do for remote players + return FALSE; + } + if (o->oInteractionSubtype & INT_SUBTYPE_FADING_WARP) { action = m->action; @@ -1792,7 +1804,10 @@ void mario_process_interactions(struct MarioState *m) { sDisplayingDoorText = FALSE; } if (!(m->marioObj->collidedObjInteractTypes & INTERACT_WARP)) { - sJustTeleported = FALSE; + if (m == &gMarioStates[0]) { + // limit to only local mario + sJustTeleported = FALSE; + } } } diff --git a/src/game/level_update.c b/src/game/level_update.c index aa4c9920..0c8ab70a 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -884,9 +884,8 @@ void initiate_delayed_warp(void) { default: warpNode = area_get_warp_node(sSourceWarpNodeId); - initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea, - warpNode->node.destNode, sDelayedWarpArg); + warpNode->node.destNode, sDelayedWarpArg); check_if_should_set_warp_checkpoint(&warpNode->node); if (sWarpDest.type != WARP_TYPE_CHANGE_LEVEL) { diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 60f9ad97..787d74e9 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -1436,7 +1436,10 @@ s32 act_teleport_fade_out(struct MarioState *m) { } if (m->actionTimer++ == 20) { - level_trigger_warp(m, WARP_OP_TELEPORT); + if (m == &gMarioStates[0]) { + // only do for local player + level_trigger_warp(m, WARP_OP_TELEPORT); + } } stop_and_set_height_to_floor(m); diff --git a/src/game/save_file.c b/src/game/save_file.c index 45ac71f4..9652c97b 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -474,6 +474,7 @@ void save_file_reload(void) { * If coin score is greater than the current high score, update it. */ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex) { + s32 fileIndex = gCurrSaveFileNum - 1; s32 courseIndex = gCurrCourseNum - 1; diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 9c37e48c..ad38690f 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -110,6 +110,7 @@ void network_update(void) { case PACKET_OBJECT: network_receive_object(&p); break; case PACKET_LEVEL_WARP: network_receive_level_warp(&p); break; case PACKET_INSIDE_PAINTING: network_receive_inside_painting(&p); break; + case PACKET_COLLECT_STAR: network_receive_collect_star(&p); break; default: printf("%s received unknown packet: %d\n", NETWORKTYPESTR, p.buffer[0]); } diff --git a/src/pc/network/network.h b/src/pc/network/network.h index 82af23b4..315eee2c 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -20,6 +20,7 @@ enum PacketType { PACKET_OBJECT, PACKET_LEVEL_WARP, PACKET_INSIDE_PAINTING, + PACKET_COLLECT_STAR, }; struct Packet { @@ -78,4 +79,6 @@ void network_receive_level_warp(struct Packet* p); void network_update_inside_painting(void); void network_receive_inside_painting(struct Packet* p); +void network_send_collect_star(s16 coinScore, s16 starIndex); +void network_receive_collect_star(struct Packet* p); #endif diff --git a/src/pc/network/packets/packet_collect_star.c b/src/pc/network/packets/packet_collect_star.c new file mode 100644 index 00000000..b78419b9 --- /dev/null +++ b/src/pc/network/packets/packet_collect_star.c @@ -0,0 +1,39 @@ +#include +#include "../network.h" +#include "course_table.h" + +extern s16 gCurrSaveFileNum; +extern s16 gCurrCourseNum; + +void network_send_collect_star(s16 coinScore, s16 starIndex) { + struct Packet p; + packet_init(&p, PACKET_COLLECT_STAR, true); + + packet_write(&p, &gCurrSaveFileNum, sizeof(s16)); + packet_write(&p, &gCurrCourseNum, sizeof(s16)); + packet_write(&p, &coinScore, sizeof(s16)); + packet_write(&p, &starIndex, sizeof(s16)); + + network_send(&p); +} + +void network_receive_collect_star(struct Packet* p) { + s16 coinScore, starIndex; + s16 lastSaveFileNum = gCurrSaveFileNum; + s16 lastCourseNum = gCurrCourseNum; + + packet_read(p, &gCurrSaveFileNum, sizeof(s16)); + packet_read(p, &gCurrCourseNum, sizeof(s16)); + packet_read(p, &coinScore, sizeof(s16)); + packet_read(p, &starIndex, sizeof(s16)); + + save_file_collect_star_or_key(coinScore, starIndex); + + s32 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1); + for (int i = 0; i < 2; i++) { + gMarioStates[i].numStars = numStars; + } + + gCurrSaveFileNum = lastSaveFileNum; + gCurrCourseNum = lastCourseNum; +} diff --git a/src/pc/network/packets/packet_level_warp.c b/src/pc/network/packets/packet_level_warp.c index eb387261..7e9ea261 100644 --- a/src/pc/network/packets/packet_level_warp.c +++ b/src/pc/network/packets/packet_level_warp.c @@ -3,7 +3,7 @@ #include "src/game/level_update.h" #include "src/game/area.h" -int warpTimeout = 0; +int matchCount = 0; void network_send_level_warp(void) { struct Packet p; @@ -17,7 +17,6 @@ void network_send_level_warp(void) { } void network_receive_level_warp(struct Packet* p) { - if (warpTimeout != 0) { return; } s16 remotePlayMode; s16 remoteLevelNum; s32 remoteWarpArg; @@ -28,16 +27,25 @@ void network_receive_level_warp(struct Packet* p) { packet_read(p, &remoteWarpArg, 4); packet_read(p, &remoteWarpNodeId, 2); - if (gCurrLevelNum == remoteLevelNum) { + bool matching = (remoteLevelNum == gCurrLevelNum) + && (remoteWarpArg == sDelayedWarpArg) + && (remoteWarpNodeId == sSourceWarpNodeId); + + if (matching) { if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { // our levels match now, lets play! set_play_mode(PLAY_MODE_NORMAL); set_menu_mode((s16)-1); } // our levels match, make sure the other player knows that - network_send_level_warp(); + if (matchCount++ < 3) { + network_send_level_warp(); + } else { + matchCount = 0; + } return; } + matchCount = 0; // remote isn't trying to sync, don't warp if (remotePlayMode != PLAY_MODE_SYNC_LEVEL) { return; } @@ -50,12 +58,8 @@ void network_receive_level_warp(struct Packet* p) { sDelayedWarpArg = remoteWarpArg; sSourceWarpNodeId = remoteWarpNodeId; sDelayedWarpOp = WARP_OP_FORCE_SYNC; - - // don't repeat the warp too quickly - warpTimeout = 2; } void network_update_level_warp(void) { network_send_level_warp(); - if (warpTimeout > 0) { warpTimeout--; } } \ No newline at end of file