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;