Players and visibility

Started by
10 comments, last by GameDev.net 18 years, 4 months ago
I'm currently pseudo coding the portion of my network code that will hide/show players as they move into the current player's range of visibility. I'm halfway where I need to be :) When a player (VisiblePlayer) moves into the range of visibility (CurrentPlayer): -Server sends CurrentClient a packet describing a position for a VisiblePlayer. -Client establishes that the VisiblePlayer is not in the current list of visible players. -Client then sends back asking for full details of the VisiblePlayer, so it can be drawn on the screen -Server determines of the requested details are allowed to be shown on the screen (to prevent hacks and spoofing of requests) -Server then sends back, if allowed, the details of the VisiblePlayer -Client draws VisiblePlayer at updatedlocation On the other hand, when VisiblePlayer walks outside of the visibility range of CurrentPlayer, how do you tell the Client to drop the player off its visible players list? One thought I had was to have a "LastUpdated" timer. If an update wasn't received within XX seconds, then the Client would remove the VisiblePlayer. This would require a "heartbeat" type function though, I believe. IE, what if a player goes AFK..they should just stand there, not go poof. Thanks in advance :) Edit: If this is in the wrong place, please move to where applicable :D Thx!
Advertisement
what type of game is this? 2d or 3d??

it's been a while, but IIRC, the way I handled this in my 2D mini MMORPG it is this:

-player requests to move
-server verifies
-server checks ALL players on the SAME MAP to see who is in the range of the player, and forwards the movement to only the people within that range


if you need "full details" on how the player should be rendered, then when the player first enters the map, send everyone on the map these details. you could even get more in-depth and keep "version numbers", so when people left the map, and came back, the server checks to see if the visible players have the same "version" of what that player looks like, and only sends the data to people with "older versions".

of course i'm assuming you are making a game that would fit to this protocol. you have to give more information [grin].
FTA, my 2D futuristic action MMORPG
Sorry...

This is a 3d game, aiming for MMORPG.

I dont' want to send any player data unless the player is absolutely visible to the person requesting (snuffs out radar hacks and the likes).


Edit: And I'm pretty sure I can handles the "enters visible range" events, but I'm not sure about the "exit visible range" events.
Quote:Original post by Siberwulf
On the other hand, when VisiblePlayer walks outside of the visibility range of CurrentPlayer, how do you tell the Client to drop the player off its visible players list?


Ok... I think I fully understand your problem now... and I don't think my last reply was too helpfull [grin].

OK, I have solved this EXACT problem in my game before, but it's been so long... I believe it worked something like this:

- on the server, each player has a list of what players are visible to him. he builds this for each player when they first enter the map.
- client requests to move
- server loops through each player on the map...is this player close enough? if so, make sure he is on that players list...if not, add him to that list. is the player NOT close enough? if so, remove him from the list
- server forwards movement message to all players on the list. he then forwards to all players who were removed, telling them he is no longer visible. this should only have to be a singly byte (EDIT: you said MMMORPG, so 2 bytes probably), minus headers and stuff.

hope that helps.


FTA, my 2D futuristic action MMORPG
step 3/4 should look like this in pseudo-code:

case REQUEST_MOVEMENT:P1 = this player who's requesting movement   for each player (NOT P1) P2 on this map         if(P2.IsVisible(P1))             P2.AddToList(P1)             P1.AddToList(P2)         else             P2.RemoveFromList(P1)             P1.RemoveFromList(P2)


You can assume that the AddToList() and RemoveFromList() functions will check if they were actually added / removed, and if so send the apprioriate packet.
FTA, my 2D futuristic action MMORPG
Quote:Original post by Siberwulf
Sorry...

This is a 3d game, aiming for MMORPG.

I dont' want to send any player data unless the player is absolutely visible to the person requesting (snuffs out radar hacks and the likes).


Edit: And I'm pretty sure I can handles the "enters visible range" events, but I'm not sure about the "exit visible range" events.


This post confused me. In the original post you made, your logic prevents the client from getting movement packets unless the player is in range, therefore they can't have radar hacks and stuff.

Really the only reason to send a "player is no longer visible" to the client would be for rendering, not security purposes. It is for the situation where player A left player B's range, and stops getting movement packets.... then player B has player A's OLD position, and if he runs into that position, player A will be rendered there, in a frozen type state. (even though he's somewhere completely different, probably moving around)...... although I'm sure you know this already, I just had to remember it for myself [grin]. In this case my logic should handle this.
FTA, my 2D futuristic action MMORPG
I've been stewing on this...

I really don't want the client to rely on the server to remove a player from the render/visibilty list. Yes, I know the hardfast rule that server > client, but i think as far as overhead goes, it might be more prudent to do something like this:

Each player has a heartbeat function. If they haven't sent a movement command in XX seconds, the heartbeat kicks in, like a keep alive. It broadcasts "I'm alive" for all players in visible range. If a client hasn't gotten a heartbeat from a player that is in visible range, its safe to say that player either went link dead, disconnected, or exited the visible range.

Whats your thoughts?
Quote:Original post by Siberwulf
Each player has a heartbeat function. If they haven't sent a movement command in XX seconds, the heartbeat kicks in, like a keep alive. It broadcasts "I'm alive" for all players in visible range. If a client hasn't gotten a heartbeat from a player that is in visible range, its safe to say that player either went link dead, disconnected, or exited the visible range.
Whats your thoughts?


This solution is based on timing. In case of lag, it's perfectly possible that the client won't get any updates for some time, and every other player will disappear (because they time out). It's true that they reappear once the next update gets through, but it's not pretty or clean.

A simple way is to have a list on the server, and have the server check the list and update it. Then calculate the difference with the last list sent to the client and only send what changed. This way you could send a 'remove client' event in case a client moves or disconnects, or you could send a 'client keepalive' event in case you want to use timeouts. When large crowds are standing, like on a marketplace, the keepalive (or zero movement) vs. remove client balance will move towards using remove events.

Viktor
I see what you're saying, and I agree.

But, isn't that a whole lot of overhead? You have to pull a list of visible players, and save it. Next time through, you have to pull the list and compare it to the old list (seems like the bulk of nastiness is that step). Then you can finally send additions/removals to clients. Rinse and repeat for every player connected... Seems it would be ugly to do it that way, but I am seeing flaws in my own idea.
This is, more or less, how we do it:

For each player, keep a list of other visible players, sorted by player ID.

Once every 5 seconds or so, build a new list by traversing your quadtree of player locations. Compare this list (again sorted by player ID) to the old list, and enqueue visibility/invisibility messages based on the differences. Because the lists are both sorted, this can be done in O(visible players) time.

You can even make the number of seconds between visibility events be (1 + #players / 10) or something like that so that your server will scale more gracefully under load. You can also increase the time between visibility checks if you want lots of players on the server, and think that searching the quadtree (or hash grid) of players will take a lot of CPU -- the number of seconds that will work fine is mostly a function of how far away you want to see players pop in at the latest compared to nominal, and how fast players can move.

However, our rule is that you get the closest N players (modified by distance) rather than all players within M meters. The thinking is that, with a bandwidth budget of X per player, X*N is our channel size, and we manage the (narrow) channel quite closely.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement