From 843a8cd18f4d8bd36745b135da1fe1485205d3b7 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 5 Apr 2021 03:21:37 +0300 Subject: [PATCH] djoslin0's new warp code --- build-windows-visual-studio/sm64ex.vcxproj | 1 + .../sm64ex.vcxproj.filters | 3 + developer/network.sh | 6 +- developer/proto-4.sh | 23 +-- src/game/area.c | 18 ++- src/game/level_update.c | 28 ++-- src/game/level_update.h | 4 + src/pc/network/packets/packet.c | 1 + src/pc/network/packets/packet.h | 6 + src/pc/network/packets/packet_level_warp_2.c | 143 ++++++++++++++++++ 10 files changed, 191 insertions(+), 42 deletions(-) create mode 100644 src/pc/network/packets/packet_level_warp_2.c diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index dc68a31d2..d536ee689 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -3974,6 +3974,7 @@ + diff --git a/build-windows-visual-studio/sm64ex.vcxproj.filters b/build-windows-visual-studio/sm64ex.vcxproj.filters index 49a460886..a41039554 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj.filters +++ b/build-windows-visual-studio/sm64ex.vcxproj.filters @@ -15087,6 +15087,9 @@ Source Files\src\game + + Source Files\src\pc\network\packets + diff --git a/developer/network.sh b/developer/network.sh index 795ded532..8d0b2e08f 100644 --- a/developer/network.sh +++ b/developer/network.sh @@ -18,9 +18,9 @@ fi #exit # no debug, direct -#$FILE --server 27015 --configfile sm64config_server.txt & -#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & -#exit +$FILE --server 27015 --configfile sm64config_server.txt & +$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & +exit # debug on server #$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & diff --git a/developer/proto-4.sh b/developer/proto-4.sh index 623295c62..128afe9c8 100644 --- a/developer/proto-4.sh +++ b/developer/proto-4.sh @@ -12,26 +12,6 @@ if [ ! -f "$FILE" ]; then FILE=./build/us_pc/sm64.us.f3dex2e fi -# no debug, discord -#$FILE --discord 2 --configfile sm64config_server.txt & -#$FILE --discord 1 --configfile sm64config_client.txt & -#exit - -# no debug, direct -#$FILE --server 27015 --configfile sm64config_server.txt & -#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & -#exit - -# debug on server -#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & -#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_server.txt' -ex 'quit' -#exit - -################### -# debug on client # -################### - -#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_p1.txt' -ex 'quit' $FILE --server 27015 --configfile sm64config_p1.txt & sleep 2 $FILE --client 127.0.0.1 27015 --configfile sm64config_p2.txt & @@ -39,4 +19,7 @@ sleep 2 $FILE --client 127.0.0.1 27015 --configfile sm64config_p3.txt & sleep 2 $FILE --client 127.0.0.1 27015 --configfile sm64config_p4.txt & + +#sleep 2 +#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_p1.txt' -ex 'quit' #winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --client 127.0.0.1 27015 --configfile sm64config_p4.txt' -ex 'quit' diff --git a/src/game/area.c b/src/game/area.c index aff256358..cafd4207d 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -257,6 +257,15 @@ void load_area(s32 index) { load_obj_warp_nodes(); geo_call_global_function_nodes(&gCurrentArea->unk04->node, GEO_CONTEXT_AREA_LOAD); } + + if (!network_is_warp_2_duplicate()) { + if (gNetworkType != NT_NONE) { + network_send_level_warp_2(TRUE, gNetworkPlayerLocal->globalIndex); + } + if (gNetworkType == NT_CLIENT) { + sCurrPlayMode = PLAY_MODE_SYNC_LEVEL; + } + } } void unload_area(void) { @@ -442,15 +451,8 @@ void render_game(void) { } // only render 'synchronizing' text if we've been waiting for a while - static u8 syncLevelTime = 0; if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { - if (syncLevelTime < 30) { - syncLevelTime++; - } else { - render_sync_level_screen(); - } - } else { - syncLevelTime = 0; + render_sync_level_screen(); } D_8032CE74 = NULL; diff --git a/src/game/level_update.c b/src/game/level_update.c index 52d8def9f..a334233a4 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -53,6 +53,10 @@ u8 gControlledWarpGlobalIndex = 0; extern s8 sReceivedLoadedActNum; u8 gRejectInstantWarp = 0; +s16 gChangeLevel = -1; +s16 gChangeAreaIndex = -1; +s16 gChangeActNum = -1; + #ifdef VERSION_JP const char *credits01[] = { "1GAME DIRECTOR", "SHIGERU MIYAMOTO" }; const char *credits02[] = { "2ASSISTANT DIRECTORS", "YOSHIAKI KOIZUMI", "TAKASHI TEZUKA" }; @@ -1090,15 +1094,9 @@ s32 play_mode_normal(void) { } } else if (!gReceiveWarp.received) { if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL) { - set_play_mode(PLAY_MODE_SYNC_LEVEL); - network_send_level_warp_begin(); + set_play_mode(PLAY_MODE_CHANGE_LEVEL); } else if (sTransitionTimer != 0) { - if (sWarpDest.type == WARP_TYPE_CHANGE_AREA) { - set_play_mode(PLAY_MODE_SYNC_LEVEL); - network_send_level_warp_begin(); - } else { - set_play_mode(PLAY_MODE_CHANGE_AREA); - } + set_play_mode(PLAY_MODE_CHANGE_AREA); } else if (sCurrPlayMode == PLAY_MODE_NORMAL && pressed_pause()) { lower_background_noise(1); cancel_rumble(); @@ -1129,8 +1127,7 @@ s32 play_mode_paused(void) { fade_into_special_warp(0, 0); gSavedCourseNum = COURSE_NONE; } - set_play_mode(PLAY_MODE_SYNC_LEVEL); - network_send_level_warp_begin(); + set_play_mode(PLAY_MODE_CHANGE_LEVEL); } else if (gPauseScreenMode == 3) { // We should only be getting "int 3" to here initiate_warp(LEVEL_CASTLE, 1, 0x1F, 0); @@ -1150,7 +1147,7 @@ s32 play_mode_sync_level(void) { set_menu_mode(-1); gCameraMovementFlags &= ~CAM_MOVE_PAUSE_SCREEN; - check_received_warp(); + //check_received_warp(); return 0; } @@ -1262,6 +1259,15 @@ static s32 play_mode_unused(void) { s32 update_level(void) { s32 changeLevel = 0; + if (gChangeLevel != -1) { + gHudDisplay.flags = HUD_DISPLAY_NONE; + sTransitionTimer = 0; + sTransitionUpdate = NULL; + changeLevel = gChangeLevel; + gChangeLevel = -1; + return changeLevel; + } + switch (sCurrPlayMode) { case PLAY_MODE_NORMAL: changeLevel = play_mode_normal(); diff --git a/src/game/level_update.h b/src/game/level_update.h index eeea9baac..52f5d9a2e 100644 --- a/src/game/level_update.h +++ b/src/game/level_update.h @@ -76,6 +76,10 @@ extern s16 sTransitionTimer; extern void (*sTransitionUpdate)(s16 *); extern u8 unused3[4]; +extern s16 gChangeLevel; +extern s16 gChangeAreaIndex; +extern s16 gChangeActNum; + struct WarpDest { u8 type; u8 levelNum; diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index 800cc8db6..b7d44f683 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -56,6 +56,7 @@ void packet_receive(struct Packet* p) { case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break; case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break; case PACKET_DEATH: network_receive_death(p); break; + case PACKET_LEVEL_WARP_2: network_receive_level_warp_2(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 e14b0db3c..2f2835f90 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -33,6 +33,7 @@ enum PacketType { PACKET_INSTANT_WARP, PACKET_NETWORK_PLAYERS, PACKET_DEATH, + PACKET_LEVEL_WARP_2, /// PACKET_CUSTOM = 255, }; @@ -171,4 +172,9 @@ void network_receive_network_players(struct Packet* p); void network_send_death(void); void network_receive_death(struct Packet* p); +// packet_level_warp_2.c +void network_send_level_warp_2(u8 eventBegins, u8 controlledGlobalIndex); +void network_receive_level_warp_2(struct Packet* p); +u8 network_is_warp_2_duplicate(void); + #endif diff --git a/src/pc/network/packets/packet_level_warp_2.c b/src/pc/network/packets/packet_level_warp_2.c new file mode 100644 index 000000000..9cb574d43 --- /dev/null +++ b/src/pc/network/packets/packet_level_warp_2.c @@ -0,0 +1,143 @@ +#include "../network.h" +#include "game/level_update.h" +#include "game/object_list_processor.h" +//#define DISABLE_MODULE_LOG +#include "pc/debuglog.h" + +#define SERVER_RETAIN_WARP_SECONDS 1 + +extern u8 gControlledWarpGlobalIndex; +extern float gPaintingMarioYEntry; + +#pragma pack(1) +struct PacketLevelWarp2Data { + s16 levelNum; + s16 areaIndex; + s16 actNum; + + u8 warpType; + u8 warpLevelNum; + u8 warpAreaIdx; + u8 warpNodeId; + u32 warpArg; + + s8 inWarpCheckpoint; + s16 ttcSpeedSetting; + s16 D_80339EE0; + f32 paintingMarioYEntry; + u8 controlledWarpGlobalIndex; +}; + +struct PacketLevelWarp2Data sSavedLevelWarp2Data = { 0 }; +static clock_t sSavedClockTime = 0; + +static void populate_packet_data(struct PacketLevelWarp2Data* data) { + data->levelNum = gCurrLevelNum; + data->areaIndex = gCurrAreaIndex; + data->actNum = gCurrActNum; + + data->warpType = sWarpDest.type; + data->warpLevelNum = sWarpDest.levelNum; + data->warpAreaIdx = sWarpDest.areaIdx; + data->warpNodeId = sWarpDest.nodeId; + data->warpArg = sWarpDest.arg; + + data->inWarpCheckpoint = gInWarpCheckpoint; + data->ttcSpeedSetting = gTTCSpeedSetting; + data->D_80339EE0 = D_80339EE0; + data->paintingMarioYEntry = gPaintingMarioYEntry; + data->controlledWarpGlobalIndex = gControlledWarpGlobalIndex; +} + +void network_send_level_warp_2(u8 eventBegins, u8 controlledGlobalIndex) { + struct PacketLevelWarp2Data data = { 0 }; + if (eventBegins) { + gControlledWarpGlobalIndex = controlledGlobalIndex; + populate_packet_data(&data); + if (gNetworkType == NT_SERVER) { + sSavedLevelWarp2Data = data; + sSavedClockTime = clock(); + } + } else { + data = sSavedLevelWarp2Data; + } + + struct Packet p; + packet_init(&p, PACKET_LEVEL_WARP_2, true, false); + packet_write(&p, &data, sizeof(struct PacketLevelWarp2Data)); + + if (gNetworkType == NT_SERVER) { + network_send(&p); + } else { + network_send_to(gNetworkPlayerServer->localIndex, &p); + } + + LOG_INFO("send warp: %d, %d, %d", gCurrLevelNum, gCurrAreaIndex, gCurrActNum); +} + +static void do_warp(struct PacketLevelWarp2Data* data) { + if (gCurrLevelNum != data->levelNum ) { gChangeLevel = data->levelNum; } + + sWarpDest.type = data->warpType; + sWarpDest.levelNum = data->warpLevelNum; + sWarpDest.areaIdx = data->warpAreaIdx; + sWarpDest.nodeId = data->warpNodeId; + sWarpDest.arg = data->warpArg; + + gInWarpCheckpoint = data->inWarpCheckpoint; + gTTCSpeedSetting = data->ttcSpeedSetting; + D_80339EE0 = data->D_80339EE0; + gPaintingMarioYEntry = data->paintingMarioYEntry; + gControlledWarpGlobalIndex = data->controlledWarpGlobalIndex; + + gCurrLevelNum = data->levelNum; + gCurrAreaIndex = data->areaIndex; + gCurrActNum = data->actNum; + + LOG_INFO("do warp: %d, %d, %d", gCurrLevelNum, gCurrAreaIndex, gCurrActNum); +} + +void network_receive_level_warp_2(struct Packet* p) { + struct PacketLevelWarp2Data remote = { 0 }; + packet_read(p, &remote, sizeof(struct PacketLevelWarp2Data)); + LOG_INFO("rx warp: %d, %d, %d", remote.levelNum, remote.areaIndex, remote.actNum); + + u8 levelOrAreaDifference = (gCurrLevelNum != remote.levelNum) || (gCurrAreaIndex != remote.areaIndex); + + if (gNetworkType == NT_SERVER) { + f32 elapsed = (clock() - sSavedClockTime) / (f32)CLOCKS_PER_SEC; + if (elapsed < SERVER_RETAIN_WARP_SECONDS || !levelOrAreaDifference) { + network_send_level_warp_2(FALSE, gNetworkPlayerLocal->globalIndex); + return; + } + } + + if (levelOrAreaDifference) { + do_warp(&remote); + } + + if (gNetworkType == NT_CLIENT) { + sSavedLevelWarp2Data = remote; + sSavedClockTime = clock(); + } + + if (gNetworkType == NT_SERVER) { + network_send_level_warp_2(TRUE, remote.controlledWarpGlobalIndex); + } else { + sCurrPlayMode = PLAY_MODE_NORMAL; + network_on_init_level(); + } +} + +u8 network_is_warp_2_duplicate(void) { + struct PacketLevelWarp2Data data = { 0 }; + populate_packet_data(&data); + + if (data.levelNum == 1 && data.areaIndex == 1) { return TRUE; } + + if (gNetworkType == NT_SERVER) { + f32 elapsed = (clock() - sSavedClockTime) / (f32)CLOCKS_PER_SEC; + if (elapsed >= SERVER_RETAIN_WARP_SECONDS) { return FALSE; } + } + return (memcmp(&sSavedLevelWarp2Data, &data, sizeof(struct PacketLevelWarp2Data)) == 0); +} \ No newline at end of file