Exemple #1
0
void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update)
{
	userinfo_t *info = &players[pnum].userinfo;
	TArray<FName> compact_names(info->CountUsed());
	FBaseCVar **cvar_ptr;
	const char *ptr = *((const char **)stream);
	const char *breakpt;
	FString value;
	bool compact;
	FName keyname;
	unsigned int infotype = 0;

	if (*ptr++ != '\\')
		return;

	compact = (*ptr == '\\') ? ptr++, true : false;

	// We need the cvar names in sorted order for compact mode
	if (compact)
	{
		TMap<FName, FBaseCVar *>::Iterator it(*info);
		TMap<FName, FBaseCVar *>::Pair *pair;

		while (it.NextPair(pair))
		{
			compact_names.Push(pair->Key);
		}
		qsort(&compact_names[0], compact_names.Size(), sizeof(FName), namesortfunc);
	}

	if (pnum < MAXPLAYERS)
	{
		for (breakpt = ptr; breakpt != NULL; ptr = breakpt + 1)
		{
			breakpt = strchr(ptr, '\\');

			if (compact)
			{
				// Compact has just the value.
				if (infotype >= compact_names.Size())
				{ // Too many entries! OMG!
					break;
				}
				keyname = compact_names[infotype++];
				value = D_UnescapeUserInfo(ptr, breakpt != NULL ? breakpt - ptr : strlen(ptr));
			}
			else
			{
				// Verbose has both the key name and its value.
				assert(breakpt != NULL);
				// A malicious remote machine could invalidate the above assert.
				if (breakpt == NULL)
				{
					break;
				}
				const char *valstart = breakpt + 1;
				if ( (breakpt = strchr (valstart, '\\')) != NULL )
				{
					value = D_UnescapeUserInfo(valstart, breakpt - valstart);
				}
				else
				{
					value = D_UnescapeUserInfo(valstart, strlen(valstart));
				}
				keyname = FName(ptr, valstart - ptr - 1, true);
			}
			
			// A few of these need special handling.
			switch (keyname)
			{
			case NAME_Gender:
				info->GenderChanged(value);
				break;

			case NAME_PlayerClass:
				info->PlayerClassChanged(value);
				break;

			case NAME_Skin:
				info->SkinChanged(value);
				if (players[pnum].mo != NULL)
				{
					if (players[pnum].cls != NULL &&
						!(players[pnum].mo->flags4 & MF4_NOSKIN) &&
						players[pnum].mo->state->sprite ==
						GetDefaultByType (players[pnum].cls)->SpawnState->sprite)
					{ // Only change the sprite if the player is using a standard one
						players[pnum].mo->sprite = skins[info->GetSkin()].sprite;
					}
				}
				// Rebuild translation in case the new skin uses a different range
				// than the old one.
				R_BuildPlayerTranslation(pnum);
				break;

			case NAME_Team:
				UpdateTeam(pnum, atoi(value), update);
				break;

			case NAME_Color:
				info->ColorChanged(value);
				break;

			default:
				cvar_ptr = info->CheckKey(keyname);
				if (cvar_ptr != NULL)
				{
					assert(*cvar_ptr != NULL);
					UCVarValue val;
					FString oldname;

					if (keyname == NAME_Name)
					{
						val = (*cvar_ptr)->GetGenericRep(CVAR_String);
						oldname = val.String;
					}
					val.String = CleanseString(value.LockBuffer());
					(*cvar_ptr)->SetGenericRep(val, CVAR_String);
					value.UnlockBuffer();
					if (keyname == NAME_Name && update && oldname != value)
					{
						Printf("%s is now known as %s\n", oldname.GetChars(), value.GetChars());
					}
				}
				break;
			}
			if (keyname == NAME_Color || keyname == NAME_ColorSet)
			{
				R_BuildPlayerTranslation(pnum);
				if (StatusBar != NULL && pnum == StatusBar->GetPlayer())
				{
					StatusBar->AttachToPlayer(&players[pnum]);
				}
			}
		}
	}
	*stream += strlen (*((char **)stream)) + 1;
}
void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
{
	userinfo_t *info = &players[i].userinfo;
	const char *ptr = *((const char **)stream);
	const char *breakpt;
	FString value;
	bool compact;
	int infotype = -1;

	if (*ptr++ != '\\')
		return;

	compact = (*ptr == '\\') ? ptr++, true : false;

	if (i < MAXPLAYERS)
	{
		for (;;)
		{
			int j;

			breakpt = strchr (ptr, '\\');

			if (compact)
			{
				value = D_UnescapeUserInfo(ptr, breakpt != NULL ? breakpt - ptr : strlen(ptr));
				infotype++;
			}
			else
			{
				assert(breakpt != NULL);
				// A malicious remote machine could invalidate the above assert.
				if (breakpt == NULL)
				{
					break;
				}
				const char *valstart = breakpt + 1;
				if ( (breakpt = strchr (valstart, '\\')) != NULL )
				{
					value = D_UnescapeUserInfo(valstart, breakpt - valstart);
				}
				else
				{
					value = D_UnescapeUserInfo(valstart, strlen(valstart));
				}

				for (j = 0;
					 UserInfoStrings[j] && strnicmp (UserInfoStrings[j], ptr, valstart - ptr - 1) != 0;
					 ++j)
				{ }
				if (UserInfoStrings[j] == NULL)
				{
					infotype = -1;
				}
				else
				{
					infotype = j;
				}
			}
			switch (infotype)
			{
			case INFO_Autoaim: {
				double angles;

				angles = atof (value);
				if (angles > 35.f || angles < 0.f)
				{
						info->aimdist = ANGLE_1*35;
				}
				else
				{
						info->aimdist = abs ((int)(angles * (float)ANGLE_1));
				}
								}
				break;

			case INFO_Name:
				{
					char oldname[MAXPLAYERNAME+1];

					strcpy (oldname, info->netname);
					strncpy (info->netname, value, MAXPLAYERNAME);
					info->netname[MAXPLAYERNAME] = 0;
					CleanseString(info->netname);

					if (update && strcmp (oldname, info->netname) != 0)
					{
						Printf ("%s is now known as %s\n", oldname, info->netname);
					}
				}
				break;

			case INFO_Team:
				UpdateTeam (i, atoi(value), update);
				break;

			case INFO_Color:
				info->color = V_GetColorFromString (NULL, value);
				R_BuildPlayerTranslation (i);
				if (StatusBar != NULL && i == StatusBar->GetPlayer())
				{
					StatusBar->AttachToPlayer (&players[i]);
				}
				break;

			case INFO_Skin:
				info->skin = R_FindSkin (value, players[i].CurrentPlayerClass);
				if (players[i].mo != NULL)
				{
					if (players[i].cls != NULL &&
						players[i].mo->state->sprite ==
						GetDefaultByType (players[i].cls)->SpawnState->sprite)
					{ // Only change the sprite if the player is using a standard one
						players[i].mo->sprite = skins[info->skin].sprite;
						players[i].mo->scaleX = skins[info->skin].ScaleX;
						players[i].mo->scaleY = skins[info->skin].ScaleY;
					}
				}
				// Rebuild translation in case the new skin uses a different range
				// than the old one.
				R_BuildPlayerTranslation (i);
				if (StatusBar != NULL && i == StatusBar->GetPlayer())
				{
					StatusBar->SetFace (&skins[info->skin]);
				}
				break;

			case INFO_Gender:
				info->gender = D_GenderToInt (value);
				break;

			case INFO_NeverSwitchOnPickup:
				if (value[0] >= '0' && value[0] <= '9')
				{
					info->neverswitch = atoi (value) ? true : false;
				}
				else if (stricmp (value, "true") == 0)
				{
					info->neverswitch = 1;
				}
				else
				{
					info->neverswitch = 0;
				}
				break;

			case INFO_MoveBob:
				info->MoveBob = (fixed_t)(atof (value) * 65536.f);
				break;

			case INFO_StillBob:
				info->StillBob = (fixed_t)(atof (value) * 65536.f);
				break;

			case INFO_PlayerClass:
				info->PlayerClass = D_PlayerClassToInt (value);
				break;

			default:
				break;
			}

			if (breakpt)
			{
				ptr = breakpt + 1;
			}
			else
			{
				break;
			}
		}
	}

	*stream += strlen (*((char **)stream)) + 1;
}