static void server_WriteUpdateInfo( BYTESTREAM_s *pByteStream, int iUpdateType ) { NETWORK_WriteByte( &g_MessageBuffer.ByteStream, iUpdateType ); switch ( iUpdateType ) { // Update the player data. case SVRCU_PLAYERDATA: NETWORK_WriteByte( pByteStream, SERVER_CountPlayers( true )); for ( unsigned int i = 0; i < MAXPLAYERS; i++ ) { if ( playeringame[i] ) { FString fsName; fsName.Format( "%s", players[i].userinfo.netname ); V_RemoveColorCodes( fsName ); NETWORK_WriteString( pByteStream, fsName ); } } break; // Update the current map. case SVRCU_MAP: NETWORK_WriteString( pByteStream, level.mapname ); break; // Update the number of other admins. case SVRCU_ADMINCOUNT: NETWORK_WriteByte( pByteStream, g_AuthedClients.Size() - 1 ); break; } }
//***************************************************************************** // void SERVER_SAVE_SaveInfo( PLAYERSAVEDINFO_t *pInfo ) { ULONG ulIdx; char szPlayerName[128]; sprintf( szPlayerName, "%s", pInfo->szName ); V_RemoveColorCodes( szPlayerName ); for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if ( g_SavedPlayerInfo[ulIdx].bInitialized ) { // If this slot matches the player we're trying to save, just update it. if (( stricmp( szPlayerName, g_SavedPlayerInfo[ulIdx].szName ) == 0 ) && ( NETWORK_CompareAddress( pInfo->Address, g_SavedPlayerInfo[ulIdx].Address, false ))) { server_save_UpdateSlotWithInfo( ulIdx, pInfo ); return; } continue; } server_save_UpdateSlotWithInfo( ulIdx, pInfo ); return; } }
void I_PrintStr (const char *cp) { // [BB] The color codes don't seem to be compatible with stdout under Linux, so just remove them. FString copy = cp; V_RemoveColorCodes ( copy ); fputs (copy.GetChars(), stdout); fflush (stdout); }
//***************************************************************************** //***************************************************************************** // void server_save_UpdateSlotWithInfo( ULONG ulSlot, PLAYERSAVEDINFO_t *pInfo ) { if (( ulSlot < 0 ) || ( ulSlot >= MAXPLAYERS )) return; g_SavedPlayerInfo[ulSlot].bInitialized = true; g_SavedPlayerInfo[ulSlot].Address = pInfo->Address; g_SavedPlayerInfo[ulSlot].lFragCount = pInfo->lFragCount; g_SavedPlayerInfo[ulSlot].lPointCount = pInfo->lPointCount; g_SavedPlayerInfo[ulSlot].lWinCount = pInfo->lWinCount; sprintf( g_SavedPlayerInfo[ulSlot].szName, pInfo->szName ); V_RemoveColorCodes( g_SavedPlayerInfo[ulSlot].szName ); }
// [RC] Strips color codes from an FString. void V_RemoveColorCodes( FString &String ) { const ULONG length = (ULONG) String.Len(); char *szString = new char[length+1]; // Copy the FString to a temporary char array. strncpy( szString, String.GetChars(), length ); szString[length] = 0; // Remove the colors. V_ColorizeString( szString ); V_RemoveColorCodes( szString ); // Convert back and clean up. String = szString; delete[] szString; }
//***************************************************************************** // PLAYERSAVEDINFO_t *SERVER_SAVE_GetSavedInfo( char *pszPlayerName, netadr_t Address ) { ULONG ulIdx; char szPlayerName[128]; sprintf( szPlayerName, "%s", pszPlayerName ); V_RemoveColorCodes( szPlayerName ); for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if ( g_SavedPlayerInfo[ulIdx].bInitialized == false ) continue; if (( stricmp( szPlayerName, g_SavedPlayerInfo[ulIdx].szName ) == 0 ) && ( NETWORK_CompareAddress( Address, g_SavedPlayerInfo[ulIdx].Address, false ))) { return ( &g_SavedPlayerInfo[ulIdx] ); } } return ( NULL ); }
// [BB] Strips color codes from a string respecting sv_colorstripmethod. void V_StripColors( char *pszString ) { switch ( sv_colorstripmethod ) { // Strip messages here of color codes. case 0: V_ColorizeString( pszString ); V_RemoveColorCodes( pszString ); break; // Don't strip out the color codes. case 1: V_ColorizeString( pszString ); break; // Just leave the damn thing alone! case 2: default: break; } }
//***************************************************************************** // void CHAT_PrintChatString( ULONG ulPlayer, ULONG ulMode, const char *pszString ) { ULONG ulChatLevel = 0; FString OutString; FString ChatString; // [RC] Are we ignoring this player? if (( ulPlayer != MAXPLAYERS ) && players[ulPlayer].bIgnoreChat ) return; // If ulPlayer == MAXPLAYERS, it is the server talking. if ( ulPlayer == MAXPLAYERS ) { // Special support for "/me" commands. ulChatLevel = PRINT_HIGH; if ( strnicmp( "/me", pszString, 3 ) == 0 ) { pszString += 3; OutString = "* <server>"; } else OutString = "<server>: "; } else if ( ulMode == CHATMODE_GLOBAL ) { ulChatLevel = PRINT_CHAT; // Special support for "/me" commands. if ( strnicmp( "/me", pszString, 3 ) == 0 ) { ulChatLevel = PRINT_HIGH; pszString += 3; OutString.AppendFormat( "* %s\\cc", players[ulPlayer].userinfo.netname ); } else { OutString.AppendFormat( "%s" TEXTCOLOR_CHAT ": ", players[ulPlayer].userinfo.netname ); } } else if ( ulMode == CHATMODE_TEAM ) { ulChatLevel = PRINT_TEAMCHAT; if ( PLAYER_IsTrueSpectator ( &players[consoleplayer] ) ) OutString += "<SPEC> "; else { OutString = "\\c"; OutString += V_GetColorChar( TEAM_GetTextColor( players[consoleplayer].ulTeam )); OutString += "<TEAM> "; } // Special support for "/me" commands. if ( strnicmp( "/me", pszString, 3 ) == 0 ) { ulChatLevel = PRINT_HIGH; pszString += 3; OutString.AppendFormat( "\\cc* %s\\cc", players[ulPlayer].userinfo.netname ); } else { OutString.AppendFormat( "\\cd%s" TEXTCOLOR_TEAMCHAT ": ", players[ulPlayer].userinfo.netname ); } } ChatString = pszString; // [RC] Remove linebreaks and other escape codes from chat. ChatString.Substitute("\\", "\\\\"); // [RC] ...but allow chat colors. ChatString.Substitute("\\\\c", "\\c"); // [BB] Remove invalid color codes, those can confuse the printing and create new lines. V_RemoveInvalidColorCodes( ChatString ); // [RC] ...if the user wants them. if ( con_colorinmessages == 2) V_RemoveColorCodes( ChatString ); // [BB] Remove any kind of trailing crap. V_RemoveTrailingCrapFromFString ( ChatString ); // [BB] If the chat string is empty now, it only contained crap and is ignored. if ( ChatString.IsEmpty() ) return; OutString += ChatString; Printf( ulChatLevel, "%s\n", OutString.GetChars() ); // [BB] If the user doesn't want to see the messages, they shouldn't make a sound. if ( show_messages ) { // [RC] User can choose the chat sound. if ( chat_sound == 1 ) // Default S_Sound( CHAN_VOICE | CHAN_UI, gameinfo.chatSound, 1, ATTN_NONE ); else if ( chat_sound == 2 ) // Doom 1 S_Sound( CHAN_VOICE | CHAN_UI, "misc/chat2", 1, ATTN_NONE ); else if ( chat_sound == 3 ) // Doom 2 S_Sound( CHAN_VOICE | CHAN_UI, "misc/chat", 1, ATTN_NONE ); } BOTCMD_SetLastChatString( pszString ); BOTCMD_SetLastChatPlayer( players[ulPlayer].userinfo.netname ); { ULONG ulIdx; for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if ( playeringame[ulIdx] == false ) continue; // Don't tell the bot someone talked if it was it who talked. if ( ulIdx == ulPlayer ) continue; // If this is a bot, tell it a player said something. if ( players[ulIdx].pSkullBot ) players[ulIdx].pSkullBot->PostEvent( BOTEVENT_PLAYER_SAY ); } } }
// [RC] Conforms names to meet standards. void V_CleanPlayerName( char *pszString ) { char *pszStart; char *p; char c; ULONG ulStringLength; ULONG ulTotalLength; ULONG ulNonWhitespace; char szColorlessName[256]; ulStringLength = static_cast<ULONG>(strlen( pszString )); ulTotalLength = 0; ulNonWhitespace = 0; // Start at the beginning of the string. p = pszString; pszStart = pszString; // The name must be longer than three characters. if ( ulStringLength < 3 ) { strcpy( pszString, "Player" ); return; } // Go through and remove the illegal characters. while ( (c = *p++) ) { if ( !v_IsCharAcceptableInNames(c) ) { ULONG ulPos; ulStringLength = static_cast<ULONG>(strlen( pszString )); // Shift the rest of the string back one. for ( ulPos = 0; ulPos < ulStringLength; ulPos++ ) pszString[ulPos] = pszString[ulPos + 1]; // Don't skip a character. p--; } else { pszString++; ulTotalLength++; } } // Cut the string at its new end. *pszString = 0; // [BB] Remove any trailing incomplete escaped color codes. Since we just removed // quite a bit from the string, it's possible that those are there now. // Note: We need to work on pszStart now, by now pszString only contains a pointer // to the end of the string. // [BB] I don't want to implement the trailing crap removement for escaped and // unescaped color codes, so I have to uncolorize, clean and colorize the name here. // Not so efficient, but V_CleanPlayerName is called seldom enough so that this // doesn't matter. FString tempString = pszStart; V_UnColorizeString ( tempString ); V_RemoveTrailingCrapFromFString ( tempString ); // [BB] If the name uses color codes, make sure that it is terminated with "\\c-". // V_RemoveTrailingCrapFromFString removes all trailing color codes including "\\c-". // This is necessary to catch incomplete color codes before the trailing "\\c-". // Hence, we have to re-add "\\c-" here. if ( ( tempString.IndexOf ( "\\c" ) != -1 ) ) { // [BB] In the uncolorized string, color codes need one additional char, take this // into account when checking whether the name is too long. FString tempColorizedString = tempString.GetChars(); V_ColorizeString ( tempColorizedString ); const unsigned int numColorCodes = tempString.Len() - tempColorizedString.Len(); if ( tempString.Len() > MAXPLAYERNAME - 3 + numColorCodes ) { tempString = tempString.Left ( MAXPLAYERNAME - 3 + numColorCodes ); V_RemoveTrailingCrapFromFString ( tempString ); } tempString += "\\c-"; } V_ColorizeString ( tempString ); sprintf ( pszStart, "%s", tempString.GetChars() ); // Determine the name's actual length. strncpy( szColorlessName, pszStart, 256 ); V_RemoveColorCodes( szColorlessName ); p = szColorlessName; ulNonWhitespace = 0; while ( (c = *p++) ) { if ( !v_IsCharacterWhitespace(c) ) ulNonWhitespace++; } // Check the length again, as characters were removed. if ( ulNonWhitespace < 3 ) strcpy( pszStart, "Player" ); }