Author Topic: Area of Interest  (Read 5820 times)

Masaaki

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
Area of Interest
« on: February 04, 2014, 09:37:26 PM »
Hello
I'm using TNet in an application designed for fairly large player populations (aiming for by default a max of 128 players per server, but server hosts can change this value).
One thing I want to add is interest management. With a 10km world, a hundred players scattered across the world, player-made structures, loot chests, monsters, and more, doing it "the naive" way (zero interest management, player gets messages for everything in the entire world) is probably not going to cut it.

So on a conceptual level, when an object enters a client's area of interest, the server sends a Create message for that object and additionally any buffered RFCs. When an object leaves a client's area of interest, the client destroys that object. The server only sends RFCs of an object to a player if that object is in their area of interest. (going to skip how the actual checks are performed for the sake of argument - doesn't really matter, will probably use quad trees though)

Question is, can I accomplish this without touching core TNet code, or should I modify TNet for my needs?

(by the way, when I refer to the server I mean a "game server" which is just a special build of my game that spins up a TNet Server and immediately joins as the host)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Area of Interest
« Reply #1 on: February 05, 2014, 04:59:24 PM »
You can currently achieve this in TNet by joining a channel based on your position -- so think of your world as being divided into cells, with each cell having a region. Once the player enters this region, join a specific channel (for example channel ID of cell's [(X << 8) | Y] would give you limit of 255x255). The idea is that each cell would have a fixed channel ID that players join.

The problem is that this also implies that people who are on the edges of their cell but happen to be in different cells may not see each other even if they are actually right next to each other in the world. I plan to add a feature to TNet that makes it possible to either be in several channels at the same time, or -- more likely -- a way to subscribe to sub-channels/regions within each channel.

It's quite an addition though, so there is no ETA.

Masaaki

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
Re: Area of Interest
« Reply #2 on: February 05, 2014, 07:10:43 PM »
I'm probably just going to get my hands dirty and rip apart the TNet code for this then :)
I think what I'll do is have my "interesting objects" (TNObjects which can enter and exit a player's area of interest), sorted into a quadtree. My server keeps track of which object a client is currently interested in at any given time (a list of interesting objects can be obtained by querying a rectangle of the quadtree). If any new objects get added to this list of interesting objects, Create messages are sent to the player. If any objects are removed from this list of interesting objects, Destroy messages are sent to the player. Then I could add a check to see if a given TNObject is "interesting" to a given player, so prior to sending an RFC packet I could check if the TNObject is interesting to the given client and if not don't send the packet.

That said, I would actually like to see a feature in TNet of being able to set the scope of a TNObject per-player. So perhaps I can say (in psuedo code) tno.SetScope( player, true/false ). So if I set it to "false" the player stops receiving any RPCs. If I set it to true, the player gets all buffered RPCs and any others sent from then on. It should be trivial to also add that setting False sends a Destroy message, and setting True sends a Create message (maybe controlled by a parameter of the SetScope function of whether or not I want it to send Create/Destroy messages).
That should afford pretty fine-grained control over this stuff.

Masaaki

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
Re: Area of Interest
« Reply #3 on: February 06, 2014, 12:20:19 AM »
Turned out to not be too difficult to add this myself.
(to clarify the following, when I say TNServer I mean the actual physical server that comes with TNet, and when I say Game Server I mean a special build of my game that spins up a TNServer and joins as the host)

So I modified TNServer to add a "blacklist". So I can essentially register a TcpPlayer with a particular UID. So when the TNServer goes to send an RFC to everyone, it checks if a given player is on the blacklist for the given TNObject UID before sending.
I added a new Packet.RequestSetScope. This tells the TNServer to add or remove the given player from the blacklist of a given UID. It also generates ResponseDestroy and ResponseCreate packets if you set scope to False or True (respectively).
Then I wrapped this with a function TNObject.SetScope( TNet.Player player, bool hasScope ) which sends the RequestSetScope packet to the TNServer.

I use this for my area of interest management like this:
- Interesting Objects are sorted into a quadtree each frame.
- Interest Observers (players) query the quadtree for nearby objects within their area of interest. When new objects enter their area of interest, they call newObject.SetScope( myOwner, true ), and when objects leave their area of interest they call leavingObject.SetScope( myOwner, false ). This is performed on the Game Server (which always has all objects loaded, and never has it's own player)

Beyond an edge case (nullref exception is throwing my Game Server for a loop at the moment, nothing a little debugging can't fix), it appears to be working perfectly. If I walk away from my spawned enemy mob, they are deleted from the scene. If I return, they get re-instantiated.
So far has taken about a day.

EDIT: There's always another edge case, lol.
« Last Edit: February 06, 2014, 12:45:31 AM by Masaaki »

gg67

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 66
    • View Profile
Re: Area of Interest
« Reply #4 on: February 06, 2014, 02:20:15 PM »
Aren, when implementing your cell/region concept, does the user "see" the other region while they are walking towards it?If so, does that mean every scene have the main region and the surrounding regions (although you can only walk around the main region)? And then once you reach and edge region, you switch channels and set that edge region as your main region, etc.

Thanks!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Area of Interest
« Reply #5 on: February 06, 2014, 10:47:38 PM »
That's an interesting way to do it, Masaaki.

@gg67: I was thinking of keeping it simple and just making it possible to set a region ID for each TNO. The player would then subscribe to regions as they travel (and it's up to you to convert their position to some region ID), which would result in the server sending appropriate create/destroy calls. Since the player can be in multiple regions at the same time, there would be no concept of a "main" region.

The tricky part is making it so that the object creation that gets handled on the server knows about the region ID when it's creating the object, which would imply modifying the creation logic a bit.

The region-based approach can also be used to create chat subscriptions (joining chatrooms in-game).