mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-01-22 15:43:18 -05:00
Ripped out level synchronization/warp code
Began writing new system that synchronizes course/act/level/area per player and 'ownership' of that location.
This commit is contained in:
parent
48c2d91eef
commit
bbdc942501
34 changed files with 552 additions and 728 deletions
|
@ -3967,14 +3967,11 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_collect_item.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_collect_star.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_custom.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_instant_warp.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_death.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_kick.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_inside_painting.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_join.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_keep_alive.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_leaving.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_warp.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_warp_2.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_network_players.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_object.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_player.c" />
|
||||
|
|
|
@ -14967,15 +14967,9 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_warp.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reliable.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_inside_painting.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_collect_star.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
|
@ -15069,9 +15063,6 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_leaving.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_instant_warp.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\utils\string_linked_list.c">
|
||||
<Filter>Source Files\src\pc\utils</Filter>
|
||||
</ClCompile>
|
||||
|
@ -15087,7 +15078,7 @@
|
|||
<ClCompile Include="..\src\game\characters.c">
|
||||
<Filter>Source Files\src\game</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_warp_2.c">
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_death.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 &
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(); }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -46,6 +46,7 @@ struct SyncObject {
|
|||
u16 reserved;
|
||||
float maxSyncDistance;
|
||||
bool owned;
|
||||
bool staticLevelSpawn;
|
||||
clock_t clockSinceUpdate;
|
||||
void* behavior;
|
||||
u16 txEventId;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
229
src/pc/network/packets/packet_entities_request.c
Normal file
229
src/pc/network/packets/packet_entities_request.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include <stdio.h>
|
||||
#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");
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#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");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#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();
|
||||
}
|
|
@ -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 };
|
||||
|
||||
|
|
141
src/pc/network/packets/packet_level_area.c
Normal file
141
src/pc/network/packets/packet_level_area.c
Normal file
|
@ -0,0 +1,141 @@
|
|||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#define MAX_SPAWN_OBJECTS_PER_PACKET 8
|
||||
|
||||
#pragma pack(1)
|
||||
struct SpawnObjectData {
|
||||
u8 parentId;
|
||||
u32 model;
|
||||
|
|
Loading…
Reference in a new issue