Code: Select all
//======================================================================================================
// BUGFIX for Nexgen servers... a local SendPlayers().
//======================================================================================================
function bool SendPlayers(IpAddr Addr, int queryNum, out int packetNum, int bFinalPacket) {
local Pawn P;
local bool bResult, bSendResult;
local int i;
if (Level.Game.NumPlayers <= 0) {
return SendQueryPacket(Addr, "", queryNum, packetNum, bFinalPacket);
}
bResult = false;
P = Level.PawnList;
while (i < Level.Game.NumPlayers) {
if (P.IsA('PlayerPawn')) {
if (i == Level.Game.NumPlayers - 1 && bFinalPacket == 1) {
bSendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), queryNum, packetNum, 1);
} else {
bSendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), queryNum, packetNum, 0);
}
bResult = bSendResult || bResult;
i++;
}
P = P.NextPawn;
}
return bResult;
}
If there be NumPlayers not zero and no any PlayerPawn, loop never end and server crash with runaway limit.
On condition need check "P != None".
2. This code report spectators as well. Which not match stock behavior:
Code: Select all
// Send data for each player
function bool SendPlayers(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket)
{
local Pawn P;
local int i;
local bool Result, SendResult, SentFinalPacket;
Result = false;
SentFinalPacket = false;
for ( P = Level.PawnList; P != none; P = P.nextPawn)
{
if (P.IsA('PlayerPawn') && !P.IsA('Spectator'))
{
if( i==Level.Game.NumPlayers-1 && bFinalPacket==1)
{
SendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), QueryNum, PacketNum, 1);
SentFinalPacket = true;
}
else
SendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), QueryNum, PacketNum, 0);
Result = SendResult || Result;
i++;
}
}
// stijn: make sure we send the \final\ packet even if we didn't report all players
if (bFinalPacket == 1 && !SentFinalPacket)
SendQueryPacket(Addr, "", QueryNum, PacketNum, 1);
return Result;
}
Finally, because of this loop there exists next bug:
1. Play 2 players. NumPlayers is 2. Report is ok.
2. Enter spectator.
3. NumPlayers is still 2, but spectator send as player. It is first, because new pawn get into head of Level.PawnList chain.
4. So on send will be send spectator (as player) and one from player. After that loop stop. And second player not send.
So finally we have spectator in output, and missed player.
Automatically merged
Code: Select all
function bool SendPlayers(IpAddr Addr, int queryNum, out int packetNum, int bFinalPacket) {
local Pawn P;
local bool bResult, bSendResult, bSentFinalPacket;
local int i;
if (Level.Game.NumPlayers <= 0) {
return SendQueryPacket(Addr, "", queryNum, packetNum, bFinalPacket);
}
bResult = false;
for ( P = Level.PawnList; P != none; P = P.nextPawn) {
if (P.IsA('PlayerPawn') && !P.IsA('Spectator')) {
if (i == Level.Game.NumPlayers - 1 && bFinalPacket == 1) {
bSendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), queryNum, packetNum, 1);
bSentFinalPacket = true;
} else {
bSendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), queryNum, packetNum, 0);
}
bResult = bSendResult || bResult;
i++;
}
}
// stijn: make sure we send the \final\ packet even if we didn't report all players
if (bFinalPacket == 1 && !bSentFinalPacket)
SendQueryPacket(Addr, "", QueryNum, PacketNum, 1);
return bResult;
}
There fixed loop, stop report spectators, and integrate Anth fix for send final packet in all cases.
Automatically merged
resultSet = resultSet$Chr(92)$"BotSkill"$Chr(92)$class'ChallengeBotInfo'.default.Skills[Level.Game.Difficulty];
to
resultSet = resultSet$Chr(92)$"BotSkill"$Chr(92)$class'ChallengeBotInfo'.default.Skills[DeathMatchPlus(Level.Game).BotConfig.Difficulty];
For fix discussed in topic bug.