Area Filtering ======================================= The concept of **area filtering** allows the networking library to send data only to specific groups of clients. This reduces network load and prevents players from receiving irrelevant information. Example: If clients A, B, and C are in a dungeon while client D is back in town, the dungeon events should only be broadcast to A, B, and C. Client D doesn’t need dungeon updates until they enter it. This system is useful for: - Interest management (only sync what is nearby or relevant). - Logical grouping of players (teams, parties, chat channels). - Large worlds split into zones or instanced dungeons. Examples -------- Rogue ~~~~~ Imagine a stealth character who can hide from other players. When they activate stealth, the server can remove their character object from the area shared with other players. To the hidden player, their own character is still visible locally. But other players in the same area no longer receive synchronization messages for that object. This avoids clumsy solutions like making the object invisible on clients, and instead naturally stops sending network updates. Team Chat ~~~~~~~~~ Team chat is another case where filtering is useful. - Place all players on a team into a **team-specific area** (in addition to their geographic area). - When one player sends a chat RPC, the server delivers it only to clients in the same team area. This prevents players on other teams from overhearing messages and keeps communication efficient. Virtual Areas ~~~~~~~~~~~~~ Areas can also represent **locations** in large games. For example: - A multi-floor dungeon could use a separate area ID for each floor. - Clients on floor 1 don’t receive updates for objects on floor 2. - If a player moves to floor 2, the server adds them to that area and removes them from floor 1. Similarly, areas can represent entirely different **scenes**. A player in a town scene doesn’t need network traffic for players in a dungeon scene. Using Area Filters ------------------ The API for areas is provided by ``ClientNetwork`` and ``ServerNetwork``. **On the Client:** - ``AddToArea(int areaId)`` – Requests to join a new area. - ``RemoveFromArea(int areaId)`` – Requests to leave an area. - ``AddObjectToArea(int objectId, int areaId)`` – Puts a specific object into an area. - ``RemoveObjectFromArea(int objectId, int areaId)`` – Removes a specific object from an area. Example: .. code-block:: csharp // Join dungeon area 5 clientNetwork.AddToArea(5); // Leave the town area clientNetwork.RemoveFromArea(1); // Put a summoned monster into the dungeon area clientNetwork.AddObjectToArea(monsterId, 5); **On the Server:** - ``AddToArea(clientId, areaId)`` – Assigns a client to an area. - ``RemoveFromArea(clientId, areaId)`` – Removes a client from an area. - ``AddObjectToArea(objectId, areaId)`` – Associates an object with an area. - ``RemoveObjectFromArea(objectId, areaId)`` – Removes an object from an area. Synchronizing Game State ~~~~~~~~~~~~~~~~~~~~~~~~ When a client joins an area that already contains objects, the server must **synchronize the existing state**. The flow is: 1. Client requests entry into an area. 2. Server approves and adds the client to the area list. 3. Server sends an ``AddToArea`` confirmation message. 4. Server calls ``SendInitializationData``: - Instantiates all current objects in that area for the new client. - Sends their latest sync data (position, rotation, state). 5. Client now sees the current state of the area. This ensures new clients see a **consistent world snapshot** when they enter an area, instead of waiting for the next update messages. Area Lifecycle -------------- .. code-block:: Client requests AddToArea(5) | v Server validates request | v Server adds client to area 5 | v Server sends: - Confirmation message - All objects currently in area 5 | v Client instantiates area objects | v Client receives normal sync updates for area 5 Best Practices -------------- - Keep areas **coarse-grained**. Avoid too many tiny areas, as it increases bookkeeping. - Use areas for **interest management** (visibility, proximity, zones). - Always handle **removals** cleanly. When a client leaves an area, ensure any objects exclusive to that area are destroyed on their machine. - Areas can overlap: a player can belong to multiple areas at once (e.g., dungeon floor + team chat area). - Treat area changes as **authority-driven**: the server is the source of truth for who is in which area. Summary ------- - Areas group clients and objects for efficient network updates. - Clients use ``AddToArea`` and ``RemoveFromArea`` to request changes. - Server synchronizes state when clients join an area. - Useful for stealth, chat channels, dungeons, and large-world partitioning. - Areas reduce bandwidth and improve gameplay clarity by filtering irrelevant updates. Visual Examples --------------- Town vs Dungeon (Separate Areas) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: [Area: Town (id=1)] [Area: Dungeon (id=5)] +--------------------+ +----------------------+ | Client D | | Client A | | (in Town) | | Client B | | | | Client C | +--------------------+ +----------------------+ Updates from A/B/C (Dungeon events) are only forwarded to clients in Area 5. Client D does NOT receive Dungeon updates while in Area 1. Flow: A/B/C ---> Server ---> {A,B,C} (filtered by Area 5) D ---> Server ---> {D} (filtered by Area 1) Overlapping Areas (Team Chat + Location) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: Areas can overlap: players belong to a location area AND a team area. [Team Alpha (id=100)] [Team Beta (id=200)] +---------------------+ +--------------------+ | A (also in Area 5) | | C (also in Area 5) | | B (also in Area 5) | | D (also in Area 1) | +---------------------+ +--------------------+ - Location: A,B,C in Dungeon (Area 5), D in Town (Area 1) - Team chat: A,B share Team Alpha (100) → chat RPCs delivered to {A,B} C shares Team Beta (200) → chat RPCs delivered to {C} D shares Team Beta (200) → chat RPCs delivered to {D} Example: Client A sends Team Alpha chat: A ---> Server ---> {A,B} (filtered by Area 100) Client C sends dungeon emote (location-based): C ---> Server ---> {A,B,C} (filtered by Area 5) Per-Object Area Membership ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: Some objects exist only in certain areas (e.g., a summoned monster in a dungeon). Server object table (simplified): ObjId Prefab Areas ----- ----------- ----------------- 42 "Monster" [5] (Dungeon only) 77 "TownFountain" [1] (Town only) 93 "Door" [5,7] (Spans two dungeon floors) Spawn monster for dungeon players only: AddObjectToArea(42, 5) └─> Server sends Instantiate(42,"Monster",...) only to clients in Area 5 Player exits dungeon (Area 5 → 1): - RemoveFromArea(Player, 5) - Server sends Destroy(42) to that player (no longer shares Area 5) - Player now stops receiving updates for Obj 42 End-to-End Filtered Message Flow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: (Client B in Dungeon presses a lever) Client B CallRPC("PullLever", MessageReceiver.OtherClientsInArea, leverId) | v Server - Determines B's areas (e.g., [5]) - Finds clients that share Area 5 except B - Forwards RPC only to those clients | +--> Client A (in Area 5) executes PullLever() | +--> Client C (in Area 5) executes PullLever() | └X Client D (in Area 1) receives nothing Quick Snippets -------------- **Client joins an area and receives its current state** .. code-block:: csharp // Client-side clientNetwork.AddToArea(5); // request to join dungeon // Server flow (simplified) AddToArea(clientId, 5); // add to area set // Send confirmation and initialization snapshot: // - Instantiate all objects currently in Area 5 // - Send latest Sync/LiteSync data for each // Client now sees the up-to-date dungeon state **Server sends an RPC to everyone in an area** .. code-block:: csharp // e.g., start a boss encounter for dungeon players only var areaIds = new List { 5 }; serverNetwork.CallRPCToArea( "StartBossEncounter", UCNetwork.MessageReceiver.AllClientsInArea, areaIds, -1 // networkId: -1 = call on the network manager object )