SLikeNet  0.1.3
 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 
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
72 
73 // Forward declarations
74 class TM_Team;
75 class TM_TeamMember;
76 class TM_World;
77 class TeamManager;
78 
81 {
88 };
89 
92 {
93  // Each system will send all messages to all participants
95 
96  // The host will relay incoming messages to all participants
98 };
99 
104 {
105  TeamSelection();
107  TeamSelection(JoinTeamType itt, TM_Team *param);
108  TeamSelection(JoinTeamType itt, NoTeamId param);
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 
137 {
138 public:
139  // GetInstance() and DestroyInstance(instance*)
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 
263  {
265  unsigned int requestIndex;
269  };
270 
271 protected:
274  // Teams we are a member of. We can be on more than one team, but not on the same team more than once
276  // If teams is empty, which subcategory of noTeam we are on
278  // Teams we have requested to join. Mutually exclusive with teams we are already on. Cannot request the same team more than once.
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
283  // Set by StoreLastTeams()
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 
317 {
318 public:
319  // GetInstance() and DestroyInstance(instance*)
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:
402  // Which members are on this team. The same member cannot be on the same team more than once
404  // Permissions on who can join this team
406  // Whether or not to consider this team when balancing teams
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 
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 
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 
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 
550  {
552  unsigned int teamMemberIndex;
554  unsigned int requestIndex;
555  };
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 
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 
586 
587  // For fast lookup. Shares pointers with list teams
589  // For fast lookup. Shares pointers with list teamMembers
591 
601 
602  friend class TeamManager;
603  friend class TM_TeamMember;
604  friend class TM_Team;
605 };
606 
627 {
628 public:
629  // GetInstance() and DestroyInstance(instance*)
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,
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
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