TeamBalancer.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * 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. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file TeamBalancer.h
  11. /// \brief Set and network team selection (supports peer to peer or client/server)
  12. /// \details Automatically handles transmission and resolution of team selection, including team switching and balancing
  13. /// \deprecated Use TeamManager intead
  14. ///
  15. #include "NativeFeatureIncludes.h"
  16. #if _RAKNET_SUPPORT_TeamBalancer==1
  17. #ifndef __TEAM_BALANCER_H
  18. #define __TEAM_BALANCER_H
  19. #include "PluginInterface2.h"
  20. #include "RakMemoryOverride.h"
  21. #include "NativeTypes.h"
  22. #include "DS_List.h"
  23. #include "RakString.h"
  24. namespace RakNet
  25. {
  26. /// Forward declarations
  27. class RakPeerInterface;
  28. /// \defgroup TEAM_BALANCER_GROUP TeamBalancer
  29. /// \brief Set and network team selection (supports peer to peer or client/server)
  30. /// \details Automatically handles transmission and resolution of team selection, including team switching and balancing
  31. /// \deprecated Use TeamManager intead
  32. /// \ingroup PLUGINS_GROUP
  33. /// 0...254 for your team number identifiers. 255 is reserved as undefined.
  34. /// \deprecated Use TeamManager intead
  35. /// \ingroup TEAM_BALANCER_GROUP
  36. typedef unsigned char TeamId;
  37. #define UNASSIGNED_TEAM_ID 255
  38. /// \brief Set and network team selection (supports peer to peer or client/server)
  39. /// \details Automatically handles transmission and resolution of team selection, including team switching and balancing.<BR>
  40. /// Usage: TODO
  41. /// \deprecated Use TeamManager intead
  42. /// \ingroup TEAM_BALANCER_GROUP
  43. class RAK_DLL_EXPORT TeamBalancer : public PluginInterface2
  44. {
  45. public:
  46. // GetInstance() and DestroyInstance(instance*)
  47. STATIC_FACTORY_DECLARATIONS(TeamBalancer)
  48. TeamBalancer();
  49. virtual ~TeamBalancer();
  50. /// \brief Set the limit to the number of players on the specified team
  51. /// \details SetTeamSizeLimit() must be called on the host, so the host can enforce the maximum number of players on each team.
  52. /// SetTeamSizeLimit() can be called on all systems if desired - for example, in a P2P environment you may wish to call it on all systems in advanced in case you become host.
  53. /// \param[in] team Which team to set the limit for
  54. /// \param[in] limit The maximum number of people on this team
  55. void SetTeamSizeLimit(TeamId team, unsigned short limit);
  56. enum DefaultAssigmentAlgorithm
  57. {
  58. /// Among all the teams, join the team with the smallest number of players
  59. SMALLEST_TEAM,
  60. /// Join the team with the lowest index that has open slots.
  61. FILL_IN_ORDER
  62. };
  63. /// \brief Determine how players' teams will be set when they call RequestAnyTeam()
  64. /// \details Based on the specified enumeration, a player will join a team automatically
  65. /// Defaults to SMALLEST_TEAM
  66. /// This function is only used by the host
  67. /// \param[in] daa Enumeration describing the algorithm to use
  68. void SetDefaultAssignmentAlgorithm(DefaultAssigmentAlgorithm daa);
  69. /// \brief By default, teams can be unbalanced up to the team size limit defined by SetTeamSizeLimits()
  70. /// \details If SetForceEvenTeams(true) is called on the host, then teams cannot be unbalanced by more than 1 player
  71. /// If teams are uneven at the time that SetForceEvenTeams(true) is called, players at randomly will be switched, and will be notified of ID_TEAM_BALANCER_TEAM_ASSIGNED
  72. /// If players disconnect from the host such that teams would not be even, and teams are not locked, then a player from the largest team is randomly moved to even the teams.
  73. /// Defaults to false
  74. /// \note SetLockTeams(true) takes priority over SetForceEvenTeams(), so if teams are currently locked, this function will have no effect until teams become unlocked.
  75. /// \param[in] force True to force even teams. False to allow teams to not be evenly matched
  76. void SetForceEvenTeams(bool force);
  77. /// \brief If set, calls to RequestSpecificTeam() and RequestAnyTeam() will return the team you are currently on.
  78. /// \details However, if those functions are called and you do not have a team, then you will be assigned to a default team according to SetDefaultAssignmentAlgorithm() and possibly SetForceEvenTeams(true)
  79. /// If \a lock is false, and SetForceEvenTeams() was called with \a force as true, and teams are currently uneven, they will be made even, and those players randomly moved will get ID_TEAM_BALANCER_TEAM_ASSIGNED
  80. /// Defaults to false
  81. /// \param[in] lock True to lock teams, false to unlock
  82. void SetLockTeams(bool lock);
  83. /// Set your requested team. UNASSIGNED_TEAM_ID means no team.
  84. /// After enough time for network communication, ID_TEAM_BALANCER_SET_TEAM will be returned with your current team, or
  85. /// If team switch is not possible, ID_TEAM_BALANCER_REQUESTED_TEAM_CHANGE_PENDING or ID_TEAM_BALANCER_TEAMS_LOCKED will be returned.
  86. /// In the case of ID_TEAM_BALANCER_REQUESTED_TEAM_CHANGE_PENDING the request will stay in memory. ID_TEAM_BALANCER_SET_TEAM will be returned when someone on the desired team leaves or wants to switch to your team.
  87. /// If SetLockTeams(true) is called while you have a request pending, you will get ID_TEAM_BALANCER_TEAMS_LOCKED
  88. /// \pre Call SetTeamSizeLimits() on the host and call SetHostGuid() on this system. If the host is not running the TeamBalancer plugin or did not have SetTeamSizeLimits() called, then you will not get any response.
  89. /// \param[in] memberId If there is more than one player per computer, this number identifies that player. Use any consistent value, such as UNASSIGNED_NETWORK_ID if there is only one player.
  90. /// \param[in] desiredTeam An index representing your team number. The index should range from 0 to one less than the size of the list passed to SetTeamSizeLimits() on the host. You can also pass UNASSIGNED_TEAM_ID to not be on any team (such as if spectating)
  91. void RequestSpecificTeam(NetworkID memberId, TeamId desiredTeam);
  92. /// If ID_TEAM_BALANCER_REQUESTED_TEAM_CHANGE_PENDING is returned after a call to RequestSpecificTeam(), the request will stay in memory on the host and execute when available, or until the teams become locked.
  93. /// You can cancel the request by calling CancelRequestSpecificTeam(), in which case you will stay on your existing team.
  94. /// \note Due to latency, even after calling CancelRequestSpecificTeam() you may still get ID_TEAM_BALANCER_SET_TEAM if the packet was already in transmission.
  95. /// \param[in] memberId If there is more than one player per computer, this number identifies that player. Use any consistent value, such as UNASSIGNED_NETWORK_ID if there is only one player.
  96. void CancelRequestSpecificTeam(NetworkID memberId);
  97. /// Allow host to pick your team, based on whatever algorithm it uses for default team assignments.
  98. /// This only has an effect if you are not currently on a team (GetMyTeam() returns UNASSIGNED_TEAM_ID)
  99. /// \pre Call SetTeamSizeLimits() on the host and call SetHostGuid() on this system
  100. /// \param[in] memberId If there is more than one player per computer, this number identifies that player. Use any consistent value, such as UNASSIGNED_NETWORK_ID if there is only one player.
  101. void RequestAnyTeam(NetworkID memberId);
  102. /// Returns your team.
  103. /// As your team changes, you are notified through the ID_TEAM_BALANCER_TEAM_ASSIGNED packet in byte 1.
  104. /// Returns UNASSIGNED_TEAM_ID initially
  105. /// \pre For this to return anything other than UNASSIGNED_TEAM_ID, connect to a properly initialized host and RequestSpecificTeam() or RequestAnyTeam() first
  106. /// \param[in] memberId If there is more than one player per computer, this number identifies that player. Use any consistent value, such as UNASSIGNED_NETWORK_ID if there is only one player.
  107. /// \return UNASSIGNED_TEAM_ID for no team. Otherwise, the index should range from 0 to one less than the size of the list passed to SetTeamSizeLimits() on the host
  108. TeamId GetMyTeam(NetworkID memberId) const;
  109. /// If you called RequestSpecificTeam() or RequestAnyTeam() with a value for \a memberId that
  110. /// Has since been deleted, call DeleteMember(). to notify this plugin of that event.
  111. /// Not necessary with only one team member per system
  112. /// \param[in] memberId If there is more than one player per computer, this number identifies that player. Use any consistent value, such as UNASSIGNED_NETWORK_ID if there is only one player.
  113. void DeleteMember(NetworkID memberId);
  114. struct TeamMember
  115. {
  116. RakNetGUID memberGuid;
  117. NetworkID memberId;
  118. TeamId currentTeam;
  119. TeamId requestedTeam;
  120. };
  121. struct MyTeamMembers
  122. {
  123. NetworkID memberId;
  124. TeamId currentTeam;
  125. TeamId requestedTeam;
  126. };
  127. protected:
  128. /// \internal
  129. virtual PluginReceiveResult OnReceive(Packet *packet);
  130. /// \internal
  131. virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
  132. /// \internal
  133. void OnAttach(void);
  134. void OnStatusUpdateToNewHost(Packet *packet);
  135. void OnCancelTeamRequest(Packet *packet);
  136. void OnRequestAnyTeam(Packet *packet);
  137. void OnRequestSpecificTeam(Packet *packet);
  138. RakNetGUID hostGuid;
  139. DefaultAssigmentAlgorithm defaultAssigmentAlgorithm;
  140. bool forceTeamsToBeEven;
  141. bool lockTeams;
  142. // So if we lose the connection while processing, we request the same info of the new host
  143. DataStructures::List<MyTeamMembers> myTeamMembers;
  144. DataStructures::List<unsigned short> teamLimits;
  145. DataStructures::List<unsigned short> teamMemberCounts;
  146. DataStructures::List<TeamMember> teamMembers;
  147. unsigned int GetMemberIndex(NetworkID memberId, RakNetGUID guid) const;
  148. unsigned int AddTeamMember(const TeamMember &tm); // Returns index of new member
  149. void RemoveTeamMember(unsigned int index);
  150. void EvenTeams(void);
  151. unsigned int GetMemberIndexToSwitchTeams(const DataStructures::List<TeamId> &sourceTeamNumbers, TeamId targetTeamNumber);
  152. void GetOverpopulatedTeams(DataStructures::List<TeamId> &overpopulatedTeams, int maxTeamSize);
  153. void SwitchMemberTeam(unsigned int teamMemberIndex, TeamId destinationTeam);
  154. void NotifyTeamAssigment(unsigned int teamMemberIndex);
  155. bool WeAreHost(void) const;
  156. PluginReceiveResult OnTeamAssigned(Packet *packet);
  157. PluginReceiveResult OnRequestedTeamChangePending(Packet *packet);
  158. PluginReceiveResult OnTeamsLocked(Packet *packet);
  159. void GetMinMaxTeamMembers(int &minMembersOnASingleTeam, int &maxMembersOnASingleTeam);
  160. TeamId GetNextDefaultTeam(void); // Accounting for team balancing and team limits, get the team a player should be placed on
  161. bool TeamWouldBeOverpopulatedOnAddition(TeamId teamId, unsigned int teamMemberSize); // Accounting for team balancing and team limits, would this team be overpopulated if a member was added to it?
  162. bool TeamWouldBeUnderpopulatedOnLeave(TeamId teamId, unsigned int teamMemberSize);
  163. TeamId GetSmallestNonFullTeam(void) const;
  164. TeamId GetFirstNonFullTeam(void) const;
  165. void MoveMemberThatWantsToJoinTeam(TeamId teamId);
  166. TeamId MoveMemberThatWantsToJoinTeamInternal(TeamId teamId);
  167. void NotifyTeamsLocked(RakNetGUID target, TeamId requestedTeam);
  168. void NotifyTeamSwitchPending(RakNetGUID target, TeamId requestedTeam, NetworkID memberId);
  169. void NotifyNoTeam(NetworkID memberId, RakNetGUID target);
  170. void SwapTeamMembersByRequest(unsigned int memberIndex1, unsigned int memberIndex2);
  171. void RemoveByGuid(RakNetGUID rakNetGUID);
  172. bool TeamsWouldBeEvenOnSwitch(TeamId t1, TeamId t2);
  173. };
  174. } // namespace RakNet
  175. #endif
  176. #endif // _RAKNET_SUPPORT_*
粤ICP备19079148号