diff --git a/developer/network.sh b/developer/network.sh index 259bb615..126e29d4 100644 --- a/developer/network.sh +++ b/developer/network.sh @@ -19,7 +19,7 @@ fi # no debug, direct $FILE --server 27015 --configfile sm64config_server.txt & -sleep 5 +sleep 3 $FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & exit diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index 11949f8a..86a48059 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -136,107 +136,96 @@ void network_player_update(void) { } u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, u8 paletteIndex, char* name) { + // translate globalIndex to localIndex + u8 localIndex = globalIndex; + if (gNetworkType == NT_SERVER) { + localIndex = globalIndex; + } else if (type == NPT_SERVER) { + localIndex = 1; + } else if (type == NPT_LOCAL) { + localIndex = 0; + } else if (gNetworkPlayerLocal != NULL) { + localIndex = globalIndex + ((globalIndex < gNetworkPlayerLocal->globalIndex) ? 1 : 0); + } else { + assert(false); + } + struct NetworkPlayer* np = &gNetworkPlayers[localIndex]; + // ensure that a name is given if (name[0] == '\0') { name = sDefaultPlayerName; } if (modelIndex >= CT_MAX) { modelIndex = 0; } - if (type == NPT_LOCAL) { - 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; + // if already connected, update a few things + if (np->connected) { + np->lastReceived = clock_elapsed(); + np->lastSent = clock_elapsed(); + if ((type != NPT_LOCAL) && (gNetworkType == NT_SERVER || type == NPT_SERVER)) { gNetworkSystem->save_id(localIndex, 0); } + + np->modelIndex = modelIndex; + np->paletteIndex = paletteIndex; + network_player_update_model(localIndex); - extern s16 gCurrCourseNum, gCurrActStarNum, gCurrLevelNum, gCurrAreaIndex; - network_player_update_course_level(np, gCurrCourseNum, gCurrActStarNum, gCurrLevelNum, gCurrAreaIndex); - np->currLevelSyncValid = false; - np->currAreaSyncValid = false; - np->modelIndex = modelIndex; - np->paletteIndex = paletteIndex; snprintf(np->name, MAX_PLAYER_STRING, "%s", name); - network_player_update_model(0); + return localIndex; + } - for (int j = 0; j < MAX_RX_SEQ_IDS; j++) { np->rxSeqIds[j] = 0; np->rxPacketHash[j] = 0; } - np->onRxSeqId = 0; + // clear + memset(np, 0, sizeof(struct NetworkPlayer)); + // update fundamentals + np->connected = true; + np->type = type; + np->localIndex = localIndex; + np->globalIndex = globalIndex; + if ((type != NPT_LOCAL) && (gNetworkType == NT_SERVER || type == NPT_SERVER)) { gNetworkSystem->save_id(localIndex, 0); } + + // update course/level + np->currLevelAreaSeqId = 0; + extern s16 gCurrCourseNum, gCurrActStarNum, gCurrLevelNum, gCurrAreaIndex; + network_player_update_course_level(np, gCurrCourseNum, gCurrActStarNum, gCurrLevelNum, gCurrAreaIndex); + np->currLevelSyncValid = false; + np->currAreaSyncValid = false; + + // update visuals + np->fadeOpacity = 0; + np->modelIndex = modelIndex; + np->paletteIndex = paletteIndex; + snprintf(np->name, MAX_PLAYER_STRING, "%s", name); + network_player_update_model(localIndex); + + // clear networking fields + np->lastReceived = clock_elapsed(); + np->lastSent = clock_elapsed(); + np->onRxSeqId = 0; + + if (localIndex != 0) { + for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[localIndex] = 0; } + } + for (int j = 0; j < MAX_RX_SEQ_IDS; j++) { np->rxSeqIds[j] = 0; np->rxPacketHash[j] = 0; } + packet_ordered_clear(globalIndex); + + // set up network player pointers + if (type == NPT_LOCAL) { gNetworkPlayerLocal = np; - if (gNetworkType == NT_SERVER) { gNetworkPlayerServer = gNetworkPlayerLocal; } - packet_ordered_clear(globalIndex); - return 0; + } else if (type == NPT_SERVER) { + gNetworkPlayerServer = np; } - if (globalIndex != UNKNOWN_GLOBAL_INDEX) { - for (int i = 1; i < MAX_PLAYERS; i++) { - struct NetworkPlayer* np = &gNetworkPlayers[i]; - if (!np->connected) { continue; } - if (np->globalIndex != globalIndex) { continue; } - np->localIndex = i; - np->lastReceived = clock_elapsed(); - np->lastSent = clock_elapsed(); - np->modelIndex = modelIndex; - np->paletteIndex = paletteIndex; - np->localLevelMatch = (np->currCourseNum == gCurrCourseNum && np->currActNum == gCurrActStarNum && np->currLevelNum == gCurrLevelNum); - snprintf(np->name, MAX_PLAYER_STRING, "%s", name); - network_player_update_model(i); - if (gNetworkType == NT_SERVER || type == NPT_SERVER) { gNetworkSystem->save_id(i, 0); } - LOG_ERROR("player connected, reusing local %d, global %d, duplicate event?", i, globalIndex); - return i; - } + // display connected popup + if (type != NPT_SERVER && (gNetworkType != NT_SERVER || type != NPT_LOCAL)) { + u8* rgb = get_player_color(np->paletteIndex, 0); + char popupMsg[128] = { 0 }; + snprintf(popupMsg, 128, "\\#%02x%02x%02x\\%s\\#dcdcdc\\ connected", rgb[0], rgb[1], rgb[2], np->name); + djui_popup_create(popupMsg, 1); } + LOG_INFO("player connected, local %d, global %d", localIndex, np->globalIndex); - for (int i = 1; i < MAX_PLAYERS; i++) { - struct NetworkPlayer* np = &gNetworkPlayers[i]; - if (np->connected) { continue; } - memset(np, 0, sizeof(struct NetworkPlayer)); - np->connected = true; - np->currLevelAreaSeqId = 0; - if (gNetworkType == NT_SERVER && !np->currAreaSyncValid) { - network_player_update_course_level(np, 0, 0, 16, 1); - np->currLevelSyncValid = false; - np->currAreaSyncValid = false; - } - np->fadeOpacity = 0; - np->localIndex = i; - np->globalIndex = (gNetworkType == NT_SERVER) ? i : globalIndex; - np->type = type; - np->lastReceived = clock_elapsed(); - np->lastSent = clock_elapsed(); - np->modelIndex = modelIndex; - np->paletteIndex = paletteIndex; - np->localLevelMatch = (np->currCourseNum == gCurrCourseNum && np->currActNum == gCurrActStarNum && np->currLevelNum == gCurrLevelNum); - snprintf(np->name, MAX_PLAYER_STRING, "%s", name); - network_player_update_model(i); - if (gNetworkType == NT_SERVER || type == NPT_SERVER) { gNetworkSystem->save_id(i, 0); } - for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; } - for (int j = 0; j < MAX_RX_SEQ_IDS; j++) { np->rxSeqIds[j] = 0; np->rxPacketHash[j] = 0; } - np->onRxSeqId = 0; - if (type == NPT_SERVER) { - gNetworkPlayerServer = np; - } else { - // display popup - u8* rgb = get_player_color(np->paletteIndex, 0); - char popupMsg[128] = { 0 }; - snprintf(popupMsg, 128, "\\#%02x%02x%02x\\%s\\#dcdcdc\\ connected", rgb[0], rgb[1], rgb[2], np->name); - djui_popup_create(popupMsg, 1); - } - LOG_INFO("player connected, local %d, global %d", i, np->globalIndex); - packet_ordered_clear(np->globalIndex); - return i; - } - - LOG_ERROR("player connected, but unable to allocate!"); - return UNKNOWN_GLOBAL_INDEX; + return localIndex; } u8 network_player_disconnected(u8 globalIndex) { diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index ac10964e..d731ffa6 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -36,7 +36,6 @@ struct NetworkPlayer { u8 onRxSeqId; u8 modelIndex; u8 paletteIndex; - bool localLevelMatch; char name[MAX_PLAYER_STRING+1]; u16 rxSeqIds[MAX_RX_SEQ_IDS]; u32 rxPacketHash[MAX_RX_SEQ_IDS]; diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index b897307e..e1dcbd50 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -85,6 +85,8 @@ void packet_process(struct Packet* p) { case PACKET_LUA_SYNC_TABLE: network_receive_lua_sync_table(p); break; + case PACKET_NETWORK_PLAYERS_REQUEST: network_receive_network_players_request(p); break; + // custom case PACKET_CUSTOM: network_receive_custom(p); break; default: LOG_ERROR("received unknown packet: %d", p->buffer[0]); diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index 4d778051..c4472085 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -61,6 +61,8 @@ enum PacketType { PACKET_LUA_SYNC_TABLE, + PACKET_NETWORK_PLAYERS_REQUEST, + /// PACKET_CUSTOM = 255, }; @@ -223,7 +225,9 @@ void network_send_save_set_flag(s32 fileIndex, s32 courseIndex, u8 courseStars, void network_receive_save_set_flag(struct Packet* p); // packet_network_players.c -void network_send_network_players(void); +void network_send_network_players_request(void); +void network_receive_network_players_request(struct Packet* p); +void network_send_network_players(u8 exceptLocalIndex); void network_receive_network_players(struct Packet* p); // packet_death.c diff --git a/src/pc/network/packets/packet_join.c b/src/pc/network/packets/packet_join.c index cfb35ba3..8f8c0412 100644 --- a/src/pc/network/packets/packet_join.c +++ b/src/pc/network/packets/packet_join.c @@ -63,12 +63,24 @@ void network_receive_join_request(struct Packet* p) { void network_send_join(struct Packet* joinRequestPacket) { SOFT_ASSERT(gNetworkType == NT_SERVER); - // do connection event - joinRequestPacket->localIndex = network_player_connected(NPT_CLIENT, joinRequestPacket->localIndex, sJoinRequestPlayerModel, sJoinRequestPlayerPalette, sJoinRequestPlayerName); - if (joinRequestPacket->localIndex == UNKNOWN_LOCAL_INDEX) { - network_send_kick(EKT_FULL_PARTY); - return; + // figure out id + u8 globalIndex = joinRequestPacket->localIndex; + if (globalIndex == UNKNOWN_LOCAL_INDEX) { + for (int i = 1; i < MAX_PLAYERS; i++) { + if (!gNetworkPlayers[i].connected) { + globalIndex = i; + break; + } + } + if (globalIndex == UNKNOWN_LOCAL_INDEX) { + network_send_kick(EKT_FULL_PARTY); + return; + } } + LOG_INFO("chose globalIndex: %d", globalIndex); + + // do connection event + network_player_connected(NPT_CLIENT, globalIndex, sJoinRequestPlayerModel, sJoinRequestPlayerPalette, sJoinRequestPlayerName); fs_file_t* fp = fs_open(SAVE_FILENAME); if (fp != NULL) { @@ -83,7 +95,7 @@ void network_send_join(struct Packet* joinRequestPacket) { struct Packet p = { 0 }; packet_init(&p, PACKET_JOIN, true, PLMT_NONE); packet_write(&p, &version, sizeof(u8) * MAX_VERSION_LENGTH); - packet_write(&p, &joinRequestPacket->localIndex, sizeof(u8)); + packet_write(&p, &globalIndex, sizeof(u8)); packet_write(&p, &gCurrSaveFileNum, sizeof(s16)); packet_write(&p, &gServerSettings.playerInteractions, sizeof(u8)); packet_write(&p, &gServerSettings.playerKnockbackStrength, sizeof(u8)); @@ -108,10 +120,10 @@ void network_send_join(struct Packet* joinRequestPacket) { node = node->next; } - network_send_to(joinRequestPacket->localIndex , &p); + network_send_to(globalIndex, &p); LOG_INFO("sending join packet"); - network_send_network_players(); + network_send_network_players(globalIndex); } void network_receive_join(struct Packet* p) { @@ -219,4 +231,6 @@ void network_receive_join(struct Packet* p) { gChangeLevel = 16; smlua_init(); + + network_send_network_players_request(); } diff --git a/src/pc/network/packets/packet_network_players.c b/src/pc/network/packets/packet_network_players.c index f2eac731..7a7bb864 100644 --- a/src/pc/network/packets/packet_network_players.c +++ b/src/pc/network/packets/packet_network_players.c @@ -41,11 +41,30 @@ static void network_send_to_network_players(u8 sendToLocalIndex) { LOG_INFO("sent list of %d network players to %d", connectedCount, sendToLocalIndex); } -void network_send_network_players(void) { +void network_send_network_players_request(void) { + SOFT_ASSERT(gNetworkType == NT_CLIENT); + struct Packet p = { 0 }; + packet_init(&p, PACKET_NETWORK_PLAYERS_REQUEST, true, PLMT_NONE); + network_send_to((gNetworkPlayerServer != NULL) ? gNetworkPlayerServer->localIndex : 0, &p); + LOG_INFO("sending network players request"); +} + +void network_receive_network_players_request(struct Packet* p) { + SOFT_ASSERT(gNetworkType == NT_SERVER); + u8 localIndex = p->localIndex; + if (localIndex == UNKNOWN_LOCAL_INDEX) { + LOG_ERROR("Received network players request from unknown index"); + return; + } + network_send_to_network_players(localIndex); +} + +void network_send_network_players(u8 exceptLocalIndex) { SOFT_ASSERT(gNetworkType == NT_SERVER); LOG_INFO("sending list of network players to all"); for (int i = 1; i < MAX_PLAYERS; i++) { if (!gNetworkPlayers[i].connected) { continue; } + if (i == exceptLocalIndex) { continue; } network_send_to_network_players(i); } }