diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a4cd1941b..c42987e4b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -964,12 +964,32 @@ static boolean CL_SendJoin(void) for (i = 0; i <= splitscreen; i++) { // the MAXPLAYERS addition is necessary to communicate that g_localplayers is not yet safe to reference + player_config_t temp; + CleanupPlayerName(MAXPLAYERS+i, cv_playername[i].zstring); - strncpy(netbuffer->u.clientcfg.names[i], cv_playername[i].zstring, MAXPLAYERNAME); + + strncpy(temp.name, cv_playername[i].zstring, MAXPLAYERNAME); + D_FillPlayerSkinAndColor(i, NULL, &temp); + D_FillPlayerWeaponPref(i, &temp); + + netbuffer->u.clientcfg.player_configs[i] = temp; } + // privacy shield for the local players not joining this session for (; i < MAXSPLITSCREENPLAYERS; i++) - strncpy(netbuffer->u.clientcfg.names[i], va("Player %c", 'A' + i), MAXPLAYERNAME); + { + player_config_t temp; + + strncpy(temp.name, va("Player %c", 'A' + i), MAXPLAYERNAME); + temp.skin = 0; + temp.color = SKINCOLOR_NONE; + temp.follower = -1; + temp.follower_color = SKINCOLOR_NONE; + temp.weapon_prefs = 0; + temp.min_delay = 0; + + netbuffer->u.clientcfg.player_configs[i] = temp; + } memcpy(&netbuffer->u.clientcfg.availabilities, R_GetSkinAvailabilities(false, -1), MAXAVAILABILITY*sizeof(UINT8)); @@ -3751,6 +3771,12 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) newplayer = &players[newplayernum]; READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); + UINT16 skin = READUINT16(*p); + UINT16 color = READUINT16(*p); + INT16 follower = READINT16(*p); + UINT16 followercolor = READUINT16(*p); + UINT8 weaponprefs = READUINT8(*p); + UINT8 mindelay = READUINT8(*p); READMEM(*p, public_key, PUBKEYLENGTH); READMEM(*p, clientpowerlevels[newplayernum], sizeof(((serverplayer_t *)0)->powerlevels)); @@ -3790,13 +3816,20 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) } P_ForceLocalAngle(newplayer, newplayer->angleturn); - - D_SendPlayerConfig(splitscreenplayer); addedtogame = true; + + if (server) + { + for (i = 0; i < G_LocalSplitscreenPartySize(newplayernum); ++i) + playerdelaytable[G_LocalSplitscreenPartyMember(newplayernum, i)] = mindelay; + } } - players[newplayernum].splitscreenindex = splitscreenplayer; - players[newplayernum].bot = false; + newplayer->splitscreenindex = splitscreenplayer; + newplayer->bot = false; + + D_PlayerChangeSkinAndColor(newplayer, skin, color, follower, followercolor); + WeaponPref_Set(newplayernum, weaponprefs); // Previously called at the top of this function, commented as // "caused desyncs in this spot :(". But we can't do this in @@ -3979,14 +4012,10 @@ static void Got_ServerDeafenPlayer(const UINT8 **p, INT32 playernum) } } -static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, - const char *name, uint8_t *key, UINT16 *pwr, - const char *name2, uint8_t *key2, UINT16 *pwr2, - const char *name3, uint8_t *key3, UINT16 *pwr3, - const char *name4, uint8_t *key4, UINT16 *pwr4) +static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, player_config_t configs[MAXSPLITSCREENPLAYERS]) { INT32 n, newplayernum, i; - UINT8 buf[4 + MAXPLAYERNAME + PUBKEYLENGTH + MAXAVAILABILITY + sizeof(((serverplayer_t *)0)->powerlevels)]; + UINT8 buf[4 + MAXPLAYERNAME + 10 + PUBKEYLENGTH + MAXAVAILABILITY + sizeof(((serverplayer_t *)0)->powerlevels)]; UINT8 *buf_p = buf; boolean newplayer = false; @@ -4037,6 +4066,30 @@ static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, // before accepting the join I_Assert(newplayernum < MAXPLAYERS); + if (playerpernode[node] < 1) + { + nodetoplayer[node] = newplayernum; + } + else if (playerpernode[node] < 2) + { + nodetoplayer2[node] = newplayernum; + } + else if (playerpernode[node] < 3) + { + nodetoplayer3[node] = newplayernum; + } + else if (playerpernode[node] < 4) + { + nodetoplayer4[node] = newplayernum; + } + else + { + // I don't know if it's safe to assert here, + // but I do know this should not be allowed + // to be reached. + return newplayer; + } + playernode[newplayernum] = (UINT8)node; // Reset the buffer to the start for multiple joiners @@ -4045,34 +4098,16 @@ static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, WRITEUINT8(buf_p, (UINT8)node); WRITEUINT8(buf_p, newplayernum); - if (playerpernode[node] < 1) - { - nodetoplayer[node] = newplayernum; - WRITESTRINGN(buf_p, name, MAXPLAYERNAME); - WRITEMEM(buf_p, key, PUBKEYLENGTH); - WRITEMEM(buf_p, pwr, sizeof(((serverplayer_t *)0)->powerlevels)); - } - else if (playerpernode[node] < 2) - { - nodetoplayer2[node] = newplayernum; - WRITESTRINGN(buf_p, name2, MAXPLAYERNAME); - WRITEMEM(buf_p, key2, PUBKEYLENGTH); - WRITEMEM(buf_p, pwr2, sizeof(((serverplayer_t *)0)->powerlevels)); - } - else if (playerpernode[node] < 3) - { - nodetoplayer3[node] = newplayernum; - WRITESTRINGN(buf_p, name3, MAXPLAYERNAME); - WRITEMEM(buf_p, key3, PUBKEYLENGTH); - WRITEMEM(buf_p, pwr3, sizeof(((serverplayer_t *)0)->powerlevels)); - } - else if (playerpernode[node] < 4) - { - nodetoplayer4[node] = newplayernum; - WRITESTRINGN(buf_p, name4, MAXPLAYERNAME); - WRITEMEM(buf_p, key4, PUBKEYLENGTH); - WRITEMEM(buf_p, pwr4, sizeof(((serverplayer_t *)0)->powerlevels)); - } + const player_config_t *config = &configs[playerpernode[node]]; + WRITESTRINGN(buf_p, config->name, MAXPLAYERNAME); + WRITEUINT16(buf_p, config->skin); + WRITEUINT16(buf_p, config->color); + WRITEINT16(buf_p, config->follower); + WRITEUINT16(buf_p, config->follower_color); + WRITEUINT8(buf_p, config->weapon_prefs); + WRITEUINT8(buf_p, config->min_delay); + WRITEMEM(buf_p, config->key, PUBKEYLENGTH); + WRITEMEM(buf_p, config->pwr, sizeof(((serverplayer_t *)0)->powerlevels)); WRITEUINT8(buf_p, nodetoplayer[node]); // consoleplayer WRITEUINT8(buf_p, playerpernode[node]); // splitscreen num @@ -4251,11 +4286,21 @@ boolean SV_SpawnServer(void) UINT8 *availabilitiesbuffer = R_GetSkinAvailabilities(false, -1); SINT8 node = 0; for (; node < MAXNETNODES; node++) - result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, - cv_playername[0].zstring, PR_GetLocalPlayerProfile(0)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(0)->public_key)->powerlevels, - cv_playername[1].zstring, PR_GetLocalPlayerProfile(1)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(1)->public_key)->powerlevels, - cv_playername[2].zstring, PR_GetLocalPlayerProfile(2)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(2)->public_key)->powerlevels, - cv_playername[3].zstring, PR_GetLocalPlayerProfile(3)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(3)->public_key)->powerlevels); + { + player_config_t configs[MAXSPLITSCREENPLAYERS]; + + INT32 i; + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + strncpy(configs[i].name, cv_playername[i].zstring, MAXPLAYERNAME); + D_FillPlayerSkinAndColor(i, NULL, &configs[i]); + D_FillPlayerWeaponPref(i, &configs[i]); + memcpy(configs[i].key, PR_GetLocalPlayerProfile(i)->public_key, sizeof(configs[i].key)); + memcpy(configs[i].pwr, SV_GetStatsByKey(PR_GetLocalPlayerProfile(i)->public_key)->powerlevels, sizeof(configs[i].pwr)); + } + + result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, configs); + } } return result; #endif @@ -4364,6 +4409,7 @@ static boolean IsPlayerGuest(UINT8 player) */ static void HandleConnect(SINT8 node) { + player_config_t configs[MAXSPLITSCREENPLAYERS]; char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; INT32 i, j; UINT8 availabilitiesbuffer[MAXAVAILABILITY]; @@ -4487,9 +4533,12 @@ static void HandleConnect(SINT8 node) int sigcheck; boolean newnode = false; + memcpy(configs, netbuffer->u.clientcfg.player_configs, sizeof(configs)); + for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++) { - strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); + strlcpy(names[i], configs[i].name, MAXPLAYERNAME + 1); + if (!EnsurePlayerNameIsGood(names[i], -1)) { SV_SendRefuse(node, "Bad player name"); @@ -4610,11 +4659,15 @@ static void HandleConnect(SINT8 node) DEBFILE("send savegame\n"); } - SV_AddWaitingPlayers(node, availabilitiesbuffer, - names[0], lastReceivedKey[node][0], SV_GetStatsByKey(lastReceivedKey[node][0])->powerlevels, - names[1], lastReceivedKey[node][1], SV_GetStatsByKey(lastReceivedKey[node][1])->powerlevels, - names[2], lastReceivedKey[node][2], SV_GetStatsByKey(lastReceivedKey[node][2])->powerlevels, - names[3], lastReceivedKey[node][3], SV_GetStatsByKey(lastReceivedKey[node][3])->powerlevels); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + strlcpy(configs[i].name, names[i], MAXPLAYERNAME + 1); + memcpy(configs[i].key, lastReceivedKey[node][i], sizeof(configs[i].key)); + memcpy(configs[i].pwr, SV_GetStatsByKey(lastReceivedKey[node][i])->powerlevels, sizeof(configs[i].pwr)); + } + + SV_AddWaitingPlayers(node, availabilitiesbuffer, configs); + joindelay += cv_joindelay.value * TICRATE; player_joining = true; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 83e4d8409..8c05fa43f 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -273,6 +273,19 @@ struct fileack_pak #define MAXAPPLICATION 16 +struct player_config_t +{ + char name[MAXPLAYERNAME]; + UINT16 skin; + UINT16 color; + INT16 follower; + UINT16 follower_color; + UINT8 weapon_prefs; + UINT8 min_delay; + uint8_t key[PUBKEYLENGTH]; + UINT16 pwr[PWRLV_NUMTYPES]; +}; + struct clientconfig_pak { UINT8 _255;/* see serverinfo_pak */ @@ -282,9 +295,10 @@ struct clientconfig_pak UINT8 subversion; // Contains build version UINT8 localplayers; // number of splitscreen players UINT8 mode; - char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; + char _names_outdated[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; UINT8 availabilities[MAXAVAILABILITY]; uint8_t challengeResponse[MAXSPLITSCREENPLAYERS][SIGNATURELENGTH]; + player_config_t player_configs[MAXSPLITSCREENPLAYERS]; } ATTRPACK; #define SV_SPEEDMASK 0x03 // used to send kartspeed diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 75bd50915..0acd1da9d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -932,35 +932,24 @@ VaguePartyDescription (int playernum, int size, int default_color) return party_description; } -static INT32 snacpending[MAXSPLITSCREENPLAYERS] = {0,0,0,0}; -static INT32 chmappending = 0; - -// name, color, or skin has changed -// -static void SendNameAndColor(const UINT8 n) +void D_FillPlayerSkinAndColor(const UINT8 n, const player_t *player, player_config_t *config) { - const INT32 playernum = g_localplayers[n]; - player_t *player = NULL; - - if (splitscreen < n) + if (player != NULL) { - return; // can happen if skin4/color4/name4 changed + // We cannot return during this function, + // handle your input sanitizing before + I_Assert(splitscreen >= n); } - if (playernum == -1) - { - return; - } - - player = &players[playernum]; - UINT16 sendColor = cv_playercolor[n].value; UINT16 sendFollowerColor = cv_followercolor[n].value; // don't allow inaccessible colors if (sendColor != SKINCOLOR_NONE && K_ColorUsable(sendColor, false, true) == false) { - if (player->skincolor && K_ColorUsable(player->skincolor, false, true) == true) + if (player != NULL // in-game change + && player->skincolor != SKINCOLOR_NONE + && K_ColorUsable(player->skincolor, false, true) == true) { // Use our previous color CV_StealthSetValue(&cv_playercolor[n], player->skincolor); @@ -971,7 +960,11 @@ static void SendNameAndColor(const UINT8 n) CV_StealthSetValue(&cv_playercolor[n], SKINCOLOR_NONE); } - lastgoodcolor[playernum] = sendColor = cv_playercolor[n].value; + sendColor = cv_playercolor[n].value; + if (player != NULL) + { + lastgoodcolor[player - players] = sendColor; + } } // ditto for follower colour: @@ -981,14 +974,8 @@ static void SendNameAndColor(const UINT8 n) sendFollowerColor = cv_followercolor[n].value; } - // We'll handle it later if we're not playing. - if (!Playing()) - { - return; - } - // Don't change skin if the server doesn't want you to. - if (!CanChangeSkin(playernum)) + if (player != NULL && !CanChangeSkin(player - players)) { CV_StealthSet(&cv_skin[n], skins[player->skin]->name); } @@ -996,7 +983,7 @@ static void SendNameAndColor(const UINT8 n) // check if player has the skin loaded (cv_skin may have // the name of a skin that was available in the previous game) cv_skin[n].value = R_SkinAvailableEx(cv_skin[n].string, false); - if ((cv_skin[n].value < 0) || !R_SkinUsable(playernum, cv_skin[n].value, false)) + if ((cv_skin[n].value < 0) || !R_SkinUsable((player ? player - players : -1), cv_skin[n].value, false)) { CV_StealthSet(&cv_skin[n], DEFAULTSKIN); cv_skin[n].value = 0; @@ -1021,52 +1008,66 @@ static void SendNameAndColor(const UINT8 n) } } - // Don't send if everything was identical. - if (!strcmp(cv_playername[n].string, player_names[playernum]) - && sendColor == player->prefcolor - && !stricmp(cv_skin[n].string, skins[player->prefskin]->name) - && !stricmp(cv_follower[n].string, - (player->preffollower < 0 ? "None" : followers[player->preffollower].name)) - && sendFollowerColor == player->preffollowercolor) + config->skin = (UINT16)cv_skin[n].value; + config->color = sendColor; + config->follower = (horngoner ? -1 : (INT16)cv_follower[n].value); + config->follower_color = sendFollowerColor; +} + +static INT32 snacpending[MAXSPLITSCREENPLAYERS] = {0,0,0,0}; +static INT32 chmappending = 0; + +// name, color, or skin has changed +// +static void SendNameAndColor(const UINT8 n) +{ + if (!Playing()) { return; } - snacpending[n]++; + if (splitscreen < n) + { + return; // can happen if skin4/color4/name4 changed + } + + const INT32 playernum = g_localplayers[n]; + if (playernum == -1) + { + return; + } + + player_t *player = &players[playernum]; // Don't change name if muted - if (player_name_changes[playernum] >= MAXNAMECHANGES) + if (player_name_changes[player - players] >= MAXNAMECHANGES) { - CV_StealthSet(&cv_playername[n], player_names[playernum]); + CV_StealthSet(&cv_playername[n], player_names[player - players]); HU_AddChatText("\x85* You must wait to change your name again.", false); } - else if (cv_mute.value && !(server || IsPlayerAdmin(playernum))) + else if (cv_mute.value && !(server || IsPlayerAdmin(player - players))) { - CV_StealthSet(&cv_playername[n], player_names[playernum]); + CV_StealthSet(&cv_playername[n], player_names[player - players]); } else // Cleanup name if changing it { - CleanupPlayerName(playernum, cv_playername[n].zstring); + CleanupPlayerName(player - players, cv_playername[n].zstring); } - char buf[MAXPLAYERNAME+13]; - char *p = buf; + player_config_t config; + D_FillPlayerSkinAndColor(n, player, &config); + + UINT8 buf[MAXPLAYERNAME + 13]; + UINT8 *p = buf; - // Finally write out the complete packet and send it off. WRITESTRINGN(p, cv_playername[n].zstring, MAXPLAYERNAME); - WRITEUINT16(p, sendColor); - WRITEUINT16(p, (UINT16)cv_skin[n].value); - if (horngoner) - { - WRITEINT16(p, (-1)); - } - else - { - WRITEINT16(p, (INT16)cv_follower[n].value); - } - //CONS_Printf("Sending follower id %d\n", (INT16)cv_follower[n].value); - WRITEUINT16(p, sendFollowerColor); + WRITEUINT16(p, config.skin); + WRITEUINT16(p, config.color); + WRITEINT16(p, config.follower); + //CONS_Printf("Sending follower id %d\n", config.follower); + WRITEUINT16(p, config.follower_color); + snacpending[n]++; SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf); } @@ -1131,6 +1132,46 @@ static void FinalisePlaystateChange(INT32 playernum) P_CheckRacers(); // also SRB2Kart } +void D_PlayerChangeSkinAndColor(player_t *p, UINT16 skin, UINT16 color, INT16 follower, UINT16 followercolor) +{ + const UINT16 old_color = p->prefcolor; + const UINT16 old_skin = p->prefskin; + const INT16 old_follower = p->preffollower; + const UINT16 old_follower_color = p->preffollowercolor; + + // queue the rest for next round + p->prefcolor = color % numskincolors; + + if (K_ColorUsable(p->prefcolor, false, false) == false) + { + p->prefcolor = SKINCOLOR_NONE; + } + + p->prefskin = skin; + p->preffollowercolor = followercolor; + p->preffollower = follower; + + if ( + (p->jointime <= 1) // Just entered + || (cv_restrictskinchange.value == 0 // Not restricted + && !Y_IntermissionPlayerLock()) // Not start of intermission + ) + { + // update preferences immediately + G_UpdatePlayerPreferences(p); + } + else if (P_IsMachineLocalPlayer(p) == true) + { + if (old_color != p->prefcolor + || old_skin != p->prefskin + || old_follower != p->preffollower + || old_follower_color != p->preffollowercolor) + { + CONS_Alert(CONS_NOTICE, "Your changes will take effect next match.\n"); + } + } +} + static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) { player_t *p = &players[playernum]; @@ -1164,8 +1205,8 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) } READSTRINGN(*cp, name, MAXPLAYERNAME); - color = READUINT16(*cp); skin = READUINT16(*cp); + color = READUINT16(*cp); follower = READINT16(*cp); followercolor = READUINT16(*cp); @@ -1176,26 +1217,7 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) SetPlayerName(playernum, name); } - // queue the rest for next round - p->prefcolor = color % numskincolors; - if (K_ColorUsable(p->prefcolor, false, false) == false) - { - p->prefcolor = SKINCOLOR_NONE; - } - - p->prefskin = skin; - p->preffollowercolor = followercolor; - p->preffollower = follower; - - if ( - (p->jointime <= 1) // Just entered - || (cv_restrictskinchange.value == 0 // Not restricted - && !Y_IntermissionPlayerLock()) // Not start of intermission - ) - { - // update preferences immediately - G_UpdatePlayerPreferences(p); - } + D_PlayerChangeSkinAndColor(p, skin, color, follower, followercolor); } enum { @@ -1215,26 +1237,26 @@ enum { // HOURS LOST TO G_PlayerReborn: UNCOUNTABLE }; -void WeaponPref_Send(UINT8 ssplayer) +void D_FillPlayerWeaponPref(const UINT8 n, player_config_t *config) { UINT8 prefs = 0; - if (cv_kickstartaccel[ssplayer].value) + if (cv_kickstartaccel[n].value) prefs |= WP_KICKSTARTACCEL; - if (cv_autoroulette[ssplayer].value) + if (cv_autoroulette[n].value) prefs |= WP_AUTOROULETTE; - if (cv_shrinkme[ssplayer].value) + if (cv_shrinkme[n].value) prefs |= WP_SHRINKME; - if (gamecontrolflags[ssplayer] & GCF_ANALOGSTICK) + if (gamecontrolflags[n] & GCF_ANALOGSTICK) prefs |= WP_ANALOGSTICK; - if (cv_autoring[ssplayer].value) + if (cv_autoring[n].value) prefs |= WP_AUTORING; - if (ssplayer == 0) + if (n == 0) { if (cv_voice_selfmute.value) prefs |= WP_SELFMUTE; @@ -1243,14 +1265,25 @@ void WeaponPref_Send(UINT8 ssplayer) prefs |= WP_SELFDEAFEN; } - if (cv_strictfastfall[ssplayer].value) + if (cv_strictfastfall[n].value) prefs |= WP_STRICTFASTFALL; - UINT8 buf[2]; - buf[0] = prefs; - buf[1] = cv_mindelay.value; + config->weapon_prefs = prefs; + config->min_delay = cv_mindelay.value; +} - SendNetXCmdForPlayer(ssplayer, XD_WEAPONPREF, buf, sizeof buf); +void WeaponPref_Send(UINT8 ssplayer) +{ + player_config_t config; + D_FillPlayerWeaponPref(ssplayer, &config); + + UINT8 buf[2]; + UINT8 *p = buf; + + WRITEUINT8(p, config.weapon_prefs); + WRITEUINT8(p, config.min_delay); + + SendNetXCmdForPlayer(ssplayer, XD_WEAPONPREF, buf, p - buf); } void WeaponPref_Save(UINT8 **cp, INT32 playernum) @@ -1280,13 +1313,10 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum) WRITEUINT8(*cp, prefs); } -size_t WeaponPref_Parse(const UINT8 *bufstart, INT32 playernum) +void WeaponPref_Set(INT32 playernum, UINT8 prefs) { - const UINT8 *p = bufstart; player_t *player = &players[playernum]; - UINT8 prefs = READUINT8(p); - player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_AUTOROULETTE|PF_AUTORING); player->pflags2 &= ~(PF2_SELFMUTE | PF2_SELFDEAFEN | PF2_STRICTFASTFALL); @@ -1315,14 +1345,14 @@ size_t WeaponPref_Parse(const UINT8 *bufstart, INT32 playernum) if (prefs & WP_STRICTFASTFALL) player->pflags2 |= PF2_STRICTFASTFALL; +} - if (leveltime < 2) - { - // BAD HACK: No other place I tried to slot this in - // made it work for the host when they initally host, - // so this will have to do. - K_UpdateShrinkCheat(player); - } +size_t WeaponPref_Parse(const UINT8 *bufstart, INT32 playernum) +{ + const UINT8 *p = bufstart; + + UINT8 prefs = READUINT8(p); + WeaponPref_Set(playernum, prefs); return p - bufstart; } diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 36a0ed134..2c81d6c90 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -201,7 +201,11 @@ void D_RegisterServerCommands(void); void D_RegisterClientCommands(void); void CleanupPlayerName(INT32 playernum, const char *newname); boolean EnsurePlayerNameIsGood(char *name, INT32 playernum); +void D_FillPlayerSkinAndColor(const UINT8 n, const player_t *player, player_config_t *config); +void D_PlayerChangeSkinAndColor(player_t *player, UINT16 skin, UINT16 color, INT16 follower, UINT16 followercolor); +void D_FillPlayerWeaponPref(const UINT8 n, player_config_t *config); void WeaponPref_Send(UINT8 ssplayer); +void WeaponPref_Set(INT32 playernum, UINT8 prefs); void WeaponPref_Save(UINT8 **cp, INT32 playernum); size_t WeaponPref_Parse(const UINT8 *p, INT32 playernum); void D_SendPlayerConfig(UINT8 n); diff --git a/src/typedef.h b/src/typedef.h index d77aac7ee..7ee93831e 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -67,6 +67,7 @@ TYPEDEF (serverconfig_pak); TYPEDEF (filetx_pak); TYPEDEF (fileacksegment_t); TYPEDEF (fileack_pak); +TYPEDEF (player_config_t); TYPEDEF (clientconfig_pak); TYPEDEF (serverinfo_pak); TYPEDEF (serverrefuse_pak);