Null Player Records

Questions, comments, and news on the server side plug-ins and it's API
Post Reply
User avatar
LouMan
Chief Sgt. of Cartography
Chief Sgt. of Cartography
Posts: 338
Joined: Mon Jan 31, 2005 3:05 am
Location: Michigan, USA

Null Player Records

Post by LouMan »

I have created and tested a timed CTF plugin (with help) that seems to be functioning fairly well, despite my very basic understanding of C++. One annoying issue that crops up from time to time is the null player record. I have managed to remove most functions that reference the player record from the plugin, save one: the function that will kill all players from a team whose timer has expired. The code that I have is as follows:

Code: Select all

if (RedTimeElapsed >= TimeLimit) {

  bzAPIIntList *playerList = bz_newIntList();
  bz_getPlayerIndexList ( playerList );

  for ( unsigned int i = 0; i < playerList->size(); i++ ){
		
    bz_PlayerRecord *player = bz_getPlayerByIndex(i);

    if (player){
		
      if (player->team == eRedTeam)
        bz_killPlayer(player->playerID, true, BZ_SERVER);
		
    }

    bz_freePlayerRecord(player);

  }

  bz_deleteIntList(playerList);
  RedLastTime = bz_getCurrentTime ();
  RedLastWarn = bz_getCurrentTime ();
  bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Red team did not capture any other team flags in time.");
  AdjTime = (int)(TimeLimit / 60 + 0.5);
  bz_sendTextMessagef (BZ_SERVER, eRedTeam, "CTF timer is reset to %i minutes for the red team.", AdjTime);
}
With this code, everything works great until there is a player present with a null player record - which happens from time to time for reasons I do not understand. When a player has a null player record, this code will necessarily skip him/her for the mass team kill (pointers to team and playerID of player record). Not really fair when one or two players are not killed when they are supposed to ;)

Does anyone know a work-around for a null player record and how I might identify this player for a mass team kill?
Enigma
Private First Class
Private First Class
Posts: 212
Joined: Sat Apr 23, 2005 3:13 am

Post by Enigma »

Never mind, this post was useless. After reading an article from Devx, I found that delete checks for NULLness. Just ignore this.
User avatar
A Meteorite
Private First Class
Private First Class
Posts: 1786
Joined: Thu Apr 28, 2005 12:56 am
Location: California, U.S.
Contact:

Post by A Meteorite »

I'm not exactly sure why null player records happen, but I have a little logic that you could probably apply: You could make a vector of player slots that have had a null player record. Then later on (maybe a tick event or even later in that function?) you could loop through that vector and attempt to kill each one. Of course, this seems like overkill for such a simple solution. :)

Anyone else who knows more info on null player records would be greatly appreciated... I'm also designing something where a null player record just can't be tolerated - it'd be extremely bad.
Image
Owner @ BZFX
Core Admin @ CAN

Email me: bzmet…@gmail.com
User avatar
LouMan
Chief Sgt. of Cartography
Chief Sgt. of Cartography
Posts: 338
Joined: Mon Jan 31, 2005 3:05 am
Location: Michigan, USA

Post by LouMan »

I tried the vector of player slots and a later kill/kick to no avail. My next thought is to try and use the player update event to kill them rather than a loop through the current players. To do this, I think I'll need to track the number of player update events versus the sum of players - I think.
User avatar
DTRemenak
General
General
Posts: 625
Joined: Thu Jan 16, 2003 4:54 am
Location: U.S.
Contact:

Post by DTRemenak »

Real, connected players should never have null player records.
User avatar
LouMan
Chief Sgt. of Cartography
Chief Sgt. of Cartography
Posts: 338
Joined: Mon Jan 31, 2005 3:05 am
Location: Michigan, USA

Post by LouMan »

I have figured a work-around for the null player records after discovering that this was the result of empty player slots, which I have seen time to time. For example, if a game had the following players:

Slot Callsign
____ ________

0 Player1
1 Player2
2 Player3
5 Player4

The null player records would be slot 3 and slot 4. Since I used the player index function with the playerlist size function, my team kill function would only test for slot 0, 1, 2, and 3 (4 total players, starting at 0); NOT slots 4 or 5.

To remedy this, I added a variable in the player update event that updates to the largest player slot (playerID) in every player update event:

int TempID = ((bz_PlayerUpdateEventData*)eventData)->playerID;

if (TempID >= LargestPlayerID)
LargestPlayerID = TempID;

I use the LargestPlayerID value as the upper limit to my team kill loop and it seems to work fine now :)

btw - the LargestPlayerID variable is reset to zero in my player join event coding, so that it gets a refresh every time a player joins.
User avatar
DTRemenak
General
General
Posts: 625
Joined: Thu Jan 16, 2003 4:54 am
Location: U.S.
Contact:

Post by DTRemenak »

bz_getPlayerIndexList already provides a list of valid id's.

In your original code, try changing:

Code: Select all

    bz_PlayerRecord *player = bz_getPlayerByIndex(i); 
to:

Code: Select all

    bz_PlayerRecord *player = bz_getPlayerByIndex(playerList[i]); 
Alternatively, use iterators to step through playerList directly.

i ranges from 0 to numPlayers, consecutively.
there are i playerList entries, but they are nonconsecutive.
Enigma
Private First Class
Private First Class
Posts: 212
Joined: Sat Apr 23, 2005 3:13 am

Post by Enigma »

DTRemenak wrote: to:

Code: Select all

    bz_PlayerRecord *player = bz_getPlayerByIndex(playerList[i]); 
This is just a small note.

playerList will give you a compiler error. Since playerList is a pointer, playerList would need to be (*playerList) or playerList->operator[](i), if you want to use that operator.


I can't believe I did not notice that you were not using playerList, as I wrote a function for killing a team the day before. :oops:
User avatar
LouMan
Chief Sgt. of Cartography
Chief Sgt. of Cartography
Posts: 338
Joined: Mon Jan 31, 2005 3:05 am
Location: Michigan, USA

Post by LouMan »

Thank you so much gentlemen. I used the playerList->operator[](i) and everything seems to work well. :D
Post Reply