Double names in scoreboard


(Chruker) #1

Hi

Got side-tracked into finding out why players can occur twice in the scoreboard. After having looked through the code I’ve found this in the G_SendScore function near the bottom of the function:

			if(size + strlen(entry) > 1000) {
				i--; // we need to redo this client in the next buffer (if we can)
				break;
			}
			size += strlen(entry);

			Q_strcat(buffer, 1024, entry);
			if( ++count >= 32 ) {
				i--; // we need to redo this client in the next buffer (if we can)
				break;
			}

The scores are sent in multiple packages if there are too many in one packet or if the buffer string is above 1024 chars.

From what I can understand of this code it breaks away properly when current entry is too big to fit within the buffer. However after that check it copies it. It then checks if the current entry would be number 32 or above. If thats the case it decreases i, so that the entry would be re-processed for the next packet. However it is already in the current packet.

My guess is that moving the count check so that you get this:

			if(size + strlen(entry) > 1000) {
				i--; // we need to redo this client in the next buffer (if we can)
				break;
			}

			// CHRUKER: #060 - Trying to fix the duplicate names on the scoreboard
			if( ++count >= 32 ) {
				i--; // we need to redo this client in the next buffer (if we can)
				break;
			} // #060

			size += strlen(entry);

			Q_strcat(buffer, 1024, entry);

***** EDIT: This turned out to fix 50% of it. See the later post for the entire fix: http://www.splashdamage.com/index.php?name=pnPHPbb2&file=viewtopic&p=112871#112871 ******

could possibly solve it. However I have no way of testing this, since I got no hugely popular server nor bot support yet.

Any comments?


(Calzonzin) #2

I have submitted your fix for the etpub development team (with a link to this thread) ( http://linespeed.net/projects/etpub/ticket/193 ). I cannot guarantee if/when they will implement your fix, but hopefully they will take a shot at it.

I know it always startles people who see two players with the same name, someone always thinks someone else is impersonating them… Thanks for the code!


(Chruker) #3

I’m still not entirely sure that this is what needs to be done in order to fix it, but I think its a step in the right direction.

Here is a screenshot taken of a demo:

The demo was recorded on a ET+shrubet server, and you can clearly see the double names in the allied side of the scoreboard. However in this case there a two sets of doublets.

I played the demo back in a modified 2.56 where I could see how the score strings were sent. As you can see from the console the two last players with 30 and 31 are repeated as entry 0 and 1 in the next packet.

Also stumbled over another thing. In ClientThink_real the server checks whether to send the score to a client or not. It seems like a strange place to do that. I would rather do it in ClientEndframe. Anyway, its not really breaking anything the way it is, it could just be a waste of bandwidth. <<— Unless the client side code is only requesting the score once in a while…


(Chruker) #4

Ok, here is the correct fix:

			if(size + strlen(entry) > 1000) {
				// CHRUKER: #060 - Removed the line which decreased i
				// we need to redo this client in the next buffer (if we can)
				break;
			}

			// CHRUKER: #060 - Move this block so that it breaks away before copying the entry
			if( ++count >= 32 ) {
				// CHRUKER: #060 - Removed the line which decreased i
				// we need to redo this client in the next buffer (if we can)
				break;
			} // #060

			size += strlen(entry);

			Q_strcat(buffer, 1024, entry);

The difference between this and the fix in the first post is that the two line that decreased i has been removed. This was why there were two duplicates: i was both decreased and its next skip in increase was bypassed.

Anyway this works. I just tested it with 40 wolfbots :slight_smile:


(Calzonzin) #5

Great! Hey I did not ask you before… Are you ok with the etpub team if they cut and paste your fix into the etpub mod?


(Chruker) #6

yes yes, please :slight_smile: and the fix is entirely serverside :slight_smile:


(Calzonzin) #7

Oops! Tony went through the while function and cleaned it all up. There is a diff link in the etpub ticket: http://linespeed.net/projects/etpub/ticket/193

Thanks!


(deathazre) #8

I always catch this trying to get the server information in XQF when the shrub server I normally play on is nearly full – appears to be an improperly fragmented packet, it definitely doesn’t pass through my openbsd firewall using ‘scrub all’. Server admin thinks it might be related to this.

17:35:03.555531 10.100.14.15.61993 > melek.hh-ops.org.27960:  udp 12 (DF)
17:35:03.831154 melek.hh-ops.org.27960 > 10.100.14.15.61993:  udp 265 (DF)
17:35:03.831371 10.100.14.15.61993 > melek.hh-ops.org.27960:  udp 14 (DF)
17:35:04.002506 melek.hh-ops.org.27960 > 10.100.14.15.61993:  udp 1531 (frag 56772:1480@0+) (DF)
17:35:04.058890 melek.hh-ops.org > 10.100.14.15: (frag 56772:59@1480) (DF)
17:35:04.559599 10.100.14.15.61993 > melek.hh-ops.org.27960:  udp 14 (DF)
17:35:04.606502 melek.hh-ops.org.27960 > 10.100.14.15.61993:  udp 1531 (frag 41727:1480@0+) (DF)
17:35:04.663955 melek.hh-ops.org > 10.100.14.15: (frag 41727:59@1480) (DF)
17:35:05.065004 10.100.14.15.61993 > melek.hh-ops.org.27960:  udp 14 (DF)
17:35:05.126155 melek.hh-ops.org.27960 > 10.100.14.15.61993:  udp 1532 (frag 19142:1480@0+) (DF)
17:35:05.181640 melek.hh-ops.org > 10.100.14.15: (frag 19142:60@1480) (DF)

(Chruker) #9

Sorry deathazre but my lack of knowledge of bsd firewalls and the deeper network workings of the quake3 engine, prevents me from giving a full answer. However people have mentioned that serverinfo doesn’t arrive when they press the serverinfo button on servers which are nearly full. If the network packages are fragmented inproperly and blocked by a firewall that could explain the lack of response.

Hopefully some of the more hardcore programmers around here can shed some light on the issue.

Anyway, all that said. These double names on the scoreboard (displayed when TAB is held down), existed only there. In the serverinfo, the Limbo or output from the /players command, there were no such double names.


(jaybird) #10

I implemented this but sometimes I’m still ending up with a duplicate. This dup does not have the XP nor the ping on the scoreboard. This piece of code confuses me:


if( ++count >= 32 ) {
	//i--; // we need to redo this client in the next buffer (if we can)
	break;
}
size += strlen(entry);

Q_strcat(buffer, 1024, entry);


trap_SendServerCommand( ent-g_entities, va("%s %i%s", startbuffer, count, buffer));

The piece of interest is the pre-incremented count variable.
So isn’t this pre-increment wrong? I might not be thinking about this correctly, but if we preincrement and then test against it, and then immediately after the break transmit it with that incremented count, aren’t we telling the client it’s receiving one more than is really there since we never really add that entry into the buffer?


(jaybird) #11

Actually, the more I think about it, moving…


if( ++count >= 32 ) {
	//i--; // we need to redo this client in the next buffer (if we can)
	break;
}

… a world of sense. The pre-increment gives the correct value for the amount of scores in the buffer, and it then checks to make sure that we’re under 32 scores. If there are more (including the one we just did), it breaks and sends, followed by the next (possible) buffer. I’m gonna test this out and see if I have issues again.

From the looks of it, the reason we were getting those duplicates is because of the decremented i’s. There’s no reason to step back an i at all since the break keeps the i from incrementing in the for loop.

Edit: And while I’m at it, I just figured out the reason we got TWO duplicates previously. In this same piece of code, where we originally decremented the i, i actually needs to be INCREMENTED, because we’ve handled that player, and if we break, i won’t get incremented through the for loop. If we decrement there, not only will we do the current score again, but the one before one, ending up with us sending 2 players twice.

So basically, with the way I’m thinking it needs to be, keep the 2nd check after the string copy, taking the i-- out of the first check, and adding an i++ to the 2nd check.

I’ll let you guys know how this goes.


(Chruker) #12

Maybe its because I’m tired. But I’m not really sure what you ended up with. Could you post your final code?


(jaybird) #13

Sure! Here you go…


			// Fix double player listings
			if(size + strlen(entry) > 1000) {
				//i--; // we need to redo this client in the next buffer (if we can)
				// do NOT decrement, will cause a dup
				break;
			}
			size += strlen(entry);

			Q_strcat(buffer, 1024, entry);

			if( ++count >= 32 ) {
				//i--; // we need to redo this client in the next buffer (if we can)
				i++; // actually, needs to be incremented so we get no dups.
				break;
			}

I left the indenting there, too lazy to format it for here heh.


(jaybird) #14

Put this up on the server last night. It was full at 46 (plus a slot or two at times) and no duplicates. This should do the trick.