From 8c7f55a1fb40d2d3656704b5434ca746fa7255dc Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 28 Sep 2020 19:58:37 -0700 Subject: [PATCH] Synchronize instant warps --- include/types.h | 2 + src/game/level_update.c | 44 ++++++--- src/game/level_update.h | 1 + src/game/screen_transition.c | 4 +- src/pc/network/packets/packet.c | 1 + src/pc/network/packets/packet.h | 5 ++ src/pc/network/packets/packet_instant_warp.c | 94 ++++++++++++++++++++ 7 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 src/pc/network/packets/packet_instant_warp.c diff --git a/include/types.h b/include/types.h index d81dc460f..dd981ee7e 100644 --- a/include/types.h +++ b/include/types.h @@ -375,6 +375,8 @@ struct MarioState /*????*/ Vec4s* splineKeyframe; /*????*/ float splineKeyframeFraction; /*????*/ int splineState; + + /*????*/ Vec3f nonInstantWarpPos; }; #define PLAY_MODE_NORMAL 0 diff --git a/src/game/level_update.c b/src/game/level_update.c index 5336c5a7d..af3a631e6 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -51,6 +51,7 @@ struct SavedWarpValues gReceiveWarp = { 0 }; u8 gControlledWarp = 0; extern s8 sReceivedLoadedActNum; +u8 gRejectInstantWarp = 0; #ifdef VERSION_JP const char *credits01[] = { "1GAME DIRECTOR", "SHIGERU MIYAMOTO" }; @@ -552,29 +553,43 @@ void check_instant_warp(void) { s16 cameraAngle; struct Surface *floor; + if (gRejectInstantWarp > 0) { + gRejectInstantWarp--; + } + if (gCurrLevelNum == LEVEL_CASTLE && save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) >= 70) { return; } - if ((floor = gMarioState->floor) != NULL) { + if ((floor = gMarioStates[0].floor) != NULL) { s32 index = floor->type - SURFACE_INSTANT_WARP_1B; if (index >= INSTANT_WARP_INDEX_START && index < INSTANT_WARP_INDEX_STOP && gCurrentArea->instantWarps != NULL) { struct InstantWarp *warp = &gCurrentArea->instantWarps[index]; - if (warp->id != 0) { - for (int i = 0; i < MAX_PLAYERS; i++) { - gMarioStates[i].pos[0] += warp->displacement[0]; - gMarioStates[i].pos[1] += warp->displacement[1]; - gMarioStates[i].pos[2] += warp->displacement[2]; + if (gRejectInstantWarp > 0) { + vec3f_copy(gMarioStates[0].pos, gMarioStates[0].nonInstantWarpPos); + //vec3f_mul(gMarioStates[0].vel, -0.8f); + return; + } + u8 changeOfArea = (gCurrAreaIndex != warp->area); + gMarioStates[0].pos[0] += warp->displacement[0]; + gMarioStates[0].pos[1] += warp->displacement[1]; + gMarioStates[0].pos[2] += warp->displacement[2]; + vec3f_copy(gMarioStates[0].nonInstantWarpPos, gMarioStates[0].pos); - gMarioStates[i].marioObj->oPosX = gMarioStates[i].pos[0]; - gMarioStates[i].marioObj->oPosY = gMarioStates[i].pos[1]; - gMarioStates[i].marioObj->oPosZ = gMarioStates[i].pos[2]; + if (changeOfArea) { + for (int i = 0; i < MAX_PLAYERS; i++) { + gMarioStates[i].marioObj->oIntangibleTimer = 30; + } } - cameraAngle = gMarioState->area->camera->yaw; + gMarioStates[0].marioObj->oPosX = gMarioStates[0].pos[0]; + gMarioStates[0].marioObj->oPosY = gMarioStates[0].pos[1]; + gMarioStates[0].marioObj->oPosZ = gMarioStates[0].pos[2]; + + cameraAngle = gMarioStates[0].area->camera->yaw; change_area(warp->area); for (int i = 0; i < MAX_PLAYERS; i++) { @@ -582,10 +597,17 @@ void check_instant_warp(void) { } warp_camera(warp->displacement[0], warp->displacement[1], warp->displacement[2]); - gMarioState->area->camera->yaw = cameraAngle; + gMarioStates[0].area->camera->yaw = cameraAngle; + + if (changeOfArea) { + set_play_mode(PLAY_MODE_SYNC_LEVEL); + network_send_instant_warp(); + } + return; } } } + vec3f_copy(gMarioStates[0].nonInstantWarpPos, gMarioStates[0].pos); } s16 music_changed_through_warp(s16 arg) { diff --git a/src/game/level_update.h b/src/game/level_update.h index 0fd1600f9..eeea9baac 100644 --- a/src/game/level_update.h +++ b/src/game/level_update.h @@ -95,6 +95,7 @@ struct SavedWarpValues { extern struct WarpDest sWarpDest; extern s8 gInWarpCheckpoint; +extern u8 gRejectInstantWarp; extern s16 D_80339EE0; extern s16 sDelayedWarpOp; diff --git a/src/game/screen_transition.c b/src/game/screen_transition.c index 8d464ed8a..fd338037c 100644 --- a/src/game/screen_transition.c +++ b/src/game/screen_transition.c @@ -20,8 +20,8 @@ static Gfx *sScreenTransitionVerticesPos[2]; static Vtx *sScreenTransitionVertices; void reset_screen_transition_timers(void) { - memset(sTransitionColorFadeCount, 0, sizeof(u8) * 4); - memset(sTransitionTextureFadeCount, 0, sizeof(u16) * 2); + for (int i = 0; i < 4; i++) { sTransitionColorFadeCount[i] = 0; } + for (int i = 0; i < 2; i++) { sTransitionTextureFadeCount[i] = 0; } } void patch_screen_transition_interpolated(void) { diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index 56b2da762..6e634a915 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -37,6 +37,7 @@ void packet_receive(struct Packet* p) { case PACKET_KEEP_ALIVE: network_receive_keep_alive(p); break; case PACKET_LEAVING: network_receive_leaving(p); break; case PACKET_SAVE_FILE: network_receive_save_file(p); break; + case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break; /// case PACKET_CUSTOM: network_receive_custom(p); break; default: LOG_ERROR("received unknown packet: %d", p->buffer[0]); diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index ff0a73dc4..ba7a940b0 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -29,6 +29,7 @@ enum PacketType { PACKET_KEEP_ALIVE, PACKET_LEAVING, PACKET_SAVE_FILE, + PACKET_INSTANT_WARP, /// PACKET_CUSTOM = 255, }; @@ -150,4 +151,8 @@ void network_receive_leaving(struct Packet* p); void network_send_save_file(s32 fileIndex); void network_receive_save_file(struct Packet* p); +// packet_instant_warp.c +void network_send_instant_warp(void); +void network_receive_instant_warp(struct Packet* p); + #endif diff --git a/src/pc/network/packets/packet_instant_warp.c b/src/pc/network/packets/packet_instant_warp.c new file mode 100644 index 000000000..f07539130 --- /dev/null +++ b/src/pc/network/packets/packet_instant_warp.c @@ -0,0 +1,94 @@ +#include +#include "sm64.h" +#include "../network.h" +#include "engine/math_util.h" +#include "game/level_update.h" +#include "game/area.h" +#include "game/ingame_menu.h" +#define DISABLE_MODULE_LOG +#include "pc/debuglog.h" + +extern u8 gRejectInstantWarp; + +static u8 seqId = 0; +static u8 remoteLastSeqId = (u8)-1; + +#pragma pack(1) +struct PacketInstantWarpData { + u8 seqId; + Vec3f pos; + s16 areaIndex; + s16 yaw; +}; + +static void populate_packet_data(struct PacketInstantWarpData* data) { + data->seqId = seqId; + data->pos[0] = gMarioStates[0].pos[0]; + data->pos[1] = gMarioStates[0].pos[1]; + data->pos[2] = gMarioStates[0].pos[2]; + data->yaw = gMarioStates[0].faceAngle[1]; + data->areaIndex = gCurrAreaIndex; +} + +void network_send_instant_warp(void) { + + struct PacketInstantWarpData data = { 0 }; + populate_packet_data(&data); + + struct Packet p; + packet_init(&p, PACKET_INSTANT_WARP, true, false); + packet_write(&p, &data, sizeof(struct PacketInstantWarpData)); + network_send(&p); + LOG_INFO("tx %d", data.areaIndex); + + gRejectInstantWarp = 120; + + seqId++; +} + +void network_receive_instant_warp(struct Packet* p) { + struct PacketInstantWarpData remote = { 0 }; + packet_read(p, &remote, sizeof(struct PacketInstantWarpData)); + + // de-dup + if (remote.seqId == remoteLastSeqId) { + LOG_INFO("we've seen this packet, escape!"); + return; + } + remoteLastSeqId = remote.seqId; + + LOG_INFO("rx instant warp"); + + if (gCurrAreaIndex == remote.areaIndex) { + if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { sCurrPlayMode = PLAY_MODE_NORMAL; } + LOG_INFO("instant warp done %d", remote.areaIndex); + return; + } + + gMarioStates[0].pos[0] = remote.pos[0]; + gMarioStates[0].pos[1] = remote.pos[1]; + gMarioStates[0].pos[2] = remote.pos[2]; + vec3f_copy(gMarioStates[0].nonInstantWarpPos, gMarioStates[0].pos); + + gMarioStates[0].marioObj->oPosX = gMarioStates[0].pos[0]; + gMarioStates[0].marioObj->oPosY = gMarioStates[0].pos[1]; + gMarioStates[0].marioObj->oPosZ = gMarioStates[0].pos[2]; + + /*gMarioStates[0].faceAngle[1] = remote.yaw; + gMarioStates[0].intendedYaw = remote.yaw; + gMarioStates[0].marioObj->oMoveAngleYaw = remote.yaw; + gMarioStates[0].marioObj->oFaceAngleYaw = remote.yaw;*/ + + for (int i = 0; i < MAX_PLAYERS; i++) { + gMarioStates[i].marioObj->oIntangibleTimer = 30; + } + + //s16 cameraAngle = gMarioStates[0].area->camera->yaw; + change_area(remote.areaIndex); + for (int i = 0; i < MAX_PLAYERS; i++) { gMarioStates[i].area = gCurrentArea; } + + //warp_camera(warp->displacement[0], warp->displacement[1], warp->displacement[2]); + //gMarioStates[0].area->camera->yaw = cameraAngle; + LOG_INFO("instant warp applied %d", remote.areaIndex); + network_send_instant_warp(); +}