diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index d536ee689..7864faca1 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -3967,14 +3967,11 @@ - + - - - diff --git a/build-windows-visual-studio/sm64ex.vcxproj.filters b/build-windows-visual-studio/sm64ex.vcxproj.filters index a41039554..5689ffd79 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj.filters +++ b/build-windows-visual-studio/sm64ex.vcxproj.filters @@ -14967,15 +14967,9 @@ Source Files\src\pc\network\packets - - Source Files\src\pc\network\packets - Source Files\src\pc\network\packets - - Source Files\src\pc\network\packets - Source Files\src\pc\network\packets @@ -15069,9 +15063,6 @@ Source Files\src\pc\network\packets - - Source Files\src\pc\network\packets - Source Files\src\pc\utils @@ -15087,7 +15078,7 @@ Source Files\src\game - + Source Files\src\pc\network\packets diff --git a/developer/network.sh b/developer/network.sh index 8d0b2e08f..b274aefee 100644 --- a/developer/network.sh +++ b/developer/network.sh @@ -19,6 +19,7 @@ fi # no debug, direct $FILE --server 27015 --configfile sm64config_server.txt & +sleep 7 $FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & exit diff --git a/developer/proto-4.sh b/developer/proto-4.sh index 128afe9c8..307d92518 100644 --- a/developer/proto-4.sh +++ b/developer/proto-4.sh @@ -13,7 +13,7 @@ if [ ! -f "$FILE" ]; then fi $FILE --server 27015 --configfile sm64config_p1.txt & -sleep 2 +sleep 4 $FILE --client 127.0.0.1 27015 --configfile sm64config_p2.txt & sleep 2 $FILE --client 127.0.0.1 27015 --configfile sm64config_p3.txt & diff --git a/include/types.h b/include/types.h index 41195c5fc..17750c932 100644 --- a/include/types.h +++ b/include/types.h @@ -386,7 +386,6 @@ struct MarioState #define PLAY_MODE_CHANGE_AREA 3 #define PLAY_MODE_CHANGE_LEVEL 4 #define PLAY_MODE_FRAME_ADVANCE 5 -#define PLAY_MODE_SYNC_LEVEL 6 // NOTE: this defines the maximum number of players... // HOWEVER, simply increasing this to 3 will not magically work diff --git a/src/game/area.c b/src/game/area.c index cafd4207d..ec7eafa73 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -257,15 +257,6 @@ 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) { @@ -450,11 +441,6 @@ void render_game(void) { } } - // only render 'synchronizing' text if we've been waiting for a while - if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { - render_sync_level_screen(); - } - D_8032CE74 = NULL; D_8032CE78 = 0; } diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 4911373d6..bbf2c76dd 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -2823,50 +2823,6 @@ s16 render_pause_courses_and_castle(void) { return 0; } -s16 render_sync_level_screen(void) { - char* message; - - if (gNetworkType == NT_SERVER) { - message = network_player_any_connected() ? "Waiting for player..." : "Waiting for player to connect..."; - } else { - message = network_player_any_connected() ? "Waiting for player..." : "Not connected to anyone.\nPlease restart the game."; - } - - static f32 alphaScalar = 0.0f; - static clock_t lastDisplay = 0; - f32 elapsed = (clock() - lastDisplay) / (f32)CLOCKS_PER_SEC; - if (elapsed > 1.0f) { - alphaScalar = 0; - } else if (alphaScalar < 1.0f) { - alphaScalar += 0.3f; - if (alphaScalar > 1) { alphaScalar = 1; } - } - u8 alpha = (((f32)fabs(sin(gGlobalTimer / 20.0f)) * alphaScalar) * 255); - lastDisplay = clock(); - - // black screen - create_dl_translation_matrix(MENU_MTX_PUSH, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 240.0f, 0); - create_dl_scale_matrix(MENU_MTX_NOPUSH, GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT / 130.0f, 3.0f, 1.0f); - gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255); - gSPDisplayList(gDisplayListHead++, dl_draw_text_bg_box); - gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - - // print text - gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); - f32 textWidth = get_generic_ascii_string_width(message); - f32 textHeight = get_generic_ascii_string_height(message); - - f32 xPos = (SCREEN_WIDTH - textWidth) / 2.0f; - f32 yPos = (SCREEN_HEIGHT + textHeight) / 2.0f; - - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, alpha); - print_generic_ascii_string(xPos, yPos, message); - - gSPDisplayList(gDisplayListHead++, dl_ia_text_end); - - return 0; -} - #if defined(VERSION_JP) || defined(VERSION_SH) #define TXT_HISCORE_X 112 #define TXT_HISCORE_Y 48 diff --git a/src/game/ingame_menu.h b/src/game/ingame_menu.h index 10a140058..dee0d3c47 100644 --- a/src/game/ingame_menu.h +++ b/src/game/ingame_menu.h @@ -153,7 +153,6 @@ void do_cutscene_handler(void); void render_hud_cannon_reticle(void); void reset_red_coins_collected(void); s16 render_menus_and_dialogs(void); -s16 render_sync_level_screen(void); void create_dl_scale_matrix(s8 pushOp, f32 x, f32 y, f32 z); #endif // INGAME_MENU_H diff --git a/src/game/interaction.c b/src/game/interaction.c index eb29e9398..5390638eb 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -1277,12 +1277,14 @@ u8 player_is_sliding(struct MarioState* m) { } u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) { + if (!is_player_active(m)) { return FALSE; } if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; } if (m->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; } struct MarioState* m2 = NULL; for (int i = 0; i < MAX_PLAYERS; i++) { if (o == gMarioStates[i].marioObj) { + if (!is_player_active(&gMarioStates[i])) { return FALSE; } m2 = &gMarioStates[i]; break; } diff --git a/src/game/level_update.c b/src/game/level_update.c index a334233a4..ac2ca502d 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -49,7 +49,6 @@ #define WARP_NODE_CREDITS_MIN 0xF8 struct SavedWarpValues gReceiveWarp = { 0 }; -u8 gControlledWarpGlobalIndex = 0; extern s8 sReceivedLoadedActNum; u8 gRejectInstantWarp = 0; @@ -603,13 +602,6 @@ void check_instant_warp(void) { warp_camera(warp->displacement[0], warp->displacement[1], warp->displacement[2]); gMarioStates[0].area->camera->yaw = cameraAngle; - // don't force synchronize the slide in TTM - u8 ignoreSyncingArea = (gCurrLevelNum == LEVEL_TTM && (gCurrAreaIndex == 3 || gCurrAreaIndex == 4)); - - if (changeOfArea && !ignoreSyncingArea) { - set_play_mode(PLAY_MODE_SYNC_LEVEL); - network_send_instant_warp(); - } return; } } @@ -1020,36 +1012,6 @@ void basic_update(UNUSED s16 *arg) { } } -static void check_received_warp(void) { - extern float gPaintingMarioYEntry; - if (!gReceiveWarp.received) { return; } - gReceiveWarp.received = FALSE; - - // keep do_warp(void) in sync with this - sWarpDest = gReceiveWarp.warpDest; - gInWarpCheckpoint = gReceiveWarp.inWarpCheckpoint; - gTTCSpeedSetting = gReceiveWarp.ttcSpeedSetting; - D_80339EE0 = gReceiveWarp.D_80339EE0; - gPaintingMarioYEntry = gReceiveWarp.paintingMarioYEntry; - - if (gControlledWarpGlobalIndex != gNetworkPlayerLocal->globalIndex) { - // force well behaved state - extern s16 gMenuMode; - gMenuMode = -1; - reset_dialog_render_state(); - reset_screen_transition_timers(); - } - - set_play_mode((sWarpDest.type == WARP_TYPE_CHANGE_LEVEL) - ? PLAY_MODE_CHANGE_LEVEL - : PLAY_MODE_CHANGE_AREA); - - s8 warpCourse = gLevelToCourseNumTable[sWarpDest.levelNum - 1]; - if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL && warpCourse == COURSE_NONE) { - sReceivedLoadedActNum = 0; - } -} - int gPressedStart = 0; s32 play_mode_normal(void) { @@ -1104,7 +1066,6 @@ s32 play_mode_normal(void) { set_play_mode(PLAY_MODE_PAUSED); } } - check_received_warp(); } @@ -1136,18 +1097,6 @@ s32 play_mode_paused(void) { } gCameraMovementFlags &= ~CAM_MOVE_PAUSE_SCREEN; - - check_received_warp(); - return 0; -} - -s32 play_mode_sync_level(void) { - // force unpause state - raise_background_noise(1); - set_menu_mode(-1); - gCameraMovementFlags &= ~CAM_MOVE_PAUSE_SCREEN; - - //check_received_warp(); return 0; } @@ -1289,9 +1238,6 @@ s32 update_level(void) { case PLAY_MODE_FRAME_ADVANCE: changeLevel = play_mode_frame_advance(); break; - case PLAY_MODE_SYNC_LEVEL: - changeLevel = play_mode_sync_level(); - break; } if (changeLevel) { diff --git a/src/game/mario.c b/src/game/mario.c index 953f0ccf1..ab15bb4a8 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1868,7 +1868,13 @@ s32 execute_mario_action(UNUSED struct Object *o) { // hide inactive players struct NetworkPlayer* np = &gNetworkPlayers[gMarioState->playerIndex]; if (np->type != NPT_LOCAL) { - if (!np->connected || np->currLevelNum != gCurrLevelNum || np->currAreaIndex != gCurrAreaIndex) { + bool levelAreaMismatch = + (np->currCourseNum != gCurrCourseNum + || np->currActNum != gCurrActNum + || np->currLevelNum != gCurrLevelNum + || np->currAreaIndex != gCurrAreaIndex); + + if (!np->connected || levelAreaMismatch) { gMarioState->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; gMarioState->marioObj->oIntangibleTimer = -1; return 0; diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index c50256b1a..1f5b960ed 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -517,7 +517,12 @@ u8 is_player_active(struct MarioState* m) { struct NetworkPlayer* np = &gNetworkPlayers[m->playerIndex]; if (np->type != NPT_LOCAL) { if (!np->connected) { return FALSE; } - if (np->currLevelNum != gCurrLevelNum || np->currAreaIndex != gCurrAreaIndex) { return FALSE; } + bool levelAreaMismatch = + (np->currCourseNum != gCurrCourseNum + || np->currActNum != gCurrActNum + || np->currLevelNum != gCurrLevelNum + || np->currAreaIndex != gCurrAreaIndex); + if (levelAreaMismatch) { return FALSE; } } return TRUE; } diff --git a/src/menu/star_select.c b/src/menu/star_select.c index 17fe478ea..afeb2840f 100644 --- a/src/menu/star_select.c +++ b/src/menu/star_select.c @@ -55,8 +55,6 @@ s8 sSelectableStarIndex = 0; // Act Selector menu timer that keeps counting until you choose an act. static s32 sActSelectorMenuTimer = 0; -extern u8 gControlledWarpGlobalIndex; - /** * Act Selector Star Type Loop Action * Defines a select type for a star in the act selector. @@ -177,11 +175,10 @@ void bhv_act_selector_loop(void) { // Sometimes, stars are not selectable even if they appear on the screen. // This code filters selectable and non-selectable stars. sSelectedActIndex = 0; - if (gControlledWarpGlobalIndex == gNetworkPlayerLocal->globalIndex) { - s8 oldIndex = sSelectableStarIndex; - handle_menu_scrolling(MENU_SCROLL_HORIZONTAL, &sSelectableStarIndex, 0, sObtainedStars); - if (oldIndex != sSelectableStarIndex) { network_send_inside_painting(); } - } + + s8 oldIndex = sSelectableStarIndex; + handle_menu_scrolling(MENU_SCROLL_HORIZONTAL, &sSelectableStarIndex, 0, sObtainedStars); + starIndexCounter = sSelectableStarIndex; for (i = 0; i < sVisibleStars; i++) { // Can the star be selected (is it either already completed or the first non-completed mission) @@ -195,11 +192,8 @@ void bhv_act_selector_loop(void) { } } else { // If all stars are collected then they are all selectable. - if (gControlledWarpGlobalIndex == gNetworkPlayerLocal->globalIndex) { - s8 oldIndex = sSelectableStarIndex; - handle_menu_scrolling(MENU_SCROLL_HORIZONTAL, &sSelectableStarIndex, 0, sVisibleStars - 1); - if (oldIndex != sSelectableStarIndex) { network_send_inside_painting(); } - } + s8 oldIndex = sSelectableStarIndex; + handle_menu_scrolling(MENU_SCROLL_HORIZONTAL, &sSelectableStarIndex, 0, sVisibleStars - 1); sSelectedActIndex = sSelectableStarIndex; } @@ -298,15 +292,6 @@ void print_act_selector_strings(void) { create_dl_ortho_matrix(); - // display disclaimer that the other player has to select - if (gControlledWarpGlobalIndex != gNetworkPlayerLocal->globalIndex) { - gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); - u8 a = ((gGlobalTimer % 24) >= 12) ? 160 : 130; - gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, a); - print_generic_ascii_string(66, 212, "Waiting for other player's selection..."); - gSPDisplayList(gDisplayListHead++, dl_ia_text_end); - } - #ifdef VERSION_EU switch (language) { case LANGUAGE_ENGLISH: @@ -436,7 +421,7 @@ s32 lvl_init_act_selector_values_and_stars(UNUSED s32 arg, UNUSED s32 unused) { * Also updates objects and returns act number selected after is chosen. */ s32 lvl_update_obj_and_load_act_button_actions(UNUSED s32 arg, UNUSED s32 unused) { - if ((gControlledWarpGlobalIndex == gNetworkPlayerLocal->globalIndex) && sActSelectorMenuTimer >= 11) { + if (sActSelectorMenuTimer >= 11) { // If any of these buttons are pressed, play sound and go to course act #ifndef VERSION_EU if ((gPlayer3Controller->buttonPressed & A_BUTTON) @@ -472,6 +457,4 @@ void star_select_finish_selection(void) { sLoadedActNum = sInitSelectedActNum; } gDialogCourseActNum = sSelectedActIndex + 1; - - if (gControlledWarpGlobalIndex == gNetworkPlayerLocal->globalIndex) { network_send_inside_painting(); } } diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c index c9b5790a1..ed99ae47e 100644 --- a/src/pc/controller/controller_keyboard_debug.c +++ b/src/pc/controller/controller_keyboard_debug.c @@ -7,7 +7,7 @@ #ifdef DEBUG -static u8 warpToLevel = LEVEL_WF; +static u8 warpToLevel = LEVEL_BOB; #define SCANCODE_0 0x0B #define SCANCODE_1 0x02 @@ -26,7 +26,6 @@ static void debug_breakpoint_here(void) { static void debug_warp_level(u8 level) { if (sCurrPlayMode == PLAY_MODE_CHANGE_LEVEL) { return; } - if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { return; } // find level from painting for (int i = 0; i < 45; i++) { @@ -39,8 +38,7 @@ static void debug_warp_level(u8 level) { sWarpDest.nodeId = node->destNode; sWarpDest.arg = 0; - sCurrPlayMode = PLAY_MODE_SYNC_LEVEL; - network_send_level_warp_begin(); + sCurrPlayMode = PLAY_MODE_CHANGE_LEVEL; return; } } @@ -55,8 +53,7 @@ static void debug_warp_level(u8 level) { sWarpDest.nodeId = node->destNode; sWarpDest.arg = 0; - sCurrPlayMode = PLAY_MODE_SYNC_LEVEL; - network_send_level_warp_begin(); + sCurrPlayMode = PLAY_MODE_CHANGE_LEVEL; return; } objectNode = objectNode->next; @@ -68,19 +65,15 @@ static void debug_warp_level(u8 level) { sWarpDest.areaIdx = 1; sWarpDest.nodeId = 0x1F; sWarpDest.arg = 0; - sCurrPlayMode = PLAY_MODE_SYNC_LEVEL; + sCurrPlayMode = PLAY_MODE_CHANGE_LEVEL; D_80339ECA = 0; D_80339EE0 = 0; extern s16 gSavedCourseNum; gSavedCourseNum = 0; - network_send_level_warp_begin(); } static void debug_warp_area() { - /*level_trigger_warp(&gMarioStates[0], WARP_OP_CREDITS_START); - return;*/ if (sCurrPlayMode == PLAY_MODE_CHANGE_LEVEL) { return; } - if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { return; } struct ObjectWarpNode* objectNode = gCurrentArea->warpNodes; while (objectNode != NULL) { @@ -92,8 +85,7 @@ static void debug_warp_area() { sWarpDest.nodeId = node->destNode; sWarpDest.arg = 0; - sCurrPlayMode = PLAY_MODE_SYNC_LEVEL; - network_send_level_warp_begin(); + sCurrPlayMode = PLAY_MODE_CHANGE_LEVEL; return; } objectNode = objectNode->next; diff --git a/src/pc/network/network.c b/src/pc/network/network.c index b9f9a6b79..e154408e7 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -11,6 +11,7 @@ // Mario 64 specific externs extern s16 sCurrPlayMode; +extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex; enum NetworkType gNetworkType = NT_NONE; #ifdef DISCORD_SDK @@ -87,6 +88,18 @@ void network_on_init_level(void) { } void network_on_loaded_level(void) { + // set all sync objects as staticLevelSpawn + for (int i = 0; i < MAX_SYNC_OBJECTS; i++) { + gSyncObjects[i].staticLevelSpawn = true; + } + + // check for level change + struct NetworkPlayer* np = gNetworkPlayerLocal; + if (np != NULL) { + network_send_level_area(); + network_send_entities_request(); + } + // request my chunk of reserved sync ids if (gNetworkType == NT_CLIENT) { network_send_reservation_request(); diff --git a/src/pc/network/network.h b/src/pc/network/network.h index e8f459cb4..b3d14dd0e 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -46,6 +46,7 @@ struct SyncObject { u16 reserved; float maxSyncDistance; bool owned; + bool staticLevelSpawn; clock_t clockSinceUpdate; void* behavior; u16 txEventId; diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index 8c8716ba9..6cdf8d757 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -17,14 +17,14 @@ bool network_player_any_connected(void) { u8 network_player_connected_count(void) { u8 count = 0; - for (int i = 1; i < MAX_PLAYERS; i++) { + for (int i = 0; i < MAX_PLAYERS; i++) { if (gNetworkPlayers[i].connected) { count++; } } return count; } struct NetworkPlayer* network_player_from_global_index(u8 globalIndex) { - for (int i = 1; i < MAX_PLAYERS; i++) { + for (int i = 0; i < MAX_PLAYERS; i++) { if (!gNetworkPlayers[i].connected) { continue; } if (gNetworkPlayers[i].globalIndex == globalIndex) { return &gNetworkPlayers[i]; @@ -69,12 +69,23 @@ void network_player_update(void) { u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) { if (type == NPT_LOCAL) { - memset(&gNetworkPlayers[0], 0, sizeof(struct NetworkPlayer)); - gNetworkPlayers[0].connected = true; - gNetworkPlayers[0].type = type; - gNetworkPlayers[0].localIndex = 0; - gNetworkPlayers[0].globalIndex = globalIndex; - gNetworkPlayerLocal = &gNetworkPlayers[0]; + struct NetworkPlayer* np = &gNetworkPlayers[0]; + if (np->connected) { + np->globalIndex = globalIndex; + return 0; + } + memset(np, 0, sizeof(struct NetworkPlayer)); + np->connected = true; + np->type = type; + np->localIndex = 0; + np->globalIndex = globalIndex; + np->currLevelAreaSeqId = 0; + np->currCourseNum = -1; + np->currActNum = -1; + np->currLevelNum = -1; + np->currAreaIndex = -1; + np->currAreaSyncValid = false; + gNetworkPlayerLocal = np; return 0; } @@ -96,8 +107,12 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) { if (np->connected) { continue; } memset(np, 0, sizeof(struct NetworkPlayer)); np->connected = true; + np->currLevelAreaSeqId = 0; + np->currCourseNum = -1; + np->currActNum = -1; np->currLevelNum = -1; np->currAreaIndex = -1; + np->currAreaSyncValid = false; np->fadeOpacity = 0; np->localIndex = i; np->globalIndex = (gNetworkType == NT_SERVER) ? i : globalIndex; @@ -108,10 +123,6 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) { if (type == NPT_SERVER) { gNetworkPlayerServer = np; } else { chat_add_message_ext("player connected", CMT_SYSTEM, get_player_color(np->globalIndex, 0)); } LOG_INFO("player connected, local %d, global %d", i, np->globalIndex); - extern s16 sCurrPlayMode; - if (gNetworkType == NT_SERVER && sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { - network_send_level_warp_repeat(); - } return i; } diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index 9f268ee07..dd91d2fda 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -23,8 +23,12 @@ struct NetworkPlayer { u8 localIndex; u8 globalIndex; clock_t lastReceived; + u16 currLevelAreaSeqId; + s16 currCourseNum; + s16 currActNum; s16 currLevelNum; s16 currAreaIndex; + bool currAreaSyncValid; u8 fadeOpacity; u16 rxSeqIds[MAX_RX_SEQ_IDS]; u8 onRxSeqId; diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index b7d44f683..f99378510 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -29,37 +29,40 @@ void packet_receive(struct Packet* p) { if (np->onRxSeqId >= MAX_RX_SEQ_IDS) { np->onRxSeqId = 0; } } - // check if we should drop packet - if (!packet_initial_read(p)) { LOG_ERROR("initial read failed (%d - %d)", packetType, p->levelAreaMustMatch); return; } - - switch (packetType) { - case PACKET_ACK: network_receive_ack(p); break; - case PACKET_PLAYER: network_receive_player(p); break; - case PACKET_OBJECT: network_receive_object(p); break; - case PACKET_SPAWN_OBJECTS: network_receive_spawn_objects(p); break; - case PACKET_SPAWN_STAR: network_receive_spawn_star(p); break; - case PACKET_SPAWN_STAR_NLE: network_receive_spawn_star_nle(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; - case PACKET_COLLECT_COIN: network_receive_collect_coin(p); break; - case PACKET_COLLECT_ITEM: network_receive_collect_item(p); break; - case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(p); break; - case PACKET_RESERVATION: network_receive_reservation(p); break; - case PACKET_JOIN_REQUEST: network_receive_join_request(p); break; - case PACKET_JOIN: network_receive_join(p); break; - case PACKET_CHAT: network_receive_chat(p); break; - case PACKET_KICK: network_receive_kick(p); break; - 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_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]); + // check if we should process the packet + if (packet_initial_read(p)) { + switch (packetType) { + case PACKET_ACK: network_receive_ack(p); break; + case PACKET_PLAYER: network_receive_player(p); break; + case PACKET_OBJECT: network_receive_object(p); break; + case PACKET_SPAWN_OBJECTS: network_receive_spawn_objects(p); break; + case PACKET_SPAWN_STAR: network_receive_spawn_star(p); break; + case PACKET_SPAWN_STAR_NLE: network_receive_spawn_star_nle(p); break; + case PACKET_COLLECT_STAR: network_receive_collect_star(p); break; + case PACKET_COLLECT_COIN: network_receive_collect_coin(p); break; + case PACKET_COLLECT_ITEM: network_receive_collect_item(p); break; + case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(p); break; + case PACKET_RESERVATION: network_receive_reservation(p); break; + case PACKET_JOIN_REQUEST: network_receive_join_request(p); break; + case PACKET_JOIN: network_receive_join(p); break; + case PACKET_CHAT: network_receive_chat(p); break; + case PACKET_KICK: network_receive_kick(p); break; + 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_NETWORK_PLAYERS: network_receive_network_players(p); break; + case PACKET_DEATH: network_receive_death(p); break; + case PACKET_LEVEL_AREA: network_receive_level_area(p); break; + case PACKET_LEVEL_AREA_VALID: network_receive_level_area_valid(p); break; + case PACKET_ENTITIES_REQUEST: network_receive_entities_request(p); break; + case PACKET_CLIENT_ENTITIES_REQUEST: network_receive_client_entities_request(p); break; + case PACKET_ENTITIES_RESPONSE: network_receive_entities_response(p); break; + /// + case PACKET_CUSTOM: network_receive_custom(p); break; + default: LOG_ERROR("received unknown packet: %d", p->buffer[0]); + } + } else { + //LOG_ERROR("initial read failed (%d - %d)", packetType, p->levelAreaMustMatch); } // broadcast packet diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index 77734d2dc..d430f54fe 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -16,8 +16,6 @@ enum PacketType { PACKET_SPAWN_OBJECTS, PACKET_SPAWN_STAR, PACKET_SPAWN_STAR_NLE, - PACKET_LEVEL_WARP, - PACKET_INSIDE_PAINTING, PACKET_COLLECT_STAR, PACKET_COLLECT_COIN, PACKET_COLLECT_ITEM, @@ -30,10 +28,13 @@ enum PacketType { PACKET_KEEP_ALIVE, PACKET_LEAVING, PACKET_SAVE_FILE, - PACKET_INSTANT_WARP, PACKET_NETWORK_PLAYERS, PACKET_DEATH, - PACKET_LEVEL_WARP_2, + PACKET_LEVEL_AREA, + PACKET_LEVEL_AREA_VALID, + PACKET_ENTITIES_REQUEST, + PACKET_CLIENT_ENTITIES_REQUEST, + PACKET_ENTITIES_RESPONSE, /// PACKET_CUSTOM = 255, }; @@ -102,15 +103,6 @@ void network_receive_spawn_star(struct Packet* p); void network_send_spawn_star_nle(struct Object* o, u32 params); void network_receive_spawn_star_nle(struct Packet* p); -// packet_level_warp.c -void network_send_level_warp_begin(void); -void network_send_level_warp_repeat(void); -void network_receive_level_warp(struct Packet* p); - -// packet_inside_painting.c -void network_send_inside_painting(void); -void network_receive_inside_painting(struct Packet* p); - // packet_collect_star.c void network_send_collect_star(struct Object* o, s16 coinScore, s16 starIndex); void network_receive_collect_star(struct Packet* p); @@ -160,10 +152,6 @@ 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); - // packet_network_players.c void network_send_network_players(void); void network_receive_network_players(struct Packet* p); @@ -172,9 +160,18 @@ 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); +// packet_level_area.c +void network_send_level_area(void); +void network_receive_level_area(struct Packet* p); +void network_send_level_area_valid(u8 toGlobalIndex); +void network_receive_level_area_valid(struct Packet* p); + +// packet_entities_request.c +void network_send_entities_request(void); +void network_receive_entities_request(struct Packet* p); +void network_send_client_entities_request(u8 destGlobalIndex, u8 srcGlobalIndex); +void network_receive_client_entities_request(struct Packet* p); +void network_send_entities_response(u8 destGlobalIndex); +void network_receive_entities_response(struct Packet* p); #endif diff --git a/src/pc/network/packets/packet_chat.c b/src/pc/network/packets/packet_chat.c index ed98c6dc4..487b56e78 100644 --- a/src/pc/network/packets/packet_chat.c +++ b/src/pc/network/packets/packet_chat.c @@ -15,6 +15,17 @@ static void print_sync_object_table(void) { } LOG_INFO(" "); } + +static void print_network_player_table(void) { + LOG_INFO("Network Player Table"); + LOG_INFO("%5s %8s %8s %8s %8s %8s", "id", "course", "act", "level", "area", "valid"); + for (int i = 0; i < MAX_PLAYERS; i++) { + struct NetworkPlayer* np = &gNetworkPlayers[i]; + if (!np->connected) { continue; } + LOG_INFO("%5d %8d %8d %8d %8d %8d", np->globalIndex, np->currCourseNum, np->currActNum, np->currLevelNum, np->currAreaIndex, np->currAreaSyncValid); + } + LOG_INFO(" "); +} #endif void network_send_chat(char* message, u8 rgb[3]) { @@ -28,7 +39,7 @@ void network_send_chat(char* message, u8 rgb[3]) { LOG_INFO("tx chat: %s", message); #ifdef DEVELOPMENT - print_sync_object_table(); + print_network_player_table(); #endif } @@ -47,6 +58,6 @@ void network_receive_chat(struct Packet* p) { LOG_INFO("rx chat: %s", remoteMessage); #ifdef DEVELOPMENT - print_sync_object_table(); + print_network_player_table(); #endif } diff --git a/src/pc/network/packets/packet_entities_request.c b/src/pc/network/packets/packet_entities_request.c new file mode 100644 index 000000000..bd10f88a0 --- /dev/null +++ b/src/pc/network/packets/packet_entities_request.c @@ -0,0 +1,229 @@ +#include +#include "../network.h" +#include "menu/custom_menu_system.h" +//#define DISABLE_MODULE_LOG 1 +#include "pc/debuglog.h" + +extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex; + +struct NetworkPlayer* get_network_player_from_valid_location(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex) { + for (int i = 0; i < MAX_PLAYERS; i++) { + struct NetworkPlayer* np = &gNetworkPlayers[i]; + if (!np->connected) { continue; } + if (!np->currAreaSyncValid) { continue; } + if (np->currCourseNum != courseNum) { continue; } + if (np->currActNum != actNum) { continue; } + if (np->currLevelNum != levelNum) { continue; } + if (np->currAreaIndex != areaIndex) { continue; } + return np; + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +void network_send_entities_request(void) { + if (gNetworkType == NT_SERVER) { + struct NetworkPlayer* np = get_network_player_from_valid_location(gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex); + if (np == NULL) { + gNetworkPlayerLocal->currAreaSyncValid = true; + LOG_INFO("set currAreaSyncValid to true (1)"); + return; + } + //LOG_INFO("network_send_entities_request()"); + network_send_client_entities_request(gNetworkPlayerLocal->globalIndex, np->globalIndex); + return; + } + + struct Packet p; + packet_init(&p, PACKET_ENTITIES_REQUEST, true, false); + packet_write(&p, &gCurrCourseNum, sizeof(s16)); + packet_write(&p, &gCurrActNum, sizeof(s16)); + packet_write(&p, &gCurrLevelNum, sizeof(s16)); + packet_write(&p, &gCurrAreaIndex, sizeof(s16)); + network_send_to(0, &p); + //LOG_INFO("network_send_entities_request() { %d, %d, %d, %d }", gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex); +} + +void network_receive_entities_request(struct Packet* p) { + if (gNetworkType != NT_SERVER) { + LOG_ERROR("non-server is receiving an entities request!"); + return; + } + + struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex]; + if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) { + LOG_ERROR("Receiving entities request from inactive player!"); + return; + } + + s16 courseNum, actNum, levelNum, areaIndex; + packet_read(p, &courseNum, sizeof(s16)); + packet_read(p, &actNum, sizeof(s16)); + packet_read(p, &levelNum, sizeof(s16)); + packet_read(p, &areaIndex, sizeof(s16)); + + np->currCourseNum = courseNum; + np->currActNum = actNum; + np->currLevelNum = levelNum; + np->currAreaIndex = areaIndex; + np->currAreaSyncValid = false; + LOG_INFO("set global %d's currAreaSyncValid to false", np->globalIndex); + + //LOG_INFO("network_receive_entities_request() { %d, %d, %d, %d }", courseNum, actNum, levelNum, areaIndex); + + struct NetworkPlayer* np2 = get_network_player_from_valid_location(courseNum, actNum, levelNum, areaIndex); + if (np2 == NULL) { + network_send_level_area_valid(np->globalIndex); + } else if (np2 == gNetworkPlayerLocal) { + network_send_entities_response(np->globalIndex); + } else { + network_send_client_entities_request(np->globalIndex, np2->globalIndex); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void network_send_client_entities_request(u8 destGlobalIndex, u8 srcGlobalIndex) { + if (gNetworkType != NT_SERVER) { + LOG_ERROR("client can't send a 'client entities request'"); + return; + } + + struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex); + if (destNp == NULL || !destNp->connected) { + LOG_ERROR("network_send_client_entities_request: dest np is invalid (global %d)", destGlobalIndex); + return; + } + + struct Packet p; + packet_init(&p, PACKET_CLIENT_ENTITIES_REQUEST, true, false); + packet_write(&p, &destGlobalIndex, sizeof(u8)); + packet_write(&p, &destNp->currCourseNum, sizeof(s16)); + packet_write(&p, &destNp->currActNum, sizeof(s16)); + packet_write(&p, &destNp->currLevelNum, sizeof(s16)); + packet_write(&p, &destNp->currAreaIndex, sizeof(s16)); + + //LOG_INFO("network_send_client_entities_request() { %d, %d, %d, %d, %d }", destGlobalIndex, destNp->currCourseNum, destNp->currActNum, destNp->currLevelNum, destNp->currAreaIndex); + + struct NetworkPlayer* srcNp = network_player_from_global_index(srcGlobalIndex); + if (srcNp == NULL || !srcNp->connected || !srcNp->currAreaSyncValid) { + LOG_ERROR("network_send_client_entities_request: source np is invalid (global %d)", srcGlobalIndex); + return; + } + + network_send_to(srcNp->localIndex, &p); +} + +void network_receive_client_entities_request(struct Packet* p) { + if (gNetworkType == NT_SERVER) { + LOG_ERROR("server is receiving a 'client entities request'!"); + return; + } + + u8 destGlobalIndex; + s16 courseNum, actNum, levelNum, areaIndex; + packet_read(p, &destGlobalIndex, sizeof(u8)); + packet_read(p, &courseNum, sizeof(s16)); + packet_read(p, &actNum, sizeof(s16)); + packet_read(p, &levelNum, sizeof(s16)); + packet_read(p, &areaIndex, sizeof(s16)); + + //LOG_INFO("network_receive_client_entities_request() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex); + + if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) { + LOG_ERROR("Receiving 'client entities request' with the wrong location!"); + return; + } + + network_send_entities_response(destGlobalIndex); +} + +/////////////////////////////////////////////////////////////////////////////// + +void network_send_entities_response(u8 destGlobalIndex) { + if (!gNetworkPlayerLocal->currAreaSyncValid) { + LOG_ERROR("my area is invalid"); + return; + } + + struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex); + if (destNp == NULL || !destNp->connected) { + LOG_ERROR("network_send_entities_response: dest np is invalid"); + return; + } + + struct Packet p; + packet_init(&p, PACKET_ENTITIES_RESPONSE, true, false); + packet_write(&p, &destGlobalIndex, sizeof(u8)); + packet_write(&p, &gCurrCourseNum, sizeof(s16)); + packet_write(&p, &gCurrActNum, sizeof(s16)); + packet_write(&p, &gCurrLevelNum, sizeof(s16)); + packet_write(&p, &gCurrAreaIndex, sizeof(s16)); + // TODO: write entities here! + + //LOG_INFO("network_send_entities_response() { %d, %d, %d, %d, %d } to: %d", destGlobalIndex, gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex, (gNetworkType == NT_SERVER) ? destNp->localIndex : 0); + + network_send_to((gNetworkType == NT_SERVER) ? destNp->localIndex : 0, &p); + + if (gNetworkType == NT_SERVER) { + LOG_INFO("sending response from global %d to global %d", gNetworkPlayerLocal->globalIndex, destNp->globalIndex); + } + +} + +void network_receive_entities_response(struct Packet* p) { + u8 destGlobalIndex; + s16 courseNum, actNum, levelNum, areaIndex; + packet_read(p, &destGlobalIndex, sizeof(u8)); + packet_read(p, &courseNum, sizeof(s16)); + packet_read(p, &actNum, sizeof(s16)); + packet_read(p, &levelNum, sizeof(s16)); + packet_read(p, &areaIndex, sizeof(s16)); + // TODO: read entities here! + + //LOG_INFO("network_receive_entities_response() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex); + + if (gNetworkType == NT_SERVER && gNetworkPlayerLocal->globalIndex != destGlobalIndex) { + // recreate packet and send to destination + struct Packet p2; + packet_init(&p2, PACKET_ENTITIES_RESPONSE, true, false); + packet_write(&p2, &destGlobalIndex, sizeof(u8)); + packet_write(&p2, &courseNum, sizeof(s16)); + packet_write(&p2, &actNum, sizeof(s16)); + packet_write(&p2, &levelNum, sizeof(s16)); + packet_write(&p2, &areaIndex, sizeof(s16)); + // TODO: write entities here! + + struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex); + if (destNp == NULL || !destNp->connected) { + LOG_ERROR("network_receive_entities_response: dest np is invalid"); + return; + } + struct NetworkPlayer* srcNp = &gNetworkPlayers[p->localIndex]; + LOG_INFO("sending response from global %d to global %d", srcNp->globalIndex, destNp->globalIndex); + network_send_to(destNp->localIndex, &p2); + return; + } else if (gNetworkPlayerLocal->globalIndex != destGlobalIndex) { + LOG_ERROR("Receiving 'entities response' meant for someone else!"); + return; + } + + if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) { + LOG_ERROR("Receiving 'entities response' with the wrong location!"); + return; + } + // TODO: apply entities! + + if (gNetworkType == NT_SERVER) { + struct NetworkPlayer* srcNp = &gNetworkPlayers[p->localIndex]; + LOG_INFO("sending response from global %d to global %d", srcNp->globalIndex, gNetworkPlayerLocal->globalIndex); + } + + gNetworkPlayerLocal->currAreaSyncValid = true; + LOG_INFO("set currAreaSyncValid to true (2)"); + if (gNetworkType != NT_SERVER) { + network_send_level_area_valid(0); + } + //LOG_INFO("network_receive_entities_response() ==> valid"); +} \ No newline at end of file diff --git a/src/pc/network/packets/packet_inside_painting.c b/src/pc/network/packets/packet_inside_painting.c deleted file mode 100644 index e0bccc820..000000000 --- a/src/pc/network/packets/packet_inside_painting.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include "../network.h" -#include "src/game/level_update.h" -#include "src/game/area.h" -#define DISABLE_MODULE_LOG -#include "pc/debuglog.h" - -extern u8 gControlledWarpGlobalIndex; - -extern u8 sSelectableStarIndex; -extern u8 sSelectedActIndex; -extern s8 sLoadedActNum; -extern s8 sReceivedLoadedActNum; - -#pragma pack(1) -struct PacketInsidePaintingData { - u8 starIndex; - u8 actIndex; - u8 loadedActNum; -}; - -static void populate_packet_data(struct PacketInsidePaintingData* data) { - data->starIndex = sSelectableStarIndex; - data->actIndex = sSelectedActIndex; - data->loadedActNum = sLoadedActNum; -} - -void network_send_inside_painting(void) { - struct PacketInsidePaintingData data = { 0 }; - populate_packet_data(&data); - - struct Packet p; - packet_init(&p, PACKET_INSIDE_PAINTING, true, false); - packet_write(&p, &data, sizeof(struct PacketInsidePaintingData)); - network_send(&p); -} - -void network_receive_inside_painting(struct Packet* p) { - struct PacketInsidePaintingData local = { 0 }; - populate_packet_data(&local); - - struct PacketInsidePaintingData remote = { 0 }; - packet_read(p, &remote, sizeof(struct PacketInsidePaintingData)); - - if (gControlledWarpGlobalIndex == gNetworkPlayerLocal->globalIndex) { - LOG_ERROR("this should never happen, received inside_painting when gControlledWarp"); - return; - } - - LOG_INFO("received update"); - - sSelectableStarIndex = remote.starIndex; - sSelectedActIndex = remote.actIndex; - if (sReceivedLoadedActNum == 0) { - sReceivedLoadedActNum = remote.loadedActNum; - } - - if (sReceivedLoadedActNum != 0) { - LOG_INFO("finished with painting"); - } -} - diff --git a/src/pc/network/packets/packet_instant_warp.c b/src/pc/network/packets/packet_instant_warp.c deleted file mode 100644 index c3b39bff6..000000000 --- a/src/pc/network/packets/packet_instant_warp.c +++ /dev/null @@ -1,82 +0,0 @@ -#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" -#include "game/mario.h" -#define DISABLE_MODULE_LOG -#include "pc/debuglog.h" - -extern u8 gRejectInstantWarp; - -#pragma pack(1) -struct PacketInstantWarpData { - Vec3f pos; - s16 areaIndex; - s16 yaw; -}; - -static void populate_packet_data(struct PacketInstantWarpData* data) { - 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; -} - -void network_receive_instant_warp(struct Packet* p) { - struct PacketInstantWarpData remote = { 0 }; - packet_read(p, &remote, sizeof(struct PacketInstantWarpData)); - - 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; - force_idle_state(&gMarioStates[i]); - } - - //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(); -} diff --git a/src/pc/network/packets/packet_join.c b/src/pc/network/packets/packet_join.c index ad7307ee7..ed87e20c3 100644 --- a/src/pc/network/packets/packet_join.c +++ b/src/pc/network/packets/packet_join.c @@ -11,8 +11,10 @@ #include "src/pc/fs/fs.h" #include "PR/os_eeprom.h" #include "pc/network/version.h" +#define DISABLE_MODULE_LOG 1 #include "pc/debuglog.h" + extern u8* gOverrideEeprom; static u8 eeprom[512] = { 0 }; diff --git a/src/pc/network/packets/packet_level_area.c b/src/pc/network/packets/packet_level_area.c new file mode 100644 index 000000000..84689c462 --- /dev/null +++ b/src/pc/network/packets/packet_level_area.c @@ -0,0 +1,141 @@ +#include +#include "../network.h" +#include "menu/custom_menu_system.h" +//#define DISABLE_MODULE_LOG 1 +#include "pc/debuglog.h" + +extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex; +static u16 currLevelAreaSeqId = 0; + +void network_send_level_area(void) { + struct Packet p; + currLevelAreaSeqId++; + packet_init(&p, PACKET_LEVEL_AREA, true, false); + packet_write(&p, &gNetworkPlayerLocal->globalIndex, sizeof(u8)); + packet_write(&p, &currLevelAreaSeqId, sizeof(u16)); + packet_write(&p, &gCurrCourseNum, sizeof(s16)); + packet_write(&p, &gCurrActNum, sizeof(s16)); + packet_write(&p, &gCurrLevelNum, sizeof(s16)); + packet_write(&p, &gCurrAreaIndex, sizeof(s16)); + network_send(&p); + + struct NetworkPlayer* np = gNetworkPlayerLocal; + if (np != NULL) { + np->currLevelAreaSeqId = currLevelAreaSeqId; + np->currCourseNum = gCurrCourseNum; + np->currActNum = gCurrActNum; + np->currLevelNum = gCurrLevelNum; + np->currAreaIndex = gCurrAreaIndex; + np->currAreaSyncValid = false; + + LOG_INFO("set currAreaSyncValid to false"); + } + + //LOG_INFO("tx location: [%d, %d, %d, %d]", gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex); +} + +void network_receive_level_area(struct Packet* p) { + u8 globalIndex; + u16 levelAreaSeqId; + s16 courseNum, actNum, levelNum, areaIndex; + + packet_read(p, &globalIndex, sizeof(u8)); + packet_read(p, &levelAreaSeqId, sizeof(u16)); + packet_read(p, &courseNum, sizeof(s16)); + packet_read(p, &actNum, sizeof(s16)); + packet_read(p, &levelNum, sizeof(s16)); + packet_read(p, &areaIndex, sizeof(s16)); + + struct NetworkPlayer* np = network_player_from_global_index(globalIndex); + if (np == gNetworkPlayerLocal) { + LOG_ERROR("Receiving level area from myself!"); + return; + } + + if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) { + LOG_ERROR("Receiving level area from inactive player global %d!", np->globalIndex); + return; + } + + if (levelAreaSeqId <= np->currLevelAreaSeqId) { + LOG_ERROR("Receiving old level area (%d <= %d) from local %d, global %d!", levelAreaSeqId, np->currLevelAreaSeqId, p->localIndex, np->globalIndex); + return; + } + + np->currLevelAreaSeqId = levelAreaSeqId; + np->currCourseNum = courseNum; + np->currActNum = actNum; + np->currLevelNum = levelNum; + np->currAreaIndex = areaIndex; + + //LOG_INFO("rx location: [%d, %d, %d, %d] from local %d, global %d", courseNum, actNum, levelNum, areaIndex, p->localIndex, np->globalIndex); +} + +/////////////////////////////////////////////////////////////////////////////// + +static void network_send_level_area_valid_server(u8 toGlobalIndex) { + struct NetworkPlayer* np = network_player_from_global_index(toGlobalIndex); + if (np == NULL || !np->connected) { + LOG_ERROR("tried to send level area valid to invalid player"); + return; + } + + struct Packet p; + packet_init(&p, PACKET_LEVEL_AREA_VALID, true, false); + packet_write(&p, &np->currCourseNum, sizeof(s16)); + packet_write(&p, &np->currActNum, sizeof(s16)); + packet_write(&p, &np->currLevelNum, sizeof(s16)); + packet_write(&p, &np->currAreaIndex, sizeof(s16)); + network_send_to(np->localIndex, &p); +} + +static void network_send_level_area_valid_client() { + struct Packet p; + packet_init(&p, PACKET_LEVEL_AREA_VALID, true, false); + network_send_to(0, &p); +} + +void network_send_level_area_valid(u8 toGlobalIndex) { + if (gNetworkType == NT_SERVER) { + network_send_level_area_valid_server(toGlobalIndex); + } else if (toGlobalIndex != 0) { + LOG_ERROR("client tried to send 'level area valid' to non-server"); + } else { + network_send_level_area_valid_client(); + } +} + +static void network_receive_level_area_valid_server(struct Packet* p) { + struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex]; + if (np == NULL || !np->connected) { + LOG_ERROR("network_receive_level_area_valid_server(): invalid network player"); + return; + } + np->currAreaSyncValid = true; + LOG_INFO("set global %d's currAreaSyncValid to true", np->globalIndex); +} + +static void network_receive_level_area_valid_client(struct Packet* p) { + s16 courseNum, actNum, levelNum, areaIndex; + packet_read(p, &courseNum, sizeof(s16)); + packet_read(p, &actNum, sizeof(s16)); + packet_read(p, &levelNum, sizeof(s16)); + packet_read(p, &areaIndex, sizeof(s16)); + + if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) { + LOG_ERROR("tried to validate a level area that isn't current"); + return; + } + + gNetworkPlayerLocal->currAreaSyncValid = true; + network_send_level_area_valid_client(); + LOG_INFO("set currAreaSyncValid to true (3)"); +} + +void network_receive_level_area_valid(struct Packet* p) { + if (gNetworkType == NT_SERVER) { + network_receive_level_area_valid_server(p); + } else { + network_receive_level_area_valid_client(p); + } +} diff --git a/src/pc/network/packets/packet_level_warp.c b/src/pc/network/packets/packet_level_warp.c deleted file mode 100644 index de2dd58ad..000000000 --- a/src/pc/network/packets/packet_level_warp.c +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include "sm64.h" -#include "../network.h" -#include "game/level_update.h" -#include "game/area.h" -#include "game/ingame_menu.h" -#define DISABLE_MODULE_LOG -#include "pc/debuglog.h" - -// two-player hack -// this entire system needs to be ripped out and replaced - -static u8 eventId = 0; -static u8 remoteFinishedEventId[2] = { (u8)-1, (u8)-1 }; - -extern s16 gTTCSpeedSetting; -extern s16 D_80339EE0; -extern float gPaintingMarioYEntry; -extern u8 gControlledWarpGlobalIndex; - -extern struct SavedWarpValues gReceiveWarp; -struct SavedWarpValues saved = { 0 }; - -static clock_t lastDoneEvent = 0; -static bool isInWarp = FALSE; - -#pragma pack(1) -struct PacketLevelWarpData { - u8 eventId; - u8 done; - u8 controlledWarp; - struct WarpDest warpDest; - s8 inWarpCheckpoint; - s16 ttcSpeedSetting; - s16 D_80339EE0; - f32 paintingMarioYEntry; -}; - -static void populate_packet_data(struct PacketLevelWarpData* data, bool done, u8 packetEventId) { - data->eventId = packetEventId; - data->done = done; - data->controlledWarp = gControlledWarpGlobalIndex; - data->warpDest = saved.warpDest; - data->inWarpCheckpoint = saved.inWarpCheckpoint; - data->ttcSpeedSetting = saved.ttcSpeedSetting; - data->D_80339EE0 = saved.D_80339EE0; - data->paintingMarioYEntry = saved.paintingMarioYEntry; -} - -void network_send_level_warp_begin(void) { - isInWarp = TRUE; - saved.warpDest = sWarpDest; - saved.inWarpCheckpoint = gInWarpCheckpoint; - saved.ttcSpeedSetting = gTTCSpeedSetting; - saved.D_80339EE0 = D_80339EE0; - saved.paintingMarioYEntry = gPaintingMarioYEntry; - - float elapsedSinceDone = (clock() - lastDoneEvent) / CLOCKS_PER_SEC; - gControlledWarpGlobalIndex = (elapsedSinceDone < 1.0f) - ? 0 - : gNetworkPlayerLocal->globalIndex; - - eventId++; - if (eventId == (u8)-1) { eventId++; } - LOG_INFO("new event [%d]!", eventId); - - struct PacketLevelWarpData data = { 0 }; - populate_packet_data(&data, false, eventId); - - struct Packet p; - packet_init(&p, PACKET_LEVEL_WARP, true, false); - packet_write(&p, &data, sizeof(struct PacketLevelWarpData)); - network_send(&p); -} - -void network_send_level_warp_repeat(void) { - if (!isInWarp) { - network_send_level_warp_begin(); - LOG_ERROR("sending repeat, but we're not warping!"); - return; - } - - struct PacketLevelWarpData data = { 0 }; - populate_packet_data(&data, false, eventId); - - struct Packet p; - packet_init(&p, PACKET_LEVEL_WARP, false, false); - packet_write(&p, &data, sizeof(struct PacketLevelWarpData)); - network_send(&p); -} - -static void network_send_level_warp_done(u8 remoteEventId) { - lastDoneEvent = clock(); - isInWarp = FALSE; - - struct PacketLevelWarpData data = { 0 }; - populate_packet_data(&data, true, remoteEventId); - - struct Packet p; - packet_init(&p, PACKET_LEVEL_WARP, true, false); - packet_write(&p, &data, sizeof(struct PacketLevelWarpData)); - network_send(&p); -} - -static void do_warp(void) { - // keep check_received_warp(void) in sync with this - gReceiveWarp = saved; - gReceiveWarp.received = TRUE; - gInWarpCheckpoint = saved.inWarpCheckpoint; - gTTCSpeedSetting = saved.ttcSpeedSetting; - D_80339EE0 = saved.D_80339EE0; - gPaintingMarioYEntry = saved.paintingMarioYEntry; -} - -void network_receive_level_warp(struct Packet* p) { - struct PacketLevelWarpData remote = { 0 }; - packet_read(p, &remote, sizeof(struct PacketLevelWarpData)); - - LOG_INFO("rx event [%d] last [%d, %d]", remote.eventId, remoteFinishedEventId[0], remoteFinishedEventId[1]); - - if (remote.done && remote.eventId != eventId) { - LOG_INFO("remote has finished the wrong id!"); - return; - } - - if (!remote.done) { - if (remote.eventId == remoteFinishedEventId[0] || remote.eventId == remoteFinishedEventId[1]) { - LOG_INFO("we've finished this event, escape!"); - return; - } - remoteFinishedEventId[1] = remoteFinishedEventId[0]; - remoteFinishedEventId[0] = remote.eventId; - } - - if (gNetworkType == NT_SERVER) { - if (!isInWarp && remote.done) { - LOG_INFO("client is done with warp, but so are we!"); - return; - } else if (!isInWarp) { - // client initiated warp - LOG_INFO("client initiated warp!"); - gControlledWarpGlobalIndex = remote.controlledWarp; - - saved.warpDest = remote.warpDest; - saved.inWarpCheckpoint = remote.inWarpCheckpoint; - saved.ttcSpeedSetting = remote.ttcSpeedSetting; - saved.D_80339EE0 = remote.D_80339EE0; - saved.paintingMarioYEntry = remote.paintingMarioYEntry; - - do_warp(); - network_send_level_warp_done(remote.eventId); - return; - } else if (remote.done && remote.eventId == eventId) { - // client done with warp - LOG_INFO("client is done with warp, lets-a-go!"); - do_warp(); - isInWarp = FALSE; - return; - } else { - LOG_INFO("client initiated warp, but server is already warping!"); - LOG_INFO("remote.done: %d, remote.eventId: %d!", remote.done, remote.eventId); - network_send_level_warp_repeat(); - return; - } - } - - assert(gNetworkType == NT_CLIENT); - - // server initiated warp - LOG_INFO("server initiated warp!"); - gControlledWarpGlobalIndex = remote.controlledWarp; - - saved.warpDest = remote.warpDest; - saved.inWarpCheckpoint = remote.inWarpCheckpoint; - saved.ttcSpeedSetting = remote.ttcSpeedSetting; - saved.D_80339EE0 = remote.D_80339EE0; - saved.paintingMarioYEntry = remote.paintingMarioYEntry; - - LOG_INFO("finished event [%d]!", remote.eventId); - do_warp(); - network_send_level_warp_done(remote.eventId); -} diff --git a/src/pc/network/packets/packet_level_warp_2.c b/src/pc/network/packets/packet_level_warp_2.c deleted file mode 100644 index 9cb574d43..000000000 --- a/src/pc/network/packets/packet_level_warp_2.c +++ /dev/null @@ -1,143 +0,0 @@ -#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 diff --git a/src/pc/network/packets/packet_network_players.c b/src/pc/network/packets/packet_network_players.c index eb599fbb9..6856814bc 100644 --- a/src/pc/network/packets/packet_network_players.c +++ b/src/pc/network/packets/packet_network_players.c @@ -14,13 +14,18 @@ static void network_send_to_network_players(u8 sendToLocalIndex) { struct Packet p; packet_init(&p, PACKET_NETWORK_PLAYERS, true, false); packet_write(&p, &connectedCount, sizeof(u8)); - for (int i = 1; i < MAX_PLAYERS; i++) { + for (int i = 0; i < MAX_PLAYERS; i++) { if (!gNetworkPlayers[i].connected) { continue; } u8 npType = gNetworkPlayers[i].type; if (npType == NPT_LOCAL) { npType = NPT_SERVER; } else if (i == sendToLocalIndex) { npType = NPT_LOCAL; } packet_write(&p, &npType, sizeof(u8)); - packet_write(&p, &gNetworkPlayers[i].globalIndex, sizeof(u8)); + packet_write(&p, &gNetworkPlayers[i].globalIndex, sizeof(u8)); + packet_write(&p, &gNetworkPlayers[i].currLevelAreaSeqId, sizeof(u16)); + packet_write(&p, &gNetworkPlayers[i].currCourseNum, sizeof(s16)); + packet_write(&p, &gNetworkPlayers[i].currActNum, sizeof(s16)); + packet_write(&p, &gNetworkPlayers[i].currLevelNum, sizeof(s16)); + packet_write(&p, &gNetworkPlayers[i].currAreaIndex, sizeof(s16)); LOG_INFO("send network player [%d == %d]", gNetworkPlayers[i].globalIndex, npType); } @@ -47,9 +52,26 @@ void network_receive_network_players(struct Packet* p) { packet_read(p, &connectedCount, sizeof(u8)); for (int i = 0; i < connectedCount; i++) { u8 npType, globalIndex; - packet_read(p, &npType, sizeof(u8)); - packet_read(p, &globalIndex, sizeof(u8)); - network_player_connected(npType, globalIndex); - LOG_INFO("received network player [%d == %d]", globalIndex, npType); + u16 levelAreaSeqId; + s16 courseNum, actNum, levelNum, areaIndex; + packet_read(p, &npType, sizeof(u8)); + packet_read(p, &globalIndex, sizeof(u8)); + packet_read(p, &levelAreaSeqId, sizeof(u16)); + packet_read(p, &courseNum, sizeof(s16)); + packet_read(p, &actNum, sizeof(s16)); + packet_read(p, &levelNum, sizeof(s16)); + packet_read(p, &areaIndex, sizeof(s16)); + + u8 localIndex = network_player_connected(npType, globalIndex); + LOG_INFO("received network player [%d == %d] (%d)", globalIndex, npType, localIndex); + if (localIndex != UNKNOWN_GLOBAL_INDEX && localIndex != 0) { + struct NetworkPlayer* np = &gNetworkPlayers[localIndex]; + np->currLevelAreaSeqId = levelAreaSeqId; + np->currCourseNum = courseNum; + np->currActNum = actNum; + np->currLevelNum = levelNum; + np->currAreaIndex = areaIndex; + LOG_INFO("received network player location (%d, %d, %d, %d)", courseNum, actNum, levelNum, areaIndex); + } } } \ No newline at end of file diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index 6fc584057..08be2e9ad 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -472,6 +472,7 @@ void network_forget_sync_object(struct SyncObject* so) { so->behavior = NULL; so->reserved = 0; so->owned = false; + so->staticLevelSpawn = false; } void network_update_objects(void) { diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 1f5101784..6a34e2331 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -65,9 +65,6 @@ struct PacketPlayerData { u8 interactSyncID; u8 usedSyncID; u8 platformSyncID; - - s16 currLevelNum; - s16 currAreaIndex; }; static void read_packet_data(struct PacketPlayerData* data, struct MarioState* m) { @@ -129,9 +126,6 @@ static void read_packet_data(struct PacketPlayerData* data, struct MarioState* m data->interactSyncID = interactSyncID; data->usedSyncID = usedSyncID; data->platformSyncID = platformSyncID; - - data->currLevelNum = gCurrLevelNum; - data->currAreaIndex = gCurrAreaIndex; } static void write_packet_data(struct PacketPlayerData* data, struct MarioState* m, @@ -226,13 +220,6 @@ void network_receive_player(struct Packet* p) { return; } - // check player level/area - u8 levelAreaMismatch = TRUE; - np->currLevelNum = data.currLevelNum; - np->currAreaIndex = data.currAreaIndex; - levelAreaMismatch = (data.currLevelNum != gCurrLevelNum || data.currAreaIndex != gCurrAreaIndex); - if (levelAreaMismatch) { np->fadeOpacity = 0; return; } - // apply data from packet to mario state u8 heldSyncID = 0; u8 heldBySyncID = 0; diff --git a/src/pc/network/packets/packet_read_write.c b/src/pc/network/packets/packet_read_write.c index 4376b497f..3f00358ab 100644 --- a/src/pc/network/packets/packet_read_write.c +++ b/src/pc/network/packets/packet_read_write.c @@ -31,6 +31,8 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl packet_set_flags(packet); if (levelAreaMustMatch) { + packet_write(packet, &gCurrCourseNum, sizeof(s16)); + packet_write(packet, &gCurrActNum, sizeof(s16)); packet_write(packet, &gCurrLevelNum, sizeof(s16)); packet_write(packet, &gCurrAreaIndex, sizeof(s16)); } @@ -58,14 +60,18 @@ u8 packet_initial_read(struct Packet* packet) { packet->requestBroadcast = GET_BIT(flags, 1); if (packet->levelAreaMustMatch) { - s16 currLevelNum; - s16 currAreaIndex; + s16 currCourseNum, currActNum, currLevelNum, currAreaIndex; + packet_read(packet, &currCourseNum, sizeof(s16)); + packet_read(packet, &currActNum, sizeof(s16)); packet_read(packet, &currLevelNum, sizeof(s16)); packet_read(packet, &currAreaIndex, sizeof(s16)); - if (currLevelNum != gCurrLevelNum || currAreaIndex != gCurrAreaIndex) { - // drop packet - return FALSE; - } + bool levelAreaMismatch = + (currCourseNum != gCurrCourseNum + || currActNum != gCurrActNum + || currLevelNum != gCurrLevelNum + || currAreaIndex != gCurrAreaIndex); + // drop packet + if (levelAreaMismatch) { return FALSE; } } // don't drop packet diff --git a/src/pc/network/packets/packet_reservation.c b/src/pc/network/packets/packet_reservation.c index 61b6ed1b7..a89660d18 100644 --- a/src/pc/network/packets/packet_reservation.c +++ b/src/pc/network/packets/packet_reservation.c @@ -6,6 +6,7 @@ #include "course_table.h" #include "src/game/interaction.h" #include "src/engine/math_util.h" +#define DISABLE_MODULE_LOG 1 #include "pc/debuglog.h" #define RESERVATION_COUNT 10 diff --git a/src/pc/network/packets/packet_spawn_objects.c b/src/pc/network/packets/packet_spawn_objects.c index 311d8eb58..10079f170 100644 --- a/src/pc/network/packets/packet_spawn_objects.c +++ b/src/pc/network/packets/packet_spawn_objects.c @@ -8,6 +8,7 @@ #define MAX_SPAWN_OBJECTS_PER_PACKET 8 +#pragma pack(1) struct SpawnObjectData { u8 parentId; u32 model;