diff --git a/port/src/net/net.c b/port/src/net/net.c index 87caa88f2..42a22669a 100644 --- a/port/src/net/net.c +++ b/port/src/net/net.c @@ -863,18 +863,28 @@ u32 netSend(struct netclient *dstcl, struct netbuf *buf, const s32 reliable, con void netPlayersAllocate(void) { + s32 playernum = 0; + + if (g_NetMode == NETMODE_CLIENT) { + // we always put the local player at index 0, even client-side + // which means that clientside we have to put the server's player into our slot + const s32 svplayernum = g_NetLocalClient->playernum; + g_NetLocalClient->playernum = 0; + g_NetClients[0].playernum = svplayernum; + } + for (s32 i = 0; i < g_NetMaxClients; ++i) { struct netclient *cl = &g_NetClients[i]; if (cl->state < CLSTATE_LOBBY) { continue; } - if (cl == g_NetLocalClient) { - // we always put the local player at index 0, even client-side - cl->playernum = 0; - } else { - // which means that clientside we have to put the server's player into our slot - cl->playernum = (g_NetMode == NETMODE_CLIENT && i == 0) ? g_NetLocalClient->id : cl->id; + if (g_NetMode == NETMODE_SERVER) { + // on the server allocate players sequentially + cl->playernum = playernum++; + } + + if (cl != g_NetLocalClient) { // disable controls for the remote pawns and set their settings // TODO: backup the player configs or something struct mpplayerconfig *cfg = &g_PlayerConfigsArray[cl->playernum]; @@ -934,14 +944,14 @@ void netSyncIdsAllocate(void) // HACK: when we're a client, we'll need to swap our player and server player's props // because of what we do in netPlayersAllocate if (g_NetMode == NETMODE_CLIENT) { - if (!g_Vars.players[g_NetLocalClient->id]->prop || !g_Vars.players[0]->prop) { + if (!g_NetLocalClient->player || !g_NetLocalClient->player->prop) { sysLogPrintf(LOG_ERROR, "NET: no props allocated for players?"); netDisconnect(); return; } - const u16 sid = g_Vars.players[g_NetLocalClient->id]->prop->syncid; - g_Vars.players[g_NetLocalClient->id]->prop->syncid = g_Vars.players[0]->prop->syncid; - g_Vars.players[0]->prop->syncid = sid; + const u16 sid = g_NetClients[0].player->prop->syncid; + g_NetClients[0].player->prop->syncid = g_NetLocalClient->player->prop->syncid; + g_NetLocalClient->player->prop->syncid = sid; } sysLogPrintf(LOG_NOTE, "NET: last initial syncid: %u", g_NetNextSyncId); diff --git a/port/src/net/netmsg.c b/port/src/net/netmsg.c index 414b01798..56508c8e9 100644 --- a/port/src/net/netmsg.c +++ b/port/src/net/netmsg.c @@ -424,8 +424,9 @@ u32 netmsgSvcStageStartWrite(struct netbuf *dst) for (s32 i = 0; i < g_NetMaxClients; ++i) { struct netclient *ncl = &g_NetClients[i]; if (ncl->state) { - ncl->settings.team = g_PlayerConfigsArray[ncl->id].base.team; + ncl->settings.team = ncl->config->base.team; netbufWriteU8(dst, ncl->id); + netbufWriteU8(dst, ncl->playernum); netbufWriteU8(dst, ncl->settings.team); netbufWriteU16(dst, ncl->settings.options); netbufWriteU8(dst, ncl->settings.bodynum); @@ -490,6 +491,7 @@ u32 netmsgSvcStageStartRead(struct netbuf *src, struct netclient *srccl) for (u8 i = 0; i < numplayers; ++i) { const u8 id = netbufReadU8(src); struct netclient *ncl = &g_NetClients[id]; + ncl->playernum = netbufReadU8(src); ncl->settings.team = netbufReadU8(src); if (ncl != g_NetLocalClient) { ncl->id = id; @@ -506,7 +508,7 @@ u32 netmsgSvcStageStartRead(struct netbuf *src, struct netclient *srccl) return 3; } } else { - // skip our own settings except for the team + // skip our own settings except for the team and player number netbufReadU16(src); netbufReadU8(src); netbufReadU8(src); @@ -523,16 +525,17 @@ u32 netmsgSvcStageStartRead(struct netbuf *src, struct netclient *srccl) } // set teams on the player configs, but swap teams with the server player + // because we haven't swapped player numbers yet (see netPlayersAlloc) for (u32 i = 0; i < NET_MAX_CLIENTS; ++i) { struct netclient *ncl = &g_NetClients[i]; if (ncl->state) { u32 playernum = 0; if (ncl->id == 0) { - playernum = g_NetLocalClient->id; + playernum = g_NetLocalClient->playernum; } else if (ncl == g_NetLocalClient) { - playernum = 0; + playernum = g_NetClients[0].playernum; } else { - playernum = ncl->id; + playernum = ncl->playernum; } g_PlayerConfigsArray[playernum].base.team = ncl->settings.team; } @@ -577,12 +580,14 @@ u32 netmsgSvcStageEndRead(struct netbuf *src, struct netclient *srccl) for (s32 i = 0; i < g_NetMaxClients; ++i) { struct netclient *ncl = &g_NetClients[i]; if (ncl->state) { - ncl->state = CLSTATE_LOBBY; + ncl->state = CLSTATE_DISCONNECTED; ncl->player = NULL; ncl->config = NULL; } } + g_NetLocalClient->state = CLSTATE_LOBBY; + g_NumReasonsToEndMpMatch = 1; mainEndStage(); diff --git a/src/game/challenge.c b/src/game/challenge.c index 167eae8aa..cfba07b4c 100644 --- a/src/game/challenge.c +++ b/src/game/challenge.c @@ -265,8 +265,10 @@ void challengePerformSanityChecks(void) g_Vars.mphilltime = 10; } } else if (!challengeIsFeatureUnlocked(MPFEATURE_8BOTS)) { - // Limit to 4 players and 4 simulants -#if MAX_PLAYERS > 4 + // Limit to 4 players and 4 simulants in local games +#ifndef PLATFORM_N64 + g_MpSetup.chrslots &= (g_NetMode ? 0x0fff : 0x0f0f); +#elif MAX_PLAYERS > 4 g_MpSetup.chrslots &= 0x0f0f; #else g_MpSetup.chrslots &= 0x00ff; diff --git a/src/game/menu.c b/src/game/menu.c index a5f3498ad..045c548dd 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -5379,7 +5379,7 @@ Gfx *menuRender(Gfx *gdl) #ifndef PLATFORM_N64 if (g_NetMode) { if (g_NetMode == NETMODE_SERVER) { - sprintf(text, "Server: %d/%d", g_NetNumClients, g_NetMaxClients); + sprintf(text, "Server: %d/%d %04x", g_NetNumClients, g_NetMaxClients, g_MpSetup.chrslots); } else { sprintf(text, "Client: ID %u", g_NetLocalClient->id); } diff --git a/src/game/menutick.c b/src/game/menutick.c index 73e19ee13..71288dcae 100644 --- a/src/game/menutick.c +++ b/src/game/menutick.c @@ -321,6 +321,18 @@ void menuTick(void) } } +#ifndef PLATFORM_N64 + if (g_NetMode == NETMODE_SERVER && g_MenuData.unk008 == -1) { + s32 slot = 1; + for (i = 1; i < g_NetMaxClients; ++i) { + if (g_NetClients[i].state >= CLSTATE_LOBBY) { + g_MpSetup.chrslots |= (1 << slot); + ++slot; + } + } + } +#endif + mpCalculateLockIfLastWinnerOrLoser(); challengePerformSanityChecks(); } diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index b1a014374..441f6aba8 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -191,9 +191,11 @@ void mpStartMatch(void) if (g_NetMode == NETMODE_SERVER) { g_MpSetup.chrslots &= 0xff00; g_MpSetup.chrslots |= 1; + s32 slot = 1; for (s32 i = 1; i < g_NetMaxClients; ++i) { if (g_NetClients[i].state >= CLSTATE_LOBBY) { - g_MpSetup.chrslots |= (1 << i); + g_MpSetup.chrslots |= (1 << slot); + ++slot; } } } @@ -3000,13 +3002,6 @@ struct mpchrconfig *mpGetChrConfigBySlotNum(s32 slot) } } -#ifndef PLATFORM_N64 - // ignore chrslots while setting up a netgame - if (!result && g_NetMode && slot < g_NetMaxClients && g_NetClients[slot].state >= CLSTATE_LOBBY) { - result = &g_PlayerConfigsArray[slot].base; - } -#endif - return result; }