SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TeamManager.h
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 // TODO: optimize the list of teams and team members to be O(1). Store in hashes, use linked lists to get ordered traversal
17
25
26
27 #include "NativeFeatureIncludes.h"
28 #if _RAKNET_SUPPORT_TeamManager==1
29
30 #ifndef __TEAM_MANAGER_H
31 #define __TEAM_MANAGER_H
32
33 #include "PluginInterface2.h"
34 #include "memoryoverride.h"
35 #include "NativeTypes.h"
36 #include "DS_List.h"
37 #include "types.h"
38 #include "DS_Hash.h"
39 #include "DS_OrderedList.h"
40
41 namespace SLNet
42 {
44 class RakPeerInterface;
45
50
53 typedef unsigned char NoTeamId;
54
57 typedef uint8_t WorldId;
58
61 typedef uint16_t TeamMemberLimit;
62
64 #define ALLOW_JOIN_ANY_AVAILABLE_TEAM (1<<0)
65
66 #define ALLOW_JOIN_SPECIFIC_TEAM (1<<1)
67
68 #define ALLOW_JOIN_REBALANCING (1<<2)
69
70 // Bitwise combination of ALLOW_JOIN_ANY_AVAILABLE_TEAM, ALLOW_JOIN_SPECIFIC_TEAM, ALLOW_JOIN_REBALANCING
71 typedef uint8_t JoinPermissions;
72
73 // Forward declarations
74 class TM_Team;
75 class TM_TeamMember;
76 class TM_World;
77 class TeamManager;
78
80 enum JoinTeamType
81 {
83 JOIN_ANY_AVAILABLE_TEAM,
85 JOIN_SPECIFIC_TEAM,
87 JOIN_NO_TEAM
88 };
89
91 enum TMTopology
92 {
93 // Each system will send all messages to all participants
94 TM_PEER_TO_PEER,
95
96 // The host will relay incoming messages to all participants
97 TM_CLIENT_SERVER,
98 };
99
103 struct TeamSelection
104 {
105 TeamSelection();
106 TeamSelection(JoinTeamType itt);
107 TeamSelection(JoinTeamType itt, TM_Team *param);
108 TeamSelection(JoinTeamType itt, NoTeamId param);
109 JoinTeamType joinTeamType;
110
111 union
112 {
113 TM_Team *specificTeamToJoin;
114 NoTeamId noTeamSubcategory;
115 } teamParameter;
116
119 static TeamSelection AnyAvailable(void);
123 static TeamSelection SpecificTeam(TM_Team *specificTeamToJoin);
127 static TeamSelection NoTeam(NoTeamId noTeamSubcategory);
128 };
129
136 class RAK_DLL_EXPORT TM_TeamMember
137 {
138 public:
139 // GetInstance() and DestroyInstance(instance*)
140 STATIC_FACTORY_DECLARATIONS(TM_TeamMember)
141
142 TM_TeamMember();
143 virtual ~TM_TeamMember();
144
153 bool RequestTeam(TeamSelection teamSelection);
154
159 bool RequestTeamSwitch(TM_Team *teamToJoin, TM_Team *teamToLeave);
160
163 TeamSelection GetRequestedTeam(void) const;
164
167 void GetRequestedSpecificTeams(DataStructures::List<TM_Team*> &requestedTeams) const;
168
172 bool HasRequestedTeam(TM_Team *team) const;
173
177 unsigned int GetRequestedTeamIndex(TM_Team *team) const;
178
180 unsigned int GetRequestedTeamCount(void) const;
181
187 bool CancelTeamRequest(TM_Team *specificTeamToCancel);
188
196 bool LeaveTeam(TM_Team* team, NoTeamId _noTeamSubcategory);
197
202 bool LeaveAllTeams(NoTeamId inNoTeamSubcategory);
203
205 TM_Team* GetCurrentTeam(void) const;
206
208 unsigned int GetCurrentTeamCount(void) const;
209
211 TM_Team* GetCurrentTeamByIndex(unsigned int index);
212
214 void GetCurrentTeams(DataStructures::List<TM_Team*> &_teams) const;
215
219 void GetLastTeams(DataStructures::List<TM_Team*> &_teams) const;
220
223 bool IsOnTeam(TM_Team *team) const;
224
226 NetworkID GetNetworkID(void) const;
227
229 TM_World* GetTM_World(void) const;
230
237 void SerializeConstruction(BitStream *constructionBitstream);
238
244 bool DeserializeConstruction(TeamManager *teamManager, BitStream *constructionBitstream);
245
247 void SetOwner(void *o);
248
250 void *GetOwner(void) const;
251
253 NoTeamId GetNoTeamId(void) const;
254
256 unsigned int GetWorldIndex(void) const;
257
259 static unsigned long ToUint32( const NetworkID &g );
260
262 struct RequestedTeam
263 {
264 SLNet::Time whenRequested;
265 unsigned int requestIndex;
266 TM_Team *requested;
267 bool isTeamSwitch;
268 TM_Team *teamToLeave;
269 };
270
271 protected:
272 NetworkID networkId;
273 TM_World* world;
274 // Teams we are a member of. We can be on more than one team, but not on the same team more than once
275 DataStructures::List<TM_Team*> teams;
276 // If teams is empty, which subcategory of noTeam we are on
277 NoTeamId noTeamSubcategory;
278 // Teams we have requested to join. Mutually exclusive with teams we are already on. Cannot request the same team more than once.
279 DataStructures::List<RequestedTeam> teamsRequested;
280 // If teamsRequested is not empty, we want to join a specific team
281 // If teamsRequested is empty, then joinTeamType is either JOIN_NO_TEAM or JOIN_ANY_AVAILABLE_TEAM
282 JoinTeamType joinTeamType;
283 // Set by StoreLastTeams()
284 DataStructures::List<TM_Team*> lastTeams;
285 SLNet::Time whenJoinAnyRequested;
286 unsigned int joinAnyRequestIndex;
287 void *owner;
288
289 // Remove from all requested and current teams.
290 void UpdateListsToNoTeam(NoTeamId nti);
291 bool JoinAnyTeamCheck(void) const;
292 bool JoinSpecificTeamCheck(TM_Team *specificTeamToJoin, bool ignoreRequested) const;
293 bool SwitchSpecificTeamCheck(TM_Team *teamToJoin, TM_Team *teamToLeave, bool ignoreRequested) const;
294 bool LeaveTeamCheck(TM_Team *team) const;
295 void UpdateTeamsRequestedToAny(void);
296 void UpdateTeamsRequestedToNone(void);
297 void AddToRequestedTeams(TM_Team *teamToJoin);
298 void AddToRequestedTeams(TM_Team *teamToJoin, TM_Team *teamToLeave);
299 bool RemoveFromRequestedTeams(TM_Team *team);
300 void AddToTeamList(TM_Team *team);
301 void RemoveFromSpecificTeamInternal(TM_Team *team);
302 void RemoveFromAllTeamsInternal(void);
303 void StoreLastTeams(void);
304
305 friend class TM_World;
306 friend class TM_Team;
307 friend class TeamManager;
308 };
309
316 class RAK_DLL_EXPORT TM_Team
317 {
318 public:
319 // GetInstance() and DestroyInstance(instance*)
320 STATIC_FACTORY_DECLARATIONS(TM_Team)
321
322 TM_Team();
323 virtual ~TM_Team();
324
332 bool SetMemberLimit(TeamMemberLimit _teamMemberLimit, NoTeamId noTeamSubcategory);
333
335 TeamMemberLimit GetMemberLimit(void) const;
336
338 TeamMemberLimit GetMemberLimitSetting(void) const;
339
347 bool SetJoinPermissions(JoinPermissions _joinPermissions);
348
350 JoinPermissions GetJoinPermissions(void) const;
351
356 void LeaveTeam(TM_TeamMember* teamMember, NoTeamId noTeamSubcategory);
357
359 bool GetBalancingApplies(void) const;
360
362 void GetTeamMembers(DataStructures::List<TM_TeamMember*> &_teamMembers) const;
363
365 unsigned int GetTeamMembersCount(void) const;
366
369 TM_TeamMember *GetTeamMemberByIndex(unsigned int index) const;
370
372 NetworkID GetNetworkID(void) const;
373
375 TM_World* GetTM_World(void) const;
376
380 void SerializeConstruction(BitStream *constructionBitstream);
381
385 bool DeserializeConstruction(TeamManager *teamManager, BitStream *constructionBitstream);
386
388 void SetOwner(void *o);
389
391 void *GetOwner(void) const;
392
394 unsigned int GetWorldIndex(void) const;
395
397 static unsigned long ToUint32( const NetworkID &g );
398
399 protected:
400 NetworkID ID;
401 TM_World* world;
402 // Which members are on this team. The same member cannot be on the same team more than once
403 DataStructures::List<TM_TeamMember*> teamMembers;
404 // Permissions on who can join this team
405 JoinPermissions joinPermissions;
406 // Whether or not to consider this team when balancing teams
407 bool balancingApplies;
408 TeamMemberLimit teamMemberLimit;
409 void *owner;
410
411 // Remove input from list teamMembers
412 void RemoveFromTeamMemberList(TM_TeamMember *teamMember);
413
414 // Find the member index that wants to join the indicated team, is only on one team, and wants to leave that team
415 unsigned int GetMemberWithRequestedSingleTeamSwitch(TM_Team *team);
416
417
418 friend class TM_World;
419 friend class TM_TeamMember;
420 friend class TeamManager;
421 };
422
427 class TM_World
428 {
429 public:
430 TM_World();
431 virtual ~TM_World();
432
434 TeamManager *GetTeamManager(void) const;
435
438 void AddParticipant(RakNetGUID rakNetGUID);
439
443 void RemoveParticipant(RakNetGUID rakNetGUID);
444
448 void SetAutoManageConnections(bool autoAdd);
449
452 void GetParticipantList(DataStructures::List<RakNetGUID> &participantList);
453
461 void ReferenceTeam(TM_Team *team, NetworkID networkId, bool applyBalancing);
462
467 void DereferenceTeam(TM_Team *team, NoTeamId noTeamSubcategory);
468
470 unsigned int GetTeamCount(void) const;
471
474 TM_Team *GetTeamByIndex(unsigned int index) const;
475
478 TM_Team *GetTeamByNetworkID(NetworkID teamId);
479
483 unsigned int GetTeamIndex(const TM_Team *team) const;
484
491 void ReferenceTeamMember(TM_TeamMember *teamMember, NetworkID networkId);
492
496 void DereferenceTeamMember(TM_TeamMember *teamMember);
497
499 unsigned int GetTeamMemberCount(void) const;
500
503 TM_TeamMember *GetTeamMemberByIndex(unsigned int index) const;
504
507 NetworkID GetTeamMemberIDByIndex(unsigned int index) const;
508
511 TM_TeamMember *GetTeamMemberByNetworkID(NetworkID teamMemberId);
512
516 unsigned int GetTeamMemberIndex(const TM_TeamMember *teamMember) const;
517
525 bool SetBalanceTeams(bool balanceTeams, NoTeamId noTeamSubcategory);
526
528 bool GetBalanceTeams(void) const;
529
536 void SetHost(RakNetGUID _hostGuid);
537
539 RakNetGUID GetHost(void) const;
540
542 WorldId GetWorldId(void) const;
543
546 void Clear(void);
547
549 struct JoinRequestHelper
550 {
551 SLNet::Time whenRequestMade;
552 unsigned int teamMemberIndex;
553 unsigned int indexIntoTeamsRequested;
554 unsigned int requestIndex;
555 };
557 static int JoinRequestHelperComp(const TM_World::JoinRequestHelper &key, const TM_World::JoinRequestHelper &data);
558
559 protected:
560 virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
561 virtual void OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming);
562
563 // Teams with too many members have those members go to other teams.
564 void EnforceTeamBalance(NoTeamId noTeamSubcategory);
565 void KickExcessMembers(NoTeamId noTeamSubcategory);
566 void FillRequestedSlots(void);
567 unsigned int GetAvailableTeamIndexWithFewestMembers(TeamMemberLimit secondaryLimit, JoinPermissions joinPermissions);
568
569 void GetSortedJoinRequests(DataStructures::OrderedList<JoinRequestHelper, JoinRequestHelper, JoinRequestHelperComp> &joinRequests);
570
571
572 // Send a message to all participants
573 void BroadcastToParticipants(SLNet::BitStream *bsOut, RakNetGUID exclusionGuid);
574 void BroadcastToParticipants(unsigned char *data, const int length, RakNetGUID exclusionGuid);
575
576 // 1. If can join a team:
577 // A. teamMember->UpdateTeamsRequestedToNone();
578 // B. teamMember->AddToTeamList()
579 // C. Return new team
580 // 2. Else return 0
581 TM_Team* JoinAnyTeam(TM_TeamMember *teamMember, int *resultCode);
582
583 int JoinSpecificTeam(TM_TeamMember *teamMember, TM_Team *team, bool isTeamSwitch, TM_Team *teamToLeave, DataStructures::List<TM_Team*> &teamsWeAreLeaving);
584
585 TeamMemberLimit GetBalancedTeamLimit(void) const;
586
587 // For fast lookup. Shares pointers with list teams
588 DataStructures::Hash<NetworkID, TM_Team*, 256, TM_Team::ToUint32> teamsHash;
589 // For fast lookup. Shares pointers with list teamMembers
590 DataStructures::Hash<NetworkID, TM_TeamMember*, 256, TM_TeamMember::ToUint32> teamMembersHash;
591
592 TeamManager *teamManager;
593 DataStructures::List<RakNetGUID> participants;
594 DataStructures::List<TM_Team*> teams;
595 DataStructures::List<TM_TeamMember*> teamMembers;
596 bool balanceTeamsIsActive;
597 RakNetGUID hostGuid;
598 WorldId worldId;
599 bool autoAddParticipants;
600 int teamRequestIndex;
601
602 friend class TeamManager;
603 friend class TM_TeamMember;
604 friend class TM_Team;
605 };
606
626 class RAK_DLL_EXPORT TeamManager : public PluginInterface2
627 {
628 public:
629 // GetInstance() and DestroyInstance(instance*)
630 STATIC_FACTORY_DECLARATIONS(TeamManager)
631
632 TeamManager();
633 virtual ~TeamManager();
634
639 TM_World* AddWorld(WorldId worldId);
640
643 void RemoveWorld(WorldId worldId);
644
646 unsigned int GetWorldCount(void) const;
647
650 TM_World* GetWorldAtIndex(unsigned int index) const;
651
654 TM_World* GetWorldWithId(WorldId worldId) const;
655
660 void SetAutoManageConnections(bool autoAdd);
661
667 void SetTopology(TMTopology _topology);
668
672 void DecomposeTeamFull(Packet *packet,
673 TM_World **world, TM_TeamMember **teamMember, TM_Team **team,
674 uint16_t &currentMembers, uint16_t &memberLimitIncludingBalancing, bool &balancingIsActive, JoinPermissions &joinPermissions);
675
679 void DecomposeTeamLocked(Packet *packet,
680 TM_World **world, TM_TeamMember **teamMember, TM_Team **team,
681 uint16_t &currentMembers, uint16_t &memberLimitIncludingBalancing, bool &balancingIsActive, JoinPermissions &joinPermissions);
682
685 void Clear(void);
686
692 void DecodeTeamAssigned(Packet *packet, TM_World **world, TM_TeamMember **teamMember);
693
694 // \brief Reads out the world and teamMember from ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED
700 void DecodeTeamCancelled(Packet *packet, TM_World **world, TM_TeamMember **teamMember, TM_Team **teamCancelled);
701
702 protected:
703
704 virtual void Update(void);
705 virtual PluginReceiveResult OnReceive(Packet *packet);
706 virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
707 virtual void OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming);
708 void Send( const SLNet::BitStream * bitStream, const AddressOrGUID systemIdentifier, bool broadcast );
709
710 void EncodeTeamFullOrLocked(SLNet::BitStream *bitStream, TM_TeamMember *teamMember, TM_Team *team);
711 void DecomposeTeamFullOrLocked(SLNet::BitStream *bsIn, TM_World **world, TM_TeamMember **teamMember, TM_Team **team,
712 uint16_t &currentMembers, uint16_t &memberLimitIncludingBalancing, bool &balancingIsActive, JoinPermissions &joinPermissions);
713 void ProcessTeamAssigned(SLNet::BitStream *bsIn);
714
715 void EncodeTeamAssigned(SLNet::BitStream *bitStream, TM_TeamMember *teamMember);
716 void RemoveFromTeamsRequestedAndAddTeam(TM_TeamMember *teamMember, TM_Team *team, bool isTeamSwitch, TM_Team *teamToLeave);
717
718 void PushTeamAssigned(TM_TeamMember *teamMember);
719 void PushBitStream(SLNet::BitStream *bitStream);
720 void OnUpdateListsToNoTeam(Packet *packet, TM_World *world);
721 void OnUpdateTeamsRequestedToAny(Packet *packet, TM_World *world);
722 void OnJoinAnyTeam(Packet *packet, TM_World *world);
723 void OnJoinRequestedTeam(Packet *packet, TM_World *world);
724 void OnUpdateTeamsRequestedToNoneAndAddTeam(Packet *packet, TM_World *world);
725 void OnRemoveFromTeamsRequestedAndAddTeam(Packet *packet, TM_World *world);
726 void OnAddToRequestedTeams(Packet *packet, TM_World *world);
727 bool OnRemoveFromRequestedTeams(Packet *packet, TM_World *world);
728 void OnLeaveTeam(Packet *packet, TM_World *world);
729 void OnSetMemberLimit(Packet *packet, TM_World *world);
730 void OnSetJoinPermissions(Packet *packet, TM_World *world);
731 void OnSetBalanceTeams(Packet *packet, TM_World *world);
732 void OnSetBalanceTeamsInitial(Packet *packet, TM_World *world);
733
734
735 void EncodeTeamFull(SLNet::BitStream *bitStream, TM_TeamMember *teamMember, TM_Team *team);
736 void EncodeTeamLocked(SLNet::BitStream *bitStream, TM_TeamMember *teamMember, TM_Team *team);
737
741 void DecodeTeamAssigned(SLNet::BitStream *bsIn, TM_World **world, TM_TeamMember **teamMember, NoTeamId &noTeamSubcategory,
742 JoinTeamType &joinTeamType, DataStructures::List<TM_Team *> &newTeam,
743 DataStructures::List<TM_Team *> &teamsLeft, DataStructures::List<TM_Team *> &teamsJoined);
744
745 // O(1) lookup for a given world. If I need more worlds, change this to a hash or ordered list
746 TM_World *worldsArray[255];
747 // All allocated worlds for linear traversal
748 DataStructures::List<TM_World*> worldsList;
749 bool autoAddParticipants;
750 TMTopology topology;
751
752 friend class TM_TeamMember;
753 friend class TM_World;
754 friend class TM_Team;
755 };
756
757 } // namespace SLNet
758
759 #endif // __TEAM_MANAGER_H
760
761 #endif // _RAKNET_SUPPORT_*
762