TeamManager.cpp 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853
  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. #include "NativeFeatureIncludes.h"
  11. #if _RAKNET_SUPPORT_TeamManager==1
  12. #include "TeamManager.h"
  13. #include "BitStream.h"
  14. #include "MessageIdentifiers.h"
  15. #include "GetTime.h"
  16. using namespace RakNet;
  17. enum TeamManagerOperations
  18. {
  19. ID_RUN_UpdateListsToNoTeam,
  20. ID_RUN_UpdateTeamsRequestedToAny,
  21. ID_RUN_JoinAnyTeam,
  22. ID_RUN_JoinRequestedTeam,
  23. ID_RUN_UpdateTeamsRequestedToNoneAndAddTeam,
  24. ID_RUN_RemoveFromTeamsRequestedAndAddTeam,
  25. ID_RUN_AddToRequestedTeams,
  26. ID_RUN_LeaveTeam,
  27. ID_RUN_SetMemberLimit,
  28. ID_RUN_SetJoinPermissions,
  29. ID_RUN_SetBalanceTeams,
  30. ID_RUN_SetBalanceTeamsInitial,
  31. ID_RUN_SerializeWorld,
  32. };
  33. STATIC_FACTORY_DEFINITIONS(TM_TeamMember,TM_TeamMember);
  34. STATIC_FACTORY_DEFINITIONS(TM_Team,TM_Team);
  35. STATIC_FACTORY_DEFINITIONS(TeamManager,TeamManager);
  36. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  37. int TM_World::JoinRequestHelperComp(const TM_World::JoinRequestHelper &key, const TM_World::JoinRequestHelper &data)
  38. {
  39. if (key.whenRequestMade < data.whenRequestMade)
  40. return -1;
  41. if (key.whenRequestMade > data.whenRequestMade)
  42. return 1;
  43. if (key.requestIndex < data.requestIndex)
  44. return -1;
  45. if (key.requestIndex > data.requestIndex)
  46. return 1;
  47. return 0;
  48. }
  49. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  50. TeamSelection::TeamSelection() {}
  51. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  52. TeamSelection::TeamSelection(JoinTeamType itt) : joinTeamType(itt) {}
  53. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  54. TeamSelection::TeamSelection(JoinTeamType itt, TM_Team *param) : joinTeamType(itt) {teamParameter.specificTeamToJoin=param;}
  55. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  56. TeamSelection::TeamSelection(JoinTeamType itt, NoTeamId param) : joinTeamType(itt) {teamParameter.noTeamSubcategory=param;}
  57. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  58. TeamSelection TeamSelection::AnyAvailable(void) {return TeamSelection(JOIN_ANY_AVAILABLE_TEAM);}
  59. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  60. TeamSelection TeamSelection::SpecificTeam(TM_Team *specificTeamToJoin) {return TeamSelection(JOIN_SPECIFIC_TEAM, specificTeamToJoin);}
  61. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  62. TeamSelection TeamSelection::NoTeam(NoTeamId noTeamSubcategory) {return TeamSelection(JOIN_NO_TEAM, noTeamSubcategory);}
  63. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  64. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  65. TM_TeamMember::TM_TeamMember()
  66. {
  67. networkId=0;
  68. world=0;
  69. joinTeamType=JOIN_NO_TEAM;
  70. noTeamSubcategory=0;
  71. }
  72. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  73. TM_TeamMember::~TM_TeamMember()
  74. {
  75. if (world)
  76. {
  77. world->DereferenceTeamMember(this);
  78. }
  79. }
  80. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  81. bool TM_TeamMember::RequestTeam(TeamSelection teamSelection)
  82. {
  83. if (teamSelection.joinTeamType==JOIN_NO_TEAM)
  84. {
  85. // If joining no team:
  86. // - If already no team, and no team category is the same, return false.
  87. // - Execute JoinNoTeam() locally. Return ID_TEAM_BALANCER_TEAM_ASSIGNED locally.
  88. // - If we are host, broadcast event. Done.
  89. // - Send to remote host event to call JoinNoTeam()
  90. // - remote Host executes JoinNoTeam() and broadcasts event. This may cause may cause rebalance if team balancing is on.
  91. // - - JoinNoTeam(): Remove from all current and requested teams. Set no-team category.
  92. if (teams.Size()==0 && noTeamSubcategory==teamSelection.teamParameter.noTeamSubcategory)
  93. {
  94. // No change
  95. return false;
  96. }
  97. BitStream bsOut;
  98. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  99. bsOut.WriteCasted<MessageID>(ID_RUN_UpdateListsToNoTeam);
  100. bsOut.Write(world->GetWorldId());
  101. bsOut.Write(networkId);
  102. bsOut.Write(teamSelection.teamParameter.noTeamSubcategory);
  103. world->BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  104. StoreLastTeams();
  105. UpdateListsToNoTeam(teamSelection.teamParameter.noTeamSubcategory);
  106. world->GetTeamManager()->PushTeamAssigned(this);
  107. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified())
  108. {
  109. world->FillRequestedSlots();
  110. world->EnforceTeamBalance(teamSelection.teamParameter.noTeamSubcategory);
  111. }
  112. }
  113. else if (teamSelection.joinTeamType==JOIN_ANY_AVAILABLE_TEAM)
  114. {
  115. // If joining any team
  116. // Execute JoinAnyTeamCheck()
  117. // - JoinAnyTeamCheck():
  118. // - - If already on a team, return false
  119. // - - If any team is already in requested teams, return false.
  120. // On local, call UpdateTeamsRequestedToAny(). Send event to also execute this to remote host
  121. // If we are host, execute JoinAnyTeam(myguid).
  122. // - JoinAnyTeam(requesterGuid): Attempt to join any team immediately. If fails, send to all except requestGuid UpdateTeamsRequestedToAny(). Else sends out new team, including to caller.
  123. // On remote host, execute JoinAnyTeamCheck(). If fails, this was because you were added to a team simultaneously on host. This is OK, just ignore the call.
  124. // Assuming JoinAnyTeamCheck() passed on remote host, call UpdateTeamsRequestedToAny() for this player. execute JoinAnyTeam(packet->guid).
  125. if (JoinAnyTeamCheck()==false)
  126. return false;
  127. UpdateTeamsRequestedToAny();
  128. // Send request to host to execute JoinAnyTeam()
  129. BitStream bsOut;
  130. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  131. bsOut.WriteCasted<MessageID>(ID_RUN_JoinAnyTeam);
  132. bsOut.Write(world->GetWorldId());
  133. bsOut.Write(networkId);
  134. world->GetTeamManager()->SendUnified(&bsOut,HIGH_PRIORITY, RELIABLE_ORDERED, 0, world->GetHost(), false);
  135. }
  136. else
  137. {
  138. RakAssert(teamSelection.joinTeamType==JOIN_SPECIFIC_TEAM);
  139. // If joining specific team
  140. // Execute JoinSpecificTeamCheck()
  141. // JoinSpecificTeamCheck():
  142. // - If already on specific team, return false
  143. // - If specific team is in requested list, return false
  144. // On local, call AddToRequestedTeams(). Send event to also execute this to remote host
  145. // If we are host, execute JoinSpecificTeam(myguid)
  146. // - JoinSpecificTeam(requesterGuid): Attempt to join specific team immediately. If fails, send to all except requesterGuid to execute AddSpecificToRequested(). Else sends out new team, including to caller.
  147. // On remote host, execute JoinSpecificTeamCheck(). If fails, just ignore.
  148. // Assuming JoinSpecificTeamCheck() passed on host, call AddSpecificToRequestedList(). Execute JoinSpecificTeam(packet->guid)
  149. if (JoinSpecificTeamCheck(teamSelection.teamParameter.specificTeamToJoin,false)==false)
  150. return false;
  151. AddToRequestedTeams(teamSelection.teamParameter.specificTeamToJoin);
  152. // Send request to host to execute JoinRequestedTeam()
  153. BitStream bsOut;
  154. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  155. bsOut.WriteCasted<MessageID>(ID_RUN_JoinRequestedTeam);
  156. bsOut.Write(world->GetWorldId());
  157. bsOut.Write(networkId);
  158. bsOut.Write(teamSelection.teamParameter.specificTeamToJoin->GetNetworkID());
  159. bsOut.Write(false);
  160. world->GetTeamManager()->SendUnified(&bsOut,HIGH_PRIORITY, RELIABLE_ORDERED, 0, world->GetHost(), false);
  161. }
  162. return true;
  163. }
  164. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  165. bool TM_TeamMember::RequestTeamSwitch(TM_Team *teamToJoin, TM_Team *teamToLeave)
  166. {
  167. if (SwitchSpecificTeamCheck(teamToJoin,teamToLeave,false)==false)
  168. return false;
  169. AddToRequestedTeams(teamToJoin, teamToLeave);
  170. // Send request to host to execute JoinRequestedTeam()
  171. BitStream bsOut;
  172. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  173. bsOut.WriteCasted<MessageID>(ID_RUN_JoinRequestedTeam);
  174. bsOut.Write(world->GetWorldId());
  175. bsOut.Write(networkId);
  176. bsOut.Write(teamToJoin->GetNetworkID());
  177. bsOut.Write(true);
  178. if (teamToLeave)
  179. {
  180. bsOut.Write(true);
  181. bsOut.Write(teamToLeave->GetNetworkID());
  182. }
  183. else
  184. {
  185. bsOut.Write(false);
  186. }
  187. world->GetTeamManager()->SendUnified(&bsOut,HIGH_PRIORITY, RELIABLE_ORDERED, 0, world->GetHost(), false);
  188. return true;
  189. }
  190. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  191. TeamSelection TM_TeamMember::GetRequestedTeam(void) const
  192. {
  193. if (teamsRequested.Size()>0)
  194. return TeamSelection::SpecificTeam(teamsRequested[0].requested);
  195. else if (joinTeamType==JOIN_NO_TEAM)
  196. return TeamSelection::NoTeam(noTeamSubcategory);
  197. else
  198. return TeamSelection::AnyAvailable();
  199. }
  200. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  201. void TM_TeamMember::GetRequestedSpecificTeams(DataStructures::List<TM_Team*> &requestedTeams) const
  202. {
  203. requestedTeams.Clear(true, _FILE_AND_LINE_);
  204. for (unsigned int i=0; i < teamsRequested.Size(); i++)
  205. requestedTeams.Push(teamsRequested[i].requested, _FILE_AND_LINE_);
  206. }
  207. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  208. bool TM_TeamMember::HasRequestedTeam(TM_Team *team) const
  209. {
  210. unsigned int i = GetRequestedTeamIndex(team);
  211. if (i==(unsigned int)-1)
  212. return false;
  213. return true;
  214. }
  215. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  216. unsigned int TM_TeamMember::GetRequestedTeamIndex(TM_Team *team) const
  217. {
  218. unsigned int i;
  219. for (i=0; i < teamsRequested.Size(); i++)
  220. {
  221. if (teamsRequested[i].requested==team)
  222. return i;
  223. }
  224. return (unsigned int) -1;
  225. }
  226. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  227. unsigned int TM_TeamMember::GetRequestedTeamCount(void) const
  228. {
  229. return teamsRequested.Size();
  230. }
  231. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  232. bool TM_TeamMember::CancelTeamRequest(TM_Team *specificTeamToCancel)
  233. {
  234. if (RemoveFromRequestedTeams(specificTeamToCancel)==false)
  235. return false;
  236. // Send request to host to execute JoinRequestedTeam()
  237. BitStream bsOut;
  238. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED);
  239. bsOut.Write(world->GetWorldId());
  240. bsOut.Write(networkId);
  241. if (specificTeamToCancel)
  242. {
  243. bsOut.Write(true);
  244. bsOut.Write(specificTeamToCancel->GetNetworkID());
  245. }
  246. else
  247. {
  248. bsOut.Write(false);
  249. }
  250. world->BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  251. world->GetTeamManager()->PushBitStream(&bsOut);
  252. return true;
  253. }
  254. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  255. bool TM_TeamMember::LeaveTeam(TM_Team* team, NoTeamId _noTeamSubcategory)
  256. {
  257. if (LeaveTeamCheck(team)==false)
  258. return false;
  259. RemoveFromSpecificTeamInternal(team);
  260. if (teams.Size()==0)
  261. {
  262. noTeamSubcategory=_noTeamSubcategory;
  263. joinTeamType=JOIN_NO_TEAM;
  264. }
  265. // Execute LeaveTeamCheck()
  266. // - LeaveTeamCheck():
  267. // - - If not on this team, return false
  268. // On local, call RemoteFromTeamsList(). Send event to also execute this to remote host
  269. // If we are host, execute OnLeaveTeamEvent(myGuid)
  270. // - OnLeaveTeamEvent(requesterGuid):
  271. // - - If rebalancing is active, rebalance
  272. // - - If someone else wants to join this team, let them.
  273. // - - Send leave team event notification to all except requesterGuid-
  274. // On remote host, execute LeaveTeamCheck(). If fails, ignore.
  275. // On remote host, execute RemoteFromTeamsList() followed by OnLeaveTeamEvent(packet->guid)
  276. // Pattern:
  277. // Execute local check, if fails return false
  278. // Locally execute non-host guaranteed changes
  279. // If local system is also host, execute host changes. Relay to all but local
  280. // On remote host, execute check. If check passes, execute non-host changes, followed by host changes. Relay to all but sender.
  281. BitStream bsOut;
  282. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  283. bsOut.WriteCasted<MessageID>(ID_RUN_LeaveTeam);
  284. bsOut.Write(world->GetWorldId());
  285. bsOut.Write(networkId);
  286. bsOut.Write(team->GetNetworkID());
  287. bsOut.Write(noTeamSubcategory);
  288. world->BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  289. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified())
  290. {
  291. // Rebalance teams
  292. world->FillRequestedSlots();
  293. world->EnforceTeamBalance(noTeamSubcategory);
  294. }
  295. return true;
  296. }
  297. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  298. bool TM_TeamMember::LeaveAllTeams(NoTeamId noTeamSubcategory)
  299. {
  300. return RequestTeam(TeamSelection::NoTeam(noTeamSubcategory));
  301. }
  302. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  303. TM_Team* TM_TeamMember::GetCurrentTeam(void) const
  304. {
  305. if (teams.Size()>0)
  306. return teams[0];
  307. return 0;
  308. }
  309. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  310. unsigned int TM_TeamMember::GetCurrentTeamCount(void) const
  311. {
  312. return teams.Size();
  313. }
  314. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  315. TM_Team* TM_TeamMember::GetCurrentTeamByIndex(unsigned int index)
  316. {
  317. return teams[index];
  318. }
  319. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  320. void TM_TeamMember::GetCurrentTeams(DataStructures::List<TM_Team*> &_teams) const
  321. {
  322. _teams=teams;
  323. }
  324. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  325. void TM_TeamMember::GetLastTeams(DataStructures::List<TM_Team*> &_teams) const
  326. {
  327. _teams=lastTeams;
  328. }
  329. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  330. bool TM_TeamMember::IsOnTeam(TM_Team *team) const
  331. {
  332. unsigned int i;
  333. for (i=0; i < teams.Size(); i++)
  334. {
  335. if (teams[i]==team)
  336. return true;
  337. }
  338. return false;
  339. }
  340. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  341. NetworkID TM_TeamMember::GetNetworkID(void) const
  342. {
  343. return networkId;
  344. }
  345. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  346. TM_World* TM_TeamMember::GetTM_World(void) const
  347. {
  348. return world;
  349. }
  350. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  351. void TM_TeamMember::SerializeConstruction(BitStream *constructionBitstream)
  352. {
  353. // Write requested teams
  354. constructionBitstream->Write(world->GetWorldId());
  355. constructionBitstream->Write(networkId);
  356. constructionBitstream->WriteCasted<uint16_t>(teamsRequested.Size());
  357. for (unsigned int i=0; i < teamsRequested.Size(); i++)
  358. {
  359. constructionBitstream->Write(teamsRequested[i].isTeamSwitch);
  360. if (teamsRequested[i].teamToLeave)
  361. {
  362. constructionBitstream->Write(true);
  363. constructionBitstream->Write(teamsRequested[i].teamToLeave->GetNetworkID());
  364. }
  365. else
  366. {
  367. constructionBitstream->Write(false);
  368. }
  369. if (teamsRequested[i].requested)
  370. {
  371. constructionBitstream->Write(true);
  372. constructionBitstream->Write(teamsRequested[i].requested->GetNetworkID());
  373. }
  374. else
  375. {
  376. constructionBitstream->Write(false);
  377. }
  378. }
  379. world->teamManager->EncodeTeamAssigned(constructionBitstream, this);
  380. }
  381. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  382. bool TM_TeamMember::DeserializeConstruction(TeamManager *teamManager, BitStream *constructionBitstream)
  383. {
  384. // Read requested teams
  385. bool success;
  386. uint16_t teamsRequestedSize;
  387. WorldId worldId;
  388. constructionBitstream->Read(worldId);
  389. TM_World *world = teamManager->GetWorldWithId(worldId);
  390. RakAssert(world);
  391. constructionBitstream->Read(networkId);
  392. world->ReferenceTeamMember(this,networkId);
  393. success=constructionBitstream->Read(teamsRequestedSize);
  394. for (unsigned int i=0; i < teamsRequestedSize; i++)
  395. {
  396. RequestedTeam rt;
  397. rt.isTeamSwitch=false;
  398. rt.requested=0;
  399. rt.whenRequested=0;
  400. constructionBitstream->Read(rt.isTeamSwitch);
  401. bool hasTeamToLeave=false;
  402. constructionBitstream->Read(hasTeamToLeave);
  403. NetworkID teamToLeaveId;
  404. if (hasTeamToLeave)
  405. {
  406. constructionBitstream->Read(teamToLeaveId);
  407. rt.teamToLeave = world->GetTeamByNetworkID(teamToLeaveId);
  408. RakAssert(rt.teamToLeave);
  409. }
  410. else
  411. rt.teamToLeave=0;
  412. bool hasTeamRequested=false;
  413. success=constructionBitstream->Read(hasTeamRequested);
  414. NetworkID teamRequestedId;
  415. if (hasTeamRequested)
  416. {
  417. success=constructionBitstream->Read(teamRequestedId);
  418. rt.requested = world->GetTeamByNetworkID(teamRequestedId);
  419. RakAssert(rt.requested);
  420. }
  421. rt.whenRequested=RakNet::GetTime();
  422. rt.requestIndex=world->teamRequestIndex++; // In case whenRequested is the same between two teams when sorting team requests
  423. if (
  424. (hasTeamToLeave==false || (hasTeamToLeave==true && rt.teamToLeave!=0)) &&
  425. (hasTeamRequested==false || (hasTeamRequested==true && rt.requested!=0))
  426. )
  427. {
  428. teamsRequested.Push(rt, _FILE_AND_LINE_);
  429. }
  430. }
  431. if (success)
  432. world->teamManager->ProcessTeamAssigned(constructionBitstream);
  433. return success;
  434. }
  435. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  436. void *TM_TeamMember::GetOwner(void) const
  437. {
  438. return owner;
  439. }
  440. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  441. void TM_TeamMember::SetOwner(void *o)
  442. {
  443. owner=o;
  444. }
  445. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  446. NoTeamId TM_TeamMember::GetNoTeamId(void) const
  447. {
  448. return noTeamSubcategory;
  449. }
  450. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  451. unsigned int TM_TeamMember::GetWorldIndex(void) const
  452. {
  453. return world->GetTeamMemberIndex(this);
  454. }
  455. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  456. unsigned long TM_TeamMember::ToUint32( const NetworkID &g )
  457. {
  458. return g & 0xFFFFFFFF;
  459. }
  460. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  461. void TM_TeamMember::UpdateListsToNoTeam(NoTeamId nti)
  462. {
  463. teamsRequested.Clear(true, _FILE_AND_LINE_ );
  464. for (unsigned int i=0; i < teams.Size(); i++)
  465. {
  466. teams[i]->RemoveFromTeamMemberList(this);
  467. }
  468. teams.Clear(true, _FILE_AND_LINE_ );
  469. noTeamSubcategory=nti;
  470. joinTeamType=JOIN_NO_TEAM;
  471. }
  472. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  473. bool TM_TeamMember::JoinAnyTeamCheck(void) const
  474. {
  475. // - - If already on a team, return false
  476. if (teams.Size() > 0)
  477. return false;
  478. // - - If any team is already in requested teams, return false.
  479. if (teamsRequested.Size()==0 && joinTeamType==JOIN_ANY_AVAILABLE_TEAM)
  480. return false;
  481. return true;
  482. }
  483. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  484. bool TM_TeamMember::JoinSpecificTeamCheck(TM_Team *specificTeamToJoin, bool ignoreRequested) const
  485. {
  486. // - If already on specific team, return false
  487. if (IsOnTeam(specificTeamToJoin))
  488. return false;
  489. if (ignoreRequested)
  490. return true;
  491. unsigned int i;
  492. for (i=0; i < teamsRequested.Size(); i++)
  493. {
  494. if (teamsRequested[i].requested==specificTeamToJoin)
  495. {
  496. if (teamsRequested[i].isTeamSwitch==true)
  497. return true; // Turn off team switch
  498. // Same thing
  499. return false;
  500. }
  501. }
  502. // Not in teams requested
  503. return true;
  504. }
  505. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  506. bool TM_TeamMember::SwitchSpecificTeamCheck(TM_Team *teamToJoin, TM_Team *teamToLeave, bool ignoreRequested) const
  507. {
  508. RakAssert(teamToJoin!=0);
  509. // - If already on specific team, return false
  510. if (IsOnTeam(teamToJoin))
  511. return false;
  512. if (teamToLeave!=0 && IsOnTeam(teamToLeave)==false)
  513. return false;
  514. if (teamToJoin==teamToLeave)
  515. return false;
  516. if (ignoreRequested)
  517. return true;
  518. unsigned int i;
  519. for (i=0; i < teamsRequested.Size(); i++)
  520. {
  521. if (teamsRequested[i].requested==teamToJoin)
  522. {
  523. if (teamsRequested[i].isTeamSwitch==false)
  524. return true; // Different - leave team was off, turn on
  525. if (teamsRequested[i].teamToLeave==teamToLeave)
  526. return false; // Same thing - leave all or a specific team
  527. // Change leave team
  528. return true;
  529. }
  530. }
  531. // Not in teams requested
  532. return true;
  533. }
  534. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  535. bool TM_TeamMember::LeaveTeamCheck(TM_Team *team) const
  536. {
  537. if (IsOnTeam(team)==false)
  538. return false;
  539. return true;
  540. }
  541. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  542. void TM_TeamMember::UpdateTeamsRequestedToAny(void)
  543. {
  544. teamsRequested.Clear(true, _FILE_AND_LINE_);
  545. joinTeamType=JOIN_ANY_AVAILABLE_TEAM;
  546. whenJoinAnyRequested=RakNet::GetTime();
  547. joinAnyRequestIndex=world->teamRequestIndex++; // In case whenRequested is the same between two teams when sorting team requests
  548. }
  549. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  550. void TM_TeamMember::UpdateTeamsRequestedToNone(void)
  551. {
  552. teamsRequested.Clear(true, _FILE_AND_LINE_);
  553. joinTeamType=JOIN_NO_TEAM;
  554. }
  555. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  556. void TM_TeamMember::AddToRequestedTeams(TM_Team *teamToJoin)
  557. {
  558. RemoveFromRequestedTeams(teamToJoin);
  559. RequestedTeam rt;
  560. rt.isTeamSwitch=false;
  561. rt.requested=teamToJoin;
  562. rt.teamToLeave=0;
  563. rt.whenRequested=RakNet::GetTime();
  564. rt.requestIndex=world->teamRequestIndex++; // In case whenRequested is the same between two teams when sorting team requests
  565. teamsRequested.Push(rt, _FILE_AND_LINE_ );
  566. }
  567. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  568. void TM_TeamMember::AddToRequestedTeams(TM_Team *teamToJoin, TM_Team *teamToLeave)
  569. {
  570. RemoveFromRequestedTeams(teamToJoin);
  571. RequestedTeam rt;
  572. rt.isTeamSwitch=true;
  573. rt.requested=teamToJoin;
  574. rt.teamToLeave=teamToLeave;
  575. rt.whenRequested=RakNet::GetTime();
  576. rt.requestIndex=world->teamRequestIndex++; // In case whenRequested is the same between two teams when sorting team requests
  577. teamsRequested.Push(rt, _FILE_AND_LINE_ );
  578. }
  579. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  580. bool TM_TeamMember::RemoveFromRequestedTeams(TM_Team *team)
  581. {
  582. if (team==0)
  583. {
  584. teamsRequested.Clear(true, _FILE_AND_LINE_);
  585. joinTeamType=JOIN_NO_TEAM;
  586. return true;
  587. }
  588. else
  589. {
  590. unsigned int i;
  591. for (i=0; i < teamsRequested.Size(); i++)
  592. {
  593. if (teamsRequested[i].requested==team)
  594. {
  595. teamsRequested.RemoveAtIndex(i);
  596. if (teamsRequested.Size()==0)
  597. {
  598. joinTeamType=JOIN_NO_TEAM;
  599. }
  600. return true;
  601. }
  602. }
  603. }
  604. return false;
  605. }
  606. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  607. void TM_TeamMember::AddToTeamList(TM_Team *team)
  608. {
  609. team->teamMembers.Push(this, _FILE_AND_LINE_ );
  610. teams.Push(team, _FILE_AND_LINE_ );
  611. }
  612. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  613. void TM_TeamMember::RemoveFromSpecificTeamInternal(TM_Team *team)
  614. {
  615. unsigned int i,j;
  616. for (i=0; i < teams.Size(); i++)
  617. {
  618. if (teams[i]==team)
  619. {
  620. for (j=0; j < team->teamMembers.Size(); j++)
  621. {
  622. if (team->teamMembers[j]==this)
  623. {
  624. team->teamMembers.RemoveAtIndex(j);
  625. break;
  626. }
  627. }
  628. teams.RemoveAtIndex(i);
  629. break;
  630. }
  631. }
  632. }
  633. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  634. void TM_TeamMember::RemoveFromAllTeamsInternal(void)
  635. {
  636. TM_Team *team;
  637. unsigned int i,j;
  638. for (i=0; i < teams.Size(); i++)
  639. {
  640. team = teams[i];
  641. for (j=0; j < team->teamMembers.Size(); j++)
  642. {
  643. if (team->teamMembers[j]==this)
  644. {
  645. team->teamMembers.RemoveAtIndex(j);
  646. break;
  647. }
  648. }
  649. }
  650. teams.Clear(true, _FILE_AND_LINE_);
  651. }
  652. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  653. void TM_TeamMember::StoreLastTeams(void)
  654. {
  655. lastTeams=teams;
  656. }
  657. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  658. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  659. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  660. TM_Team::TM_Team()
  661. {
  662. ID=0;
  663. world=0;
  664. joinPermissions=ALLOW_JOIN_ANY_AVAILABLE_TEAM|ALLOW_JOIN_SPECIFIC_TEAM|ALLOW_JOIN_REBALANCING;
  665. balancingApplies=true;
  666. teamMemberLimit=65535;
  667. owner=0;
  668. }
  669. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  670. TM_Team::~TM_Team()
  671. {
  672. if (world)
  673. world->DereferenceTeam(this, 0);
  674. }
  675. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  676. bool TM_Team::SetMemberLimit(TeamMemberLimit _teamMemberLimit, NoTeamId noTeamId)
  677. {
  678. if (teamMemberLimit==_teamMemberLimit)
  679. return false;
  680. teamMemberLimit=_teamMemberLimit;
  681. // Network this as request to host
  682. BitStream bsOut;
  683. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  684. bsOut.WriteCasted<MessageID>(ID_RUN_SetMemberLimit);
  685. bsOut.Write(world->GetWorldId());
  686. bsOut.Write(GetNetworkID());
  687. bsOut.Write(teamMemberLimit);
  688. bsOut.Write(noTeamId);
  689. world->GetTeamManager()->Send(&bsOut, world->GetHost(), false);
  690. return true;
  691. }
  692. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  693. TeamMemberLimit TM_Team::GetMemberLimit(void) const
  694. {
  695. if (world->GetBalanceTeams()==false)
  696. {
  697. return teamMemberLimit;
  698. }
  699. else
  700. {
  701. TeamMemberLimit limitWithBalancing=world->GetBalancedTeamLimit();
  702. if (limitWithBalancing < teamMemberLimit)
  703. return limitWithBalancing;
  704. return teamMemberLimit;
  705. }
  706. }
  707. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  708. TeamMemberLimit TM_Team::GetMemberLimitSetting(void) const
  709. {
  710. return teamMemberLimit;
  711. }
  712. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  713. bool TM_Team::SetJoinPermissions(JoinPermissions _joinPermissions)
  714. {
  715. if (joinPermissions==_joinPermissions)
  716. return false;
  717. joinPermissions=_joinPermissions;
  718. // Network this as request to host
  719. BitStream bsOut;
  720. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  721. bsOut.WriteCasted<MessageID>(ID_RUN_SetJoinPermissions);
  722. bsOut.Write(world->GetWorldId());
  723. bsOut.Write(GetNetworkID());
  724. bsOut.Write(_joinPermissions);
  725. world->GetTeamManager()->Send(&bsOut,world->GetHost(), false);
  726. return true;
  727. }
  728. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  729. JoinPermissions TM_Team::GetJoinPermissions(void) const
  730. {
  731. return joinPermissions;
  732. }
  733. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  734. void TM_Team::LeaveTeam(TM_TeamMember* teamMember, NoTeamId noTeamSubcategory)
  735. {
  736. teamMember->LeaveTeam(this, noTeamSubcategory);
  737. }
  738. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  739. bool TM_Team::GetBalancingApplies(void) const
  740. {
  741. return balancingApplies;
  742. }
  743. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  744. void TM_Team::GetTeamMembers(DataStructures::List<TM_TeamMember*> &_teamMembers) const
  745. {
  746. _teamMembers=teamMembers;
  747. }
  748. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  749. unsigned int TM_Team::GetTeamMembersCount(void) const
  750. {
  751. return teamMembers.Size();
  752. }
  753. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  754. TM_TeamMember *TM_Team::GetTeamMemberByIndex(unsigned int index) const
  755. {
  756. return teamMembers[index];
  757. }
  758. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  759. NetworkID TM_Team::GetNetworkID(void) const
  760. {
  761. return ID;
  762. }
  763. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  764. TM_World* TM_Team::GetTM_World(void) const
  765. {
  766. return world;
  767. }
  768. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  769. void TM_Team::SerializeConstruction(BitStream *constructionBitstream)
  770. {
  771. // Do not need to serialize member lists, the team members do this
  772. constructionBitstream->Write(world->GetWorldId());
  773. constructionBitstream->Write(ID);
  774. constructionBitstream->Write(joinPermissions);
  775. constructionBitstream->Write(balancingApplies);
  776. constructionBitstream->Write(teamMemberLimit);
  777. }
  778. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  779. bool TM_Team::DeserializeConstruction(TeamManager *teamManager, BitStream *constructionBitstream)
  780. {
  781. WorldId worldId;
  782. constructionBitstream->Read(worldId);
  783. TM_World *world = teamManager->GetWorldWithId(worldId);
  784. RakAssert(world);
  785. constructionBitstream->Read(ID);
  786. constructionBitstream->Read(joinPermissions);
  787. constructionBitstream->Read(balancingApplies);
  788. bool b = constructionBitstream->Read(teamMemberLimit);
  789. RakAssert(b);
  790. if (b)
  791. {
  792. world->ReferenceTeam(this,ID,balancingApplies);
  793. }
  794. return b;
  795. }
  796. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  797. unsigned long TM_Team::ToUint32( const NetworkID &g )
  798. {
  799. return g & 0xFFFFFFFF;
  800. }
  801. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  802. void *TM_Team::GetOwner(void) const
  803. {
  804. return owner;
  805. }
  806. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  807. unsigned int TM_Team::GetWorldIndex(void) const
  808. {
  809. return world->GetTeamIndex(this);
  810. }
  811. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  812. void TM_Team::SetOwner(void *o)
  813. {
  814. owner=o;
  815. }
  816. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  817. void TM_Team::RemoveFromTeamMemberList(TM_TeamMember *teamMember)
  818. {
  819. unsigned int index = teamMembers.GetIndexOf(teamMember);
  820. RakAssert(index != (unsigned int) -1);
  821. teamMembers.RemoveAtIndex(index);
  822. }
  823. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  824. unsigned int TM_Team::GetMemberWithRequestedSingleTeamSwitch(TM_Team *team)
  825. {
  826. unsigned int i;
  827. for (i=0; i < teamMembers.Size(); i++)
  828. {
  829. if (teamMembers[i]->GetCurrentTeamCount()==1)
  830. {
  831. unsigned int j = teamMembers[i]->GetRequestedTeamIndex(team);
  832. if (j!=(unsigned int)-1)
  833. {
  834. if (teamMembers[i]->teamsRequested[j].isTeamSwitch &&
  835. (teamMembers[i]->teamsRequested[j].teamToLeave==0 ||
  836. teamMembers[i]->teamsRequested[j].teamToLeave==teamMembers[i]->teams[0])
  837. )
  838. return i;
  839. }
  840. }
  841. }
  842. return (unsigned int) -1;
  843. }
  844. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  845. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  846. TM_World::TM_World()
  847. {
  848. teamManager=0;
  849. balanceTeamsIsActive=false;
  850. hostGuid=UNASSIGNED_RAKNET_GUID;
  851. worldId=0;
  852. autoAddParticipants=true;
  853. teamRequestIndex=0;
  854. }
  855. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  856. TM_World::~TM_World()
  857. {
  858. Clear();
  859. }
  860. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  861. TeamManager *TM_World::GetTeamManager(void) const
  862. {
  863. return teamManager;
  864. }
  865. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  866. void TM_World::AddParticipant(RakNetGUID rakNetGUID)
  867. {
  868. participants.Push(rakNetGUID, _FILE_AND_LINE_ );
  869. // Send to remote system status of balanceTeamsIsActive
  870. if (GetTeamManager()->GetMyGUIDUnified()==GetHost())
  871. {
  872. // Actually just transmitting initial value of balanceTeamsIsActive
  873. BitStream bsOut;
  874. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  875. bsOut.WriteCasted<MessageID>(ID_RUN_SetBalanceTeamsInitial);
  876. bsOut.Write(GetWorldId());
  877. bsOut.Write(balanceTeamsIsActive);
  878. teamManager->SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0,rakNetGUID, false);
  879. }
  880. }
  881. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  882. void TM_World::RemoveParticipant(RakNetGUID rakNetGUID)
  883. {
  884. unsigned int i;
  885. i = participants.GetIndexOf(rakNetGUID);
  886. if (i!=(unsigned int)-1)
  887. participants.RemoveAtIndex(i);
  888. }
  889. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  890. void TM_World::SetAutoManageConnections(bool autoAdd)
  891. {
  892. autoAddParticipants=autoAdd;
  893. }
  894. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  895. void TM_World::GetParticipantList(DataStructures::List<RakNetGUID> &participantList)
  896. {
  897. participantList = participants;
  898. }
  899. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  900. void TM_World::ReferenceTeam(TM_Team *team, NetworkID networkId, bool applyBalancing)
  901. {
  902. unsigned int i;
  903. for (i=0; i < teams.Size(); i++)
  904. {
  905. if (teams[i]==team)
  906. return;
  907. }
  908. team->ID=networkId;
  909. team->balancingApplies=applyBalancing;
  910. team->world=this;
  911. // Add this team to the list of teams
  912. teams.Push(team, _FILE_AND_LINE_);
  913. teamsHash.Push(networkId,team,_FILE_AND_LINE_);
  914. // If autobalancing is on, and the team lock state supports it, then call EnforceTeamBalancing()
  915. if (applyBalancing && balanceTeamsIsActive)
  916. {
  917. EnforceTeamBalance(0);
  918. }
  919. }
  920. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  921. void TM_World::DereferenceTeam(TM_Team *team, NoTeamId noTeamSubcategory)
  922. {
  923. unsigned int i;
  924. for (i=0; i < teams.Size(); i++)
  925. {
  926. if (teams[i]==team)
  927. {
  928. TM_Team *team = teams[i];
  929. while (team->teamMembers.Size())
  930. {
  931. team->teamMembers[team->teamMembers.Size()-1]->LeaveTeam(team, noTeamSubcategory);
  932. }
  933. teams.RemoveAtIndex(i);
  934. teamsHash.Remove(team->GetNetworkID(),_FILE_AND_LINE_);
  935. break;
  936. }
  937. }
  938. }
  939. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  940. unsigned int TM_World::GetTeamCount(void) const
  941. {
  942. return teams.Size();
  943. }
  944. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  945. TM_Team *TM_World::GetTeamByIndex(unsigned int index) const
  946. {
  947. return teams[index];
  948. }
  949. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  950. TM_Team *TM_World::GetTeamByNetworkID(NetworkID teamId)
  951. {
  952. DataStructures::HashIndex hi = teamsHash.GetIndexOf(teamId);
  953. if (hi.IsInvalid())
  954. return 0;
  955. return teamsHash.ItemAtIndex(hi);
  956. }
  957. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  958. unsigned int TM_World::GetTeamIndex(const TM_Team *team) const
  959. {
  960. unsigned int i;
  961. for (i=0; i < teams.Size(); i++)
  962. {
  963. if (teams[i]==team)
  964. return i;
  965. }
  966. return (unsigned int) -1;
  967. }
  968. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  969. void TM_World::ReferenceTeamMember(TM_TeamMember *teamMember, NetworkID networkId)
  970. {
  971. unsigned int i;
  972. for (i=0; i < teamMembers.Size(); i++)
  973. {
  974. if (teamMembers[i]==teamMember)
  975. return;
  976. }
  977. teamMember->world=this;
  978. teamMember->networkId=networkId;
  979. teamMembers.Push(teamMember, _FILE_AND_LINE_);
  980. teamMembersHash.Push(networkId,teamMember,_FILE_AND_LINE_);
  981. }
  982. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  983. void TM_World::DereferenceTeamMember(TM_TeamMember *teamMember)
  984. {
  985. unsigned int i;
  986. for (i=0; i < teamMembers.Size(); i++)
  987. {
  988. if (teamMembers[i]==teamMember)
  989. {
  990. teamMembers[i]->UpdateListsToNoTeam(0);
  991. teamMembersHash.Remove(teamMembers[i]->GetNetworkID(),_FILE_AND_LINE_);
  992. teamMembers.RemoveAtIndex(i);
  993. break;
  994. }
  995. }
  996. }
  997. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  998. unsigned int TM_World::GetTeamMemberCount(void) const
  999. {
  1000. return teamMembers.Size();
  1001. }
  1002. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1003. TM_TeamMember *TM_World::GetTeamMemberByIndex(unsigned int index) const
  1004. {
  1005. return teamMembers[index];
  1006. }
  1007. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1008. NetworkID TM_World::GetTeamMemberIDByIndex(unsigned int index) const
  1009. {
  1010. return teamMembers[index]->GetNetworkID();
  1011. }
  1012. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1013. TM_TeamMember *TM_World::GetTeamMemberByNetworkID(NetworkID teamMemberId)
  1014. {
  1015. DataStructures::HashIndex hi = teamMembersHash.GetIndexOf(teamMemberId);
  1016. if (hi.IsInvalid())
  1017. return 0;
  1018. return teamMembersHash.ItemAtIndex(hi);
  1019. }
  1020. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1021. unsigned int TM_World::GetTeamMemberIndex(const TM_TeamMember *teamMember) const
  1022. {
  1023. unsigned int i;
  1024. for (i=0; i < teamMembers.Size(); i++)
  1025. {
  1026. if (teamMembers[i]==teamMember)
  1027. return i;
  1028. }
  1029. return (unsigned int) -1;
  1030. }
  1031. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1032. bool TM_World::SetBalanceTeams(bool balanceTeams, NoTeamId noTeamId)
  1033. {
  1034. if (balanceTeams==balanceTeamsIsActive)
  1035. return false;
  1036. balanceTeamsIsActive=balanceTeams;
  1037. // Network this as request to host
  1038. BitStream bsOut;
  1039. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  1040. bsOut.WriteCasted<MessageID>(ID_RUN_SetBalanceTeams);
  1041. bsOut.Write(GetWorldId());
  1042. bsOut.Write(balanceTeams);
  1043. bsOut.Write(noTeamId);
  1044. GetTeamManager()->SendUnified(&bsOut,HIGH_PRIORITY, RELIABLE_ORDERED, 0, GetHost(), false);
  1045. return true;
  1046. }
  1047. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1048. bool TM_World::GetBalanceTeams(void) const
  1049. {
  1050. return balanceTeamsIsActive;
  1051. }
  1052. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1053. void TM_World::SetHost(RakNetGUID _hostGuid)
  1054. {
  1055. if (hostGuid==_hostGuid)
  1056. return;
  1057. RakAssert(_hostGuid!=UNASSIGNED_RAKNET_GUID);
  1058. hostGuid=_hostGuid;
  1059. if (GetHost()==GetTeamManager()->GetMyGUIDUnified())
  1060. FillRequestedSlots();
  1061. }
  1062. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1063. RakNetGUID TM_World::GetHost(void) const
  1064. {
  1065. return hostGuid;
  1066. }
  1067. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1068. WorldId TM_World::GetWorldId(void) const
  1069. {
  1070. return worldId;
  1071. }
  1072. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1073. void TM_World::Clear(void)
  1074. {
  1075. for (unsigned int i=0; i < teams.Size(); i++)
  1076. {
  1077. teams[i]->world=0;
  1078. }
  1079. for (unsigned int i=0; i < teamMembers.Size(); i++)
  1080. {
  1081. teamMembers[i]->world=0;
  1082. }
  1083. participants.Clear(true, _FILE_AND_LINE_);
  1084. teams.Clear(true, _FILE_AND_LINE_);
  1085. teamMembers.Clear(true, _FILE_AND_LINE_);
  1086. }
  1087. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1088. void TM_World::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
  1089. {
  1090. (void) lostConnectionReason;
  1091. (void) systemAddress;
  1092. RemoveParticipant(rakNetGUID);
  1093. }
  1094. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1095. void TM_World::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
  1096. {
  1097. (void) isIncoming;
  1098. (void) systemAddress;
  1099. if (autoAddParticipants)
  1100. AddParticipant(rakNetGUID);
  1101. }
  1102. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1103. void TM_World::EnforceTeamBalance(NoTeamId noTeamId)
  1104. {
  1105. // Host only function
  1106. RakAssert(GetHost()==GetTeamManager()->GetMyGUIDUnified());
  1107. KickExcessMembers(noTeamId);
  1108. }
  1109. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1110. void TM_World::KickExcessMembers(NoTeamId noTeamId)
  1111. {
  1112. // Host only function
  1113. RakAssert(GetHost()==GetTeamManager()->GetMyGUIDUnified());
  1114. // For each team that applies balancing, if the team is overfull, put on a team that is not overfull if the team has ALLOW_JOIN_REBALANCING set
  1115. // If cannot move the player to another team, just take the player off the team and set to noTeamId if they have no team at that point
  1116. TeamMemberLimit balancedTeamLimit;
  1117. if (balanceTeamsIsActive)
  1118. balancedTeamLimit = GetBalancedTeamLimit();
  1119. else
  1120. balancedTeamLimit = (TeamMemberLimit) -1;
  1121. TM_Team *team, *teamToJoin;
  1122. unsigned int i, teamIndex;
  1123. for (i=0; i < teams.Size(); i++)
  1124. {
  1125. team = teams[i];
  1126. while (team->GetMemberLimitSetting() < team->GetTeamMembersCount() ||
  1127. (balancedTeamLimit < team->GetTeamMembersCount() && team->GetBalancingApplies()) )
  1128. {
  1129. TM_TeamMember *teamMember = team->teamMembers[team->teamMembers.Size()-1];
  1130. teamIndex = GetAvailableTeamIndexWithFewestMembers(balancedTeamLimit, ALLOW_JOIN_REBALANCING);
  1131. if (teamIndex == (unsigned int)-1)
  1132. {
  1133. // Move this member to no team
  1134. teamMember->LeaveTeam(team, noTeamId);
  1135. teamManager->PushTeamAssigned(teamMember);
  1136. }
  1137. else
  1138. {
  1139. teamToJoin = teams[teamIndex];
  1140. // Move this member
  1141. teamMember->StoreLastTeams();
  1142. teamManager->RemoveFromTeamsRequestedAndAddTeam(teamMember, teamToJoin, true, team);
  1143. BitStream bsOut;
  1144. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  1145. bsOut.WriteCasted<MessageID>(ID_RUN_RemoveFromTeamsRequestedAndAddTeam);
  1146. bsOut.Write(GetWorldId());
  1147. bsOut.Write(teamMember->GetNetworkID());
  1148. bsOut.Write(teamToJoin->GetNetworkID());
  1149. bsOut.Write(true);
  1150. bsOut.Write(true);
  1151. bsOut.Write(team->GetNetworkID());
  1152. BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  1153. }
  1154. }
  1155. }
  1156. }
  1157. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1158. void TM_World::FillRequestedSlots(void)
  1159. {
  1160. // Host only function
  1161. RakAssert(GetHost()==GetTeamManager()->GetMyGUIDUnified());
  1162. TeamMemberLimit balancedTeamLimit;
  1163. if (balanceTeamsIsActive)
  1164. balancedTeamLimit = GetBalancedTeamLimit();
  1165. else
  1166. balancedTeamLimit = (TeamMemberLimit) -1;
  1167. unsigned int teamIndex, indexIntoTeamsRequested = (unsigned int)-1;
  1168. TM_Team *team;
  1169. TM_TeamMember *teamMember;
  1170. DataStructures::OrderedList<TM_World::JoinRequestHelper, TM_World::JoinRequestHelper, JoinRequestHelperComp> joinRequests;
  1171. GetSortedJoinRequests(joinRequests);
  1172. unsigned int joinRequestIndex;
  1173. for (joinRequestIndex=0; joinRequestIndex < joinRequests.Size(); joinRequestIndex++)
  1174. {
  1175. teamMember = teamMembers[joinRequests[joinRequestIndex].teamMemberIndex];
  1176. if (teamMember->teamsRequested.Size()==0)
  1177. {
  1178. if (teamMember->joinTeamType==JOIN_ANY_AVAILABLE_TEAM)
  1179. teamIndex = GetAvailableTeamIndexWithFewestMembers(balancedTeamLimit, ALLOW_JOIN_ANY_AVAILABLE_TEAM);
  1180. else
  1181. teamIndex=(unsigned int)-1;
  1182. }
  1183. else
  1184. {
  1185. indexIntoTeamsRequested = joinRequests[joinRequestIndex].indexIntoTeamsRequested;
  1186. team = teamMember->teamsRequested[indexIntoTeamsRequested].requested;
  1187. if (team->GetTeamMembersCount() < balancedTeamLimit &&
  1188. team->GetTeamMembersCount() < team->GetMemberLimitSetting() &&
  1189. (ALLOW_JOIN_SPECIFIC_TEAM & team->GetJoinPermissions())!=0)
  1190. {
  1191. teamIndex=teams.GetIndexOf(team);
  1192. }
  1193. else
  1194. {
  1195. teamIndex=(unsigned int)-1;
  1196. }
  1197. }
  1198. if (teamIndex != (unsigned int)-1)
  1199. {
  1200. team = teams[teamIndex];
  1201. if (teamMember->teamsRequested.Size()==0)
  1202. {
  1203. if (teamMember->joinTeamType==JOIN_ANY_AVAILABLE_TEAM)
  1204. {
  1205. // Join any
  1206. teamMember->StoreLastTeams();
  1207. teamMember->UpdateTeamsRequestedToNone();
  1208. teamMember->AddToTeamList(teams[teamIndex]);
  1209. teamManager->PushTeamAssigned(teamMember);
  1210. BitStream bsOut;
  1211. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  1212. bsOut.WriteCasted<MessageID>(ID_RUN_UpdateTeamsRequestedToNoneAndAddTeam);
  1213. bsOut.Write(GetWorldId());
  1214. bsOut.Write(teamMember->GetNetworkID());
  1215. bsOut.Write(team->GetNetworkID());
  1216. BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  1217. }
  1218. }
  1219. else
  1220. {
  1221. // Switch or join specific
  1222. DataStructures::List<TM_Team*> teamsWeAreLeaving;
  1223. bool isSwitch = teamMember->teamsRequested[indexIntoTeamsRequested].isTeamSwitch;
  1224. TM_Team *teamToLeave;
  1225. if (isSwitch)
  1226. {
  1227. teamToLeave=teamMember->teamsRequested[indexIntoTeamsRequested].teamToLeave;
  1228. if (teamToLeave)
  1229. {
  1230. if (teamMember->IsOnTeam(teamToLeave))
  1231. {
  1232. teamsWeAreLeaving.Push(teamToLeave, _FILE_AND_LINE_);
  1233. }
  1234. else
  1235. {
  1236. teamToLeave=0;
  1237. isSwitch=false;
  1238. }
  1239. }
  1240. else
  1241. {
  1242. teamsWeAreLeaving=teamMember->teams;
  1243. }
  1244. }
  1245. else
  1246. teamToLeave=0;
  1247. int teamJoined = JoinSpecificTeam(teamMember, team, isSwitch, teamToLeave, teamsWeAreLeaving);
  1248. if (teamJoined==1)
  1249. {
  1250. BitStream bsOut;
  1251. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  1252. bsOut.WriteCasted<MessageID>(ID_RUN_RemoveFromTeamsRequestedAndAddTeam);
  1253. bsOut.Write(GetWorldId());
  1254. bsOut.Write(teamMember->GetNetworkID());
  1255. bsOut.Write(team->GetNetworkID());
  1256. bsOut.Write(isSwitch);
  1257. if (teamToLeave!=0)
  1258. {
  1259. bsOut.Write(true);
  1260. bsOut.Write(teamToLeave->GetNetworkID());
  1261. }
  1262. else
  1263. bsOut.Write(false);
  1264. BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  1265. }
  1266. }
  1267. }
  1268. }
  1269. }
  1270. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1271. unsigned int TM_World::GetAvailableTeamIndexWithFewestMembers(TeamMemberLimit secondaryLimit, JoinPermissions joinPermissions)
  1272. {
  1273. unsigned int teamIndex;
  1274. unsigned int lowestTeamMembers = (unsigned int) -1;
  1275. unsigned int lowestIndex = (unsigned int) -1;
  1276. for (teamIndex=0; teamIndex < teams.Size(); teamIndex++)
  1277. {
  1278. if (teams[teamIndex]->GetTeamMembersCount() < secondaryLimit &&
  1279. teams[teamIndex]->GetTeamMembersCount() < teams[teamIndex]->GetMemberLimitSetting() &&
  1280. teams[teamIndex]->GetTeamMembersCount() < lowestTeamMembers &&
  1281. (joinPermissions & teams[teamIndex]->GetJoinPermissions())!=0)
  1282. {
  1283. lowestTeamMembers = teams[teamIndex]->GetTeamMembersCount();
  1284. lowestIndex = teamIndex;
  1285. }
  1286. }
  1287. return lowestIndex;
  1288. }
  1289. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1290. void TM_World::GetSortedJoinRequests(DataStructures::OrderedList<TM_World::JoinRequestHelper, TM_World::JoinRequestHelper, JoinRequestHelperComp> &joinRequests)
  1291. {
  1292. unsigned int i;
  1293. for (i=0; i < teamMembers.Size(); i++)
  1294. {
  1295. TM_TeamMember *teamMember = teamMembers[i];
  1296. if (teamMember->teamsRequested.Size()==0)
  1297. {
  1298. if (teamMember->joinTeamType==JOIN_ANY_AVAILABLE_TEAM)
  1299. {
  1300. TM_World::JoinRequestHelper jrh;
  1301. jrh.whenRequestMade=teamMember->whenJoinAnyRequested;
  1302. jrh.teamMemberIndex=i;
  1303. jrh.requestIndex=teamMember->joinAnyRequestIndex;
  1304. joinRequests.Insert(jrh, jrh, true, _FILE_AND_LINE_);
  1305. }
  1306. }
  1307. else
  1308. {
  1309. unsigned int j;
  1310. for (j=0; j < teamMember->teamsRequested.Size(); j++)
  1311. {
  1312. TM_World::JoinRequestHelper jrh;
  1313. jrh.whenRequestMade=teamMember->teamsRequested[j].whenRequested;
  1314. jrh.teamMemberIndex=i;
  1315. jrh.indexIntoTeamsRequested=j;
  1316. jrh.requestIndex=teamMember->teamsRequested[j].requestIndex;
  1317. joinRequests.Insert(jrh, jrh, true, _FILE_AND_LINE_);
  1318. }
  1319. }
  1320. }
  1321. }
  1322. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1323. void TM_World::BroadcastToParticipants(RakNet::BitStream *bsOut, RakNetGUID exclusionGuid)
  1324. {
  1325. for (unsigned int i=0; i < participants.Size(); i++)
  1326. {
  1327. if (participants[i]==exclusionGuid)
  1328. continue;
  1329. teamManager->SendUnified(bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, participants[i], false);
  1330. }
  1331. }
  1332. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1333. void TM_World::BroadcastToParticipants(unsigned char *data, const int length, RakNetGUID exclusionGuid)
  1334. {
  1335. for (unsigned int i=0; i < participants.Size(); i++)
  1336. {
  1337. if (participants[i]==exclusionGuid)
  1338. continue;
  1339. teamManager->SendUnified((const char*) data, length, HIGH_PRIORITY, RELIABLE_ORDERED, 0, participants[i], false);
  1340. }
  1341. }
  1342. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1343. TM_Team* TM_World::JoinAnyTeam(TM_TeamMember *teamMember, int *resultCode)
  1344. {
  1345. TeamMemberLimit balancedLimit = GetBalancedTeamLimit();
  1346. unsigned int idx = GetAvailableTeamIndexWithFewestMembers(balancedLimit, ALLOW_JOIN_ANY_AVAILABLE_TEAM);
  1347. if (idx == (unsigned int ) -1)
  1348. {
  1349. // If any team is joinable but full, return full. Otherwise return locked
  1350. for (idx=0; idx < teams.Size(); idx++)
  1351. {
  1352. if ((teams[idx]->GetTeamMembersCount() >= balancedLimit ||
  1353. teams[idx]->GetTeamMembersCount() >= teams[idx]->GetMemberLimitSetting()) &&
  1354. teams[idx]->GetMemberLimitSetting() != 0 &&
  1355. (ALLOW_JOIN_ANY_AVAILABLE_TEAM & teams[idx]->GetJoinPermissions())!=0)
  1356. {
  1357. // Full
  1358. *resultCode=-2;
  1359. return teams[idx];
  1360. }
  1361. }
  1362. // Locked
  1363. *resultCode=-1;
  1364. return 0;
  1365. }
  1366. TM_Team* lowestMemberTeam = teams[idx];
  1367. teamMember->StoreLastTeams();
  1368. teamMember->UpdateTeamsRequestedToNone();
  1369. teamMember->AddToTeamList(lowestMemberTeam);
  1370. teamManager->PushTeamAssigned(teamMember);
  1371. *resultCode=1;
  1372. return lowestMemberTeam;
  1373. }
  1374. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1375. int TM_World::JoinSpecificTeam(TM_TeamMember *teamMember, TM_Team *team, bool isTeamSwitch, TM_Team *teamToLeave, DataStructures::List<TM_Team*> &teamsWeAreLeaving)
  1376. {
  1377. if (team->GetJoinPermissions() & ALLOW_JOIN_SPECIFIC_TEAM)
  1378. {
  1379. if (balanceTeamsIsActive==false || teamsWeAreLeaving.Size()==0)
  1380. {
  1381. if (team->GetMemberLimit() > team->GetTeamMembersCount())
  1382. {
  1383. // Can join normally
  1384. teamMember->StoreLastTeams();
  1385. teamManager->RemoveFromTeamsRequestedAndAddTeam(teamMember, team, isTeamSwitch, teamToLeave);
  1386. return 1;
  1387. }
  1388. else
  1389. {
  1390. // Full
  1391. return -2;
  1392. }
  1393. }
  1394. else
  1395. {
  1396. // Note: balanceTeamsIsActive==true && isTeamSwitch==true
  1397. // Do limited team swap
  1398. // We must be on one team, target must be on one team, and we want to exchange teams
  1399. if (teamsWeAreLeaving.Size()==1)
  1400. {
  1401. unsigned int j = team->GetMemberWithRequestedSingleTeamSwitch(teamsWeAreLeaving[0]);
  1402. if (j!=(unsigned int)-1)
  1403. {
  1404. TM_TeamMember *swappingMember = team->teamMembers[j];
  1405. teamMember->StoreLastTeams();
  1406. swappingMember->StoreLastTeams();
  1407. teamManager->RemoveFromTeamsRequestedAndAddTeam(teamMember, team, true, 0);
  1408. teamManager->RemoveFromTeamsRequestedAndAddTeam(swappingMember, teamsWeAreLeaving[0], true, 0);
  1409. // Send ID_TEAM_BALANCER_TEAM_ASSIGNED to all, for swapped member
  1410. // Calling function sends ID_RUN_RemoveFromTeamsRequestedAndAddTeam which pushes ID_TEAM_BALANCER_TEAM_ASSIGNED for teamMember
  1411. RakNet::BitStream bitStream;
  1412. bitStream.WriteCasted<MessageID>(ID_TEAM_BALANCER_TEAM_ASSIGNED);
  1413. teamManager->EncodeTeamAssigned(&bitStream, swappingMember);
  1414. BroadcastToParticipants(&bitStream, UNASSIGNED_RAKNET_GUID);
  1415. return 1;
  1416. }
  1417. }
  1418. // Full
  1419. return -2;
  1420. }
  1421. }
  1422. else
  1423. {
  1424. // Locked
  1425. return -1;
  1426. }
  1427. }
  1428. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1429. TeamMemberLimit TM_World::GetBalancedTeamLimit(void) const
  1430. {
  1431. if (teams.Size()==0)
  1432. return 0;
  1433. if (balanceTeamsIsActive==false)
  1434. return (TeamMemberLimit) -1;
  1435. unsigned int i;
  1436. bool additionalTeamsExcluded;
  1437. TeamMemberLimit balancedLimit;
  1438. unsigned int teamsCount=teams.Size();
  1439. unsigned int membersCount=teamMembers.Size();
  1440. DataStructures::List<TM_Team*> consideredTeams = teams;
  1441. do
  1442. {
  1443. additionalTeamsExcluded=false;
  1444. balancedLimit = (TeamMemberLimit) ((membersCount+(teamsCount-1))/(teamsCount));
  1445. i=0;
  1446. while (i < consideredTeams.Size())
  1447. {
  1448. if (consideredTeams[i]->GetMemberLimitSetting() < balancedLimit)
  1449. {
  1450. additionalTeamsExcluded=true;
  1451. membersCount-=consideredTeams[i]->GetMemberLimitSetting();
  1452. teamsCount--;
  1453. consideredTeams.RemoveAtIndexFast(i);
  1454. }
  1455. else
  1456. {
  1457. i++;
  1458. }
  1459. }
  1460. } while (additionalTeamsExcluded==true && teamsCount>0);
  1461. return balancedLimit;
  1462. }
  1463. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1464. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1465. TeamManager::TeamManager()
  1466. {
  1467. for (unsigned int i=0; i < 255; i++)
  1468. worldsArray[i]=0;
  1469. autoAddParticipants=true;
  1470. topology=TM_PEER_TO_PEER;
  1471. }
  1472. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1473. TeamManager::~TeamManager()
  1474. {
  1475. Clear();
  1476. }
  1477. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1478. TM_World* TeamManager::AddWorld(WorldId worldId)
  1479. {
  1480. RakAssert(worldsArray[worldId]==0 && "World already in use");
  1481. TM_World *newWorld = RakNet::OP_NEW<TM_World>(_FILE_AND_LINE_);
  1482. newWorld->worldId=worldId;
  1483. newWorld->teamManager=this;
  1484. newWorld->hostGuid=GetMyGUIDUnified();
  1485. worldsArray[worldId]=newWorld;
  1486. worldsList.Push(newWorld,_FILE_AND_LINE_);
  1487. return newWorld;
  1488. }
  1489. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1490. void TeamManager::RemoveWorld(WorldId worldId)
  1491. {
  1492. RakAssert(worldsArray[worldId]!=0 && "World not in use");
  1493. for (unsigned int i=0; i < worldsList.Size(); i++)
  1494. {
  1495. if (worldsList[i]==worldsArray[worldId])
  1496. {
  1497. RakNet::OP_DELETE(worldsList[i],_FILE_AND_LINE_);
  1498. worldsList.RemoveAtIndexFast(i);
  1499. break;
  1500. }
  1501. }
  1502. worldsArray[worldId]=0;
  1503. }
  1504. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1505. unsigned int TeamManager::GetWorldCount(void) const
  1506. {
  1507. return worldsList.Size();
  1508. }
  1509. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1510. TM_World* TeamManager::GetWorldAtIndex(unsigned int index) const
  1511. {
  1512. return worldsList[index];
  1513. }
  1514. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1515. TM_World* TeamManager::GetWorldWithId(WorldId worldId) const
  1516. {
  1517. return worldsArray[worldId];
  1518. }
  1519. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1520. void TeamManager::SetAutoManageConnections(bool autoAdd)
  1521. {
  1522. autoAddParticipants=autoAdd;
  1523. for (unsigned int i=0; i < worldsList.Size(); i++)
  1524. {
  1525. worldsList[i]->SetAutoManageConnections(autoAdd);
  1526. }
  1527. }
  1528. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1529. void TeamManager::SetTopology(TMTopology _topology)
  1530. {
  1531. topology=_topology;
  1532. }
  1533. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1534. void TeamManager::EncodeTeamFull(RakNet::BitStream *bitStream, TM_TeamMember *teamMember, TM_Team *team)
  1535. {
  1536. bitStream->WriteCasted<MessageID>(ID_TEAM_BALANCER_REQUESTED_TEAM_FULL);
  1537. EncodeTeamFullOrLocked(bitStream, teamMember, team);
  1538. }
  1539. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1540. void TeamManager::DecomposeTeamFull(Packet *packet,
  1541. TM_World **world, TM_TeamMember **teamMember, TM_Team **team,
  1542. uint16_t &currentMembers, uint16_t &memberLimitIncludingBalancing, bool &balancingIsActive, JoinPermissions &joinPermissions)
  1543. {
  1544. BitStream bsIn(packet->data,packet->length,false);
  1545. bsIn.IgnoreBytes(sizeof(MessageID));
  1546. DecomposeTeamFullOrLocked(&bsIn, world, teamMember, team, currentMembers, memberLimitIncludingBalancing, balancingIsActive, joinPermissions);
  1547. }
  1548. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1549. void TeamManager::EncodeTeamLocked(RakNet::BitStream *bitStream, TM_TeamMember *teamMember, TM_Team *team)
  1550. {
  1551. bitStream->WriteCasted<MessageID>(ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED);
  1552. EncodeTeamFullOrLocked(bitStream, teamMember, team);
  1553. }
  1554. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1555. void TeamManager::EncodeTeamFullOrLocked(RakNet::BitStream *bitStream, TM_TeamMember *teamMember, TM_Team *team)
  1556. {
  1557. bitStream->Write(teamMember->world->GetWorldId());
  1558. bitStream->Write(teamMember->GetNetworkID());
  1559. bitStream->Write(team->GetNetworkID());
  1560. bitStream->WriteCasted<uint16_t>(team->GetTeamMembersCount());
  1561. bitStream->Write(team->GetMemberLimit());
  1562. bitStream->Write(team->GetBalancingApplies());
  1563. bitStream->Write(team->GetJoinPermissions());
  1564. }
  1565. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1566. void TeamManager::DecomposeTeamFullOrLocked(RakNet::BitStream *bsIn, TM_World **world, TM_TeamMember **teamMember, TM_Team **team,
  1567. uint16_t &currentMembers, uint16_t &memberLimitIncludingBalancing, bool &balancingIsActive, JoinPermissions &joinPermissions)
  1568. {
  1569. WorldId worldId;
  1570. NetworkID teamMemberId;
  1571. NetworkID teamId;
  1572. *teamMember=0;
  1573. *team=0;
  1574. *world=0;
  1575. bsIn->Read(worldId);
  1576. bsIn->Read(teamMemberId);
  1577. bsIn->Read(teamId);
  1578. bsIn->Read(currentMembers);
  1579. bsIn->Read(memberLimitIncludingBalancing);
  1580. bsIn->Read(balancingIsActive);
  1581. bsIn->Read(joinPermissions);
  1582. *world = GetWorldWithId(worldId);
  1583. if (*world)
  1584. {
  1585. *teamMember = (*world)->GetTeamMemberByNetworkID(teamMemberId);
  1586. *team = (*world)->GetTeamByNetworkID(teamId);
  1587. }
  1588. }
  1589. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1590. void TeamManager::DecomposeTeamLocked(Packet *packet,
  1591. TM_World **world, TM_TeamMember **teamMember, TM_Team **team,
  1592. uint16_t &currentMembers, uint16_t &memberLimitIncludingBalancing, bool &balancingIsActive, JoinPermissions &joinPermissions)
  1593. {
  1594. BitStream bsIn(packet->data,packet->length,false);
  1595. bsIn.IgnoreBytes(sizeof(MessageID));
  1596. DecomposeTeamFullOrLocked(&bsIn, world, teamMember, team, currentMembers, memberLimitIncludingBalancing, balancingIsActive, joinPermissions);
  1597. }
  1598. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1599. void TeamManager::EncodeTeamAssigned(RakNet::BitStream *bitStream, TM_TeamMember *teamMember)
  1600. {
  1601. bitStream->Write(teamMember->world->GetWorldId());
  1602. bitStream->Write(teamMember->GetNetworkID());
  1603. bitStream->WriteCasted<uint16_t>(teamMember->teams.Size());
  1604. for (unsigned int i=0; i < teamMember->teams.Size(); i++)
  1605. {
  1606. bitStream->Write(teamMember->teams[i]->GetNetworkID());
  1607. }
  1608. bitStream->Write(teamMember->noTeamSubcategory);
  1609. bitStream->Write(teamMember->joinTeamType);
  1610. }
  1611. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1612. void TeamManager::ProcessTeamAssigned(RakNet::BitStream *bsIn)
  1613. {
  1614. TM_World *world;
  1615. TM_TeamMember *teamMember;
  1616. NoTeamId noTeamId;
  1617. JoinTeamType joinTeamType;
  1618. DataStructures::List<TM_Team *> newTeam;
  1619. DataStructures::List<TM_Team *> teamsLeft;
  1620. DataStructures::List<TM_Team *> teamsJoined;
  1621. DecodeTeamAssigned(bsIn, &world, &teamMember, noTeamId, joinTeamType, newTeam, teamsLeft, teamsJoined);
  1622. if (teamMember)
  1623. {
  1624. teamMember->StoreLastTeams();
  1625. for (unsigned int i=0; i < teamsLeft.Size(); i++)
  1626. {
  1627. teamMember->RemoveFromSpecificTeamInternal(teamsLeft[i]);
  1628. }
  1629. for (unsigned int i=0; i < teamsJoined.Size(); i++)
  1630. {
  1631. if (teamMember->IsOnTeam(teamsJoined[i])==false)
  1632. {
  1633. teamMember->RemoveFromRequestedTeams(teamsJoined[i]);
  1634. teamMember->AddToTeamList(teamsJoined[i]);
  1635. }
  1636. }
  1637. teamMember->noTeamSubcategory=noTeamId;
  1638. teamMember->joinTeamType=joinTeamType;
  1639. }
  1640. }
  1641. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1642. void TeamManager::DecodeTeamAssigned(Packet *packet, TM_World **world, TM_TeamMember **teamMember)
  1643. {
  1644. WorldId worldId;
  1645. NetworkID teamMemberId;
  1646. RakNet::BitStream bsIn(packet->data, packet->length, false);
  1647. bsIn.IgnoreBytes(sizeof(MessageID));
  1648. bsIn.Read(worldId);
  1649. bsIn.Read(teamMemberId);
  1650. *world = GetWorldWithId(worldId);
  1651. if (*world)
  1652. {
  1653. *teamMember = (*world)->GetTeamMemberByNetworkID(teamMemberId);
  1654. }
  1655. else
  1656. {
  1657. *teamMember=0;
  1658. }
  1659. }
  1660. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1661. void TeamManager::DecodeTeamCancelled(Packet *packet, TM_World **world, TM_TeamMember **teamMember, TM_Team **teamCancelled)
  1662. {
  1663. WorldId worldId;
  1664. NetworkID teamMemberId;
  1665. RakNet::BitStream bsIn(packet->data, packet->length, false);
  1666. bsIn.IgnoreBytes(sizeof(MessageID));
  1667. bsIn.Read(worldId);
  1668. bsIn.Read(teamMemberId);
  1669. bool sp=false;
  1670. *world = GetWorldWithId(worldId);
  1671. if (*world)
  1672. {
  1673. *teamMember = (*world)->GetTeamMemberByNetworkID(teamMemberId);
  1674. }
  1675. else
  1676. {
  1677. *teamMember=0;
  1678. }
  1679. bsIn.Read(sp);
  1680. if (sp)
  1681. {
  1682. NetworkID nid;
  1683. bsIn.Read(nid);
  1684. *teamCancelled = (*world)->GetTeamByNetworkID(nid);
  1685. }
  1686. else
  1687. {
  1688. *teamCancelled = 0;
  1689. }
  1690. }
  1691. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1692. void TeamManager::DecodeTeamAssigned(BitStream *bsIn, TM_World **world, TM_TeamMember **teamMember, NoTeamId &noTeamId,
  1693. JoinTeamType &joinTeamType, DataStructures::List<TM_Team *> &newTeam,
  1694. DataStructures::List<TM_Team *> &teamsLeft, DataStructures::List<TM_Team *> &teamsJoined
  1695. )
  1696. {
  1697. newTeam.Clear(true, _FILE_AND_LINE_);
  1698. teamsLeft.Clear(true, _FILE_AND_LINE_);
  1699. teamsJoined.Clear(true, _FILE_AND_LINE_);
  1700. WorldId worldId;
  1701. NetworkID teamMemberId;
  1702. NetworkID teamId;
  1703. bsIn->Read(worldId);
  1704. bsIn->Read(teamMemberId);
  1705. *world = GetWorldWithId(worldId);
  1706. if (*world)
  1707. {
  1708. *teamMember = (*world)->GetTeamMemberByNetworkID(teamMemberId);
  1709. uint16_t teamsCount;
  1710. bsIn->Read(teamsCount);
  1711. for (unsigned int i=0; i < teamsCount; i++)
  1712. {
  1713. bsIn->Read(teamId);
  1714. TM_Team * team = (*world)->GetTeamByNetworkID(teamId);
  1715. RakAssert(team);
  1716. if (team)
  1717. newTeam.Push(team, _FILE_AND_LINE_);
  1718. // else probably didn't reference team first
  1719. }
  1720. if (*teamMember)
  1721. {
  1722. for (unsigned int i=0; i < (*teamMember)->teams.Size(); i++)
  1723. {
  1724. TM_Team *team = (*teamMember)->teams[i];
  1725. if (newTeam.GetIndexOf(team)==(unsigned int)-1)
  1726. teamsLeft.Push(team, _FILE_AND_LINE_);
  1727. }
  1728. }
  1729. for (unsigned int i=0; i < newTeam.Size(); i++)
  1730. {
  1731. TM_Team *team = newTeam[i];
  1732. if ((*teamMember)->teams.GetIndexOf(team)==(unsigned int)-1)
  1733. teamsJoined.Push(team, _FILE_AND_LINE_);
  1734. }
  1735. bsIn->Read(noTeamId);
  1736. bsIn->Read(joinTeamType);
  1737. }
  1738. else
  1739. {
  1740. *teamMember=0;
  1741. }
  1742. }
  1743. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1744. void TeamManager::Clear(void)
  1745. {
  1746. for (unsigned int i=0; i < worldsList.Size(); i++)
  1747. {
  1748. worldsArray[worldsList[i]->worldId]=0;
  1749. worldsList[i]->Clear();
  1750. delete worldsList[i];
  1751. }
  1752. worldsList.Clear(false, _FILE_AND_LINE_);
  1753. }
  1754. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1755. void TeamManager::Update(void)
  1756. {
  1757. }
  1758. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1759. PluginReceiveResult TeamManager::OnReceive(Packet *packet)
  1760. {
  1761. switch (packet->data[0])
  1762. {
  1763. case ID_FCM2_NEW_HOST:
  1764. {
  1765. unsigned int i;
  1766. for (i=0; i < worldsList.Size(); i++)
  1767. worldsList[i]->SetHost(packet->guid);
  1768. }
  1769. break;
  1770. case ID_TEAM_BALANCER_TEAM_ASSIGNED:
  1771. {
  1772. BitStream bsIn(packet->data,packet->length,false);
  1773. bsIn.IgnoreBytes(sizeof(MessageID));
  1774. ProcessTeamAssigned(&bsIn);
  1775. }
  1776. break;
  1777. case ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED:
  1778. {
  1779. BitStream bsIn(packet->data,packet->length,false);
  1780. bsIn.IgnoreBytes(1);
  1781. WorldId worldId;
  1782. bsIn.Read(worldId);
  1783. TM_World *world = GetWorldWithId(worldId);
  1784. if (world==0)
  1785. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  1786. bool validPacket = OnRemoveFromRequestedTeams(packet, world);
  1787. if (validPacket==false)
  1788. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  1789. break;
  1790. }
  1791. case ID_TEAM_BALANCER_INTERNAL:
  1792. {
  1793. if (packet->length>=2)
  1794. {
  1795. BitStream bsIn(packet->data,packet->length,false);
  1796. bsIn.IgnoreBytes(2);
  1797. WorldId worldId;
  1798. bsIn.Read(worldId);
  1799. TM_World *world = GetWorldWithId(worldId);
  1800. if (world==0)
  1801. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  1802. switch (packet->data[1])
  1803. {
  1804. case ID_RUN_UpdateListsToNoTeam:
  1805. OnUpdateListsToNoTeam(packet, world);
  1806. break;
  1807. case ID_RUN_UpdateTeamsRequestedToAny:
  1808. OnUpdateTeamsRequestedToAny(packet, world);
  1809. break;
  1810. case ID_RUN_JoinAnyTeam:
  1811. OnJoinAnyTeam(packet, world);
  1812. break;
  1813. case ID_RUN_JoinRequestedTeam:
  1814. OnJoinRequestedTeam(packet, world);
  1815. break;
  1816. case ID_RUN_UpdateTeamsRequestedToNoneAndAddTeam:
  1817. OnUpdateTeamsRequestedToNoneAndAddTeam(packet, world);
  1818. break;
  1819. case ID_RUN_RemoveFromTeamsRequestedAndAddTeam:
  1820. OnRemoveFromTeamsRequestedAndAddTeam(packet, world);
  1821. break;
  1822. case ID_RUN_AddToRequestedTeams:
  1823. OnAddToRequestedTeams(packet, world);
  1824. break;
  1825. case ID_RUN_LeaveTeam:
  1826. OnLeaveTeam(packet, world);
  1827. break;
  1828. case ID_RUN_SetMemberLimit:
  1829. OnSetMemberLimit(packet, world);
  1830. break;
  1831. case ID_RUN_SetJoinPermissions:
  1832. OnSetJoinPermissions(packet, world);
  1833. break;
  1834. case ID_RUN_SetBalanceTeams:
  1835. OnSetBalanceTeams(packet, world);
  1836. break;
  1837. case ID_RUN_SetBalanceTeamsInitial:
  1838. OnSetBalanceTeamsInitial(packet, world);
  1839. break;
  1840. }
  1841. }
  1842. }
  1843. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  1844. }
  1845. return RR_CONTINUE_PROCESSING;
  1846. }
  1847. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1848. void TeamManager::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
  1849. {
  1850. for (unsigned int i=0; i < worldsList.Size(); i++)
  1851. {
  1852. worldsList[i]->OnClosedConnection(systemAddress, rakNetGUID, lostConnectionReason);
  1853. }
  1854. }
  1855. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1856. void TeamManager::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
  1857. {
  1858. for (unsigned int i=0; i < worldsList.Size(); i++)
  1859. {
  1860. worldsList[i]->OnNewConnection(systemAddress, rakNetGUID, isIncoming);
  1861. }
  1862. }
  1863. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1864. void TeamManager::Send( const RakNet::BitStream * bitStream, const AddressOrGUID systemIdentifier, bool broadcast )
  1865. {
  1866. SendUnified(bitStream,HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemIdentifier, broadcast);
  1867. }
  1868. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1869. void TeamManager::RemoveFromTeamsRequestedAndAddTeam(TM_TeamMember *teamMember, TM_Team *team, bool isTeamSwitch, TM_Team *teamToLeave)
  1870. {
  1871. teamMember->RemoveFromRequestedTeams(team);
  1872. if (isTeamSwitch)
  1873. {
  1874. if (teamToLeave==0)
  1875. {
  1876. // Leave all teams
  1877. teamMember->RemoveFromAllTeamsInternal();
  1878. }
  1879. else
  1880. {
  1881. // Leave specific team if it exists
  1882. teamMember->RemoveFromSpecificTeamInternal(teamToLeave);
  1883. }
  1884. }
  1885. teamMember->AddToTeamList(team);
  1886. PushTeamAssigned(teamMember);
  1887. }
  1888. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1889. void TeamManager::PushTeamAssigned(TM_TeamMember *teamMember)
  1890. {
  1891. // Push ID_TEAM_BALANCER_TEAM_ASSIGNED locally
  1892. RakNet::BitStream bitStream;
  1893. bitStream.WriteCasted<MessageID>(ID_TEAM_BALANCER_TEAM_ASSIGNED);
  1894. EncodeTeamAssigned(&bitStream, teamMember);
  1895. PushBitStream(&bitStream);
  1896. }
  1897. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1898. void TeamManager::PushBitStream(RakNet::BitStream *bitStream)
  1899. {
  1900. Packet *p = AllocatePacketUnified(bitStream->GetNumberOfBytesUsed());
  1901. memcpy(p->data, bitStream->GetData(), bitStream->GetNumberOfBytesUsed());
  1902. p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
  1903. p->systemAddress.systemIndex=(SystemIndex)-1;
  1904. p->guid=UNASSIGNED_RAKNET_GUID;
  1905. p->wasGeneratedLocally=true;
  1906. PushBackPacketUnified(p, true);
  1907. }
  1908. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1909. void TeamManager::OnUpdateListsToNoTeam(Packet *packet, TM_World *world)
  1910. {
  1911. BitStream bsIn(packet->data,packet->length,false);
  1912. bsIn.IgnoreBytes(2+sizeof(WorldId));
  1913. NetworkID networkId;
  1914. bsIn.Read(networkId);
  1915. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  1916. NoTeamId noTeamId;
  1917. bsIn.Read(noTeamId);
  1918. if (teamMember)
  1919. {
  1920. teamMember->StoreLastTeams();
  1921. teamMember->UpdateListsToNoTeam(noTeamId);
  1922. PushTeamAssigned(teamMember);
  1923. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified())
  1924. {
  1925. world->FillRequestedSlots();
  1926. world->EnforceTeamBalance(noTeamId);
  1927. if (topology==TM_CLIENT_SERVER)
  1928. {
  1929. // Relay
  1930. world->BroadcastToParticipants(packet->data, packet->length, packet->guid);
  1931. }
  1932. }
  1933. }
  1934. }
  1935. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1936. void TeamManager::OnUpdateTeamsRequestedToAny(Packet *packet, TM_World *world)
  1937. {
  1938. BitStream bsIn(packet->data,packet->length,false);
  1939. bsIn.IgnoreBytes(2+sizeof(WorldId));
  1940. NetworkID networkId;
  1941. bsIn.Read(networkId);
  1942. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  1943. if (teamMember)
  1944. {
  1945. teamMember->UpdateTeamsRequestedToAny();
  1946. }
  1947. }
  1948. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1949. void TeamManager::OnJoinAnyTeam(Packet *packet, TM_World *world)
  1950. {
  1951. BitStream bsIn(packet->data,packet->length,false);
  1952. bsIn.IgnoreBytes(2+sizeof(WorldId));
  1953. NetworkID networkId;
  1954. bsIn.Read(networkId);
  1955. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  1956. if (teamMember)
  1957. {
  1958. // This is a host-only operation
  1959. RakAssert(world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified());
  1960. teamMember->UpdateTeamsRequestedToAny();
  1961. int resultCode;
  1962. TM_Team *newTeam = world->JoinAnyTeam(teamMember, &resultCode);
  1963. if (resultCode==1)
  1964. {
  1965. // Broadcast packet - remote systems should clear requested teams to none, and add the team we joined.
  1966. // Broadcast includes non-host sender (all participants)
  1967. BitStream bsOut;
  1968. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  1969. bsOut.WriteCasted<MessageID>(ID_RUN_UpdateTeamsRequestedToNoneAndAddTeam);
  1970. bsOut.Write(world->GetWorldId());
  1971. bsOut.Write(networkId);
  1972. bsOut.Write(newTeam->GetNetworkID());
  1973. world->BroadcastToParticipants(&bsOut, packet->guid);
  1974. // Send to sender ID_TEAM_BALANCER_TEAM_ASSIGNED
  1975. if (packet->guid!=GetMyGUIDUnified())
  1976. {
  1977. RakNet::BitStream bitStream;
  1978. bitStream.WriteCasted<MessageID>(ID_TEAM_BALANCER_TEAM_ASSIGNED);
  1979. EncodeTeamAssigned(&bitStream, teamMember);
  1980. SendUnified(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
  1981. }
  1982. }
  1983. else
  1984. {
  1985. // Relay packet to set requested teams to any
  1986. BitStream bsOut;
  1987. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  1988. bsOut.WriteCasted<MessageID>(ID_RUN_UpdateTeamsRequestedToAny);
  1989. bsOut.Write(world->GetWorldId());
  1990. bsOut.Write(networkId);
  1991. world->BroadcastToParticipants(&bsOut, packet->guid);
  1992. bsOut.Reset();
  1993. if (resultCode==-2)
  1994. {
  1995. EncodeTeamFull(&bsOut, teamMember, newTeam);
  1996. }
  1997. else if (resultCode==-1)
  1998. {
  1999. EncodeTeamLocked(&bsOut, teamMember, newTeam);
  2000. }
  2001. // SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
  2002. world->BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  2003. if (packet->guid!=GetMyGUIDUnified())
  2004. PushBitStream(&bsOut);
  2005. }
  2006. }
  2007. }
  2008. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2009. void TeamManager::OnJoinRequestedTeam(Packet *packet, TM_World *world)
  2010. {
  2011. BitStream bsIn(packet->data,packet->length,false);
  2012. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2013. NetworkID networkId;
  2014. bsIn.Read(networkId);
  2015. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  2016. NetworkID teamToJoinNetworkId;
  2017. bsIn.Read(teamToJoinNetworkId);
  2018. TM_Team *teamToJoin = world->GetTeamByNetworkID(teamToJoinNetworkId);
  2019. bool isTeamSwitch=false;
  2020. bool switchSpecificTeam=false;
  2021. NetworkID teamToLeaveNetworkId=UNASSIGNED_NETWORK_ID;
  2022. TM_Team *teamToLeave=0;
  2023. bsIn.Read(isTeamSwitch);
  2024. if (isTeamSwitch)
  2025. {
  2026. bsIn.Read(switchSpecificTeam);
  2027. if (switchSpecificTeam)
  2028. {
  2029. bsIn.Read(teamToLeaveNetworkId);
  2030. teamToLeave = world->GetTeamByNetworkID(teamToLeaveNetworkId);
  2031. if (teamToLeave==0)
  2032. isTeamSwitch=false;
  2033. }
  2034. }
  2035. if (teamToJoin && teamMember)
  2036. {
  2037. if (isTeamSwitch)
  2038. {
  2039. if (teamMember->SwitchSpecificTeamCheck(teamToJoin, teamToLeave, packet->guid==GetMyGUIDUnified())==false)
  2040. return;
  2041. teamMember->AddToRequestedTeams(teamToJoin, teamToLeave);
  2042. }
  2043. else
  2044. {
  2045. if (teamMember->JoinSpecificTeamCheck(teamToJoin, packet->guid==GetMyGUIDUnified())==false)
  2046. return;
  2047. teamMember->AddToRequestedTeams(teamToJoin);
  2048. }
  2049. DataStructures::List<TM_Team*> teamsWeAreLeaving;
  2050. if (isTeamSwitch)
  2051. {
  2052. if (teamToLeave==0)
  2053. {
  2054. teamsWeAreLeaving=teamMember->teams;
  2055. }
  2056. else
  2057. {
  2058. if (teamMember->IsOnTeam(teamToLeave))
  2059. teamsWeAreLeaving.Push(teamToLeave, _FILE_AND_LINE_);
  2060. }
  2061. if (teamsWeAreLeaving.Size()==0)
  2062. isTeamSwitch=false;
  2063. }
  2064. int resultCode = world->JoinSpecificTeam(teamMember, teamToJoin, isTeamSwitch, teamToLeave, teamsWeAreLeaving);
  2065. if (resultCode==1)
  2066. {
  2067. // Broadcast packet - remote systems should remove from requested teams and add the team we joined.
  2068. // Broadcast includes non-host sender (all participants)
  2069. BitStream bsOut;
  2070. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  2071. bsOut.WriteCasted<MessageID>(ID_RUN_RemoveFromTeamsRequestedAndAddTeam);
  2072. bsOut.Write(world->GetWorldId());
  2073. bsOut.Write(networkId);
  2074. bsOut.Write(teamToJoin->GetNetworkID());
  2075. bsOut.Write(isTeamSwitch);
  2076. if (isTeamSwitch)
  2077. {
  2078. bsOut.Write(switchSpecificTeam);
  2079. if (switchSpecificTeam)
  2080. bsOut.Write(teamToLeaveNetworkId);
  2081. }
  2082. world->BroadcastToParticipants(&bsOut, packet->guid);
  2083. // Send to sender ID_TEAM_BALANCER_TEAM_ASSIGNED
  2084. if (packet->guid!=GetMyGUIDUnified())
  2085. {
  2086. RakNet::BitStream bitStream;
  2087. bitStream.WriteCasted<MessageID>(ID_TEAM_BALANCER_TEAM_ASSIGNED);
  2088. EncodeTeamAssigned(&bitStream, teamMember);
  2089. SendUnified(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
  2090. }
  2091. }
  2092. else
  2093. {
  2094. // Relay packet to set requested teams to any
  2095. BitStream bsOut;
  2096. bsOut.WriteCasted<MessageID>(ID_TEAM_BALANCER_INTERNAL);
  2097. bsOut.WriteCasted<MessageID>(ID_RUN_AddToRequestedTeams);
  2098. bsOut.Write(world->GetWorldId());
  2099. bsOut.Write(networkId);
  2100. bsOut.Write(teamToJoin->GetNetworkID());
  2101. bsOut.Write(isTeamSwitch);
  2102. if (isTeamSwitch)
  2103. {
  2104. bsOut.Write(switchSpecificTeam);
  2105. if (switchSpecificTeam)
  2106. bsOut.Write(teamToLeaveNetworkId);
  2107. }
  2108. world->BroadcastToParticipants(&bsOut, packet->guid);
  2109. bsOut.Reset();
  2110. if (resultCode==-2)
  2111. {
  2112. EncodeTeamFull(&bsOut, teamMember, teamToJoin);
  2113. }
  2114. else if (resultCode==-1)
  2115. {
  2116. EncodeTeamLocked(&bsOut, teamMember, teamToJoin);
  2117. }
  2118. // SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
  2119. world->BroadcastToParticipants(&bsOut, UNASSIGNED_RAKNET_GUID);
  2120. if (packet->guid!=GetMyGUIDUnified())
  2121. PushBitStream(&bsOut);
  2122. }
  2123. }
  2124. }
  2125. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2126. void TeamManager::OnUpdateTeamsRequestedToNoneAndAddTeam(Packet *packet, TM_World *world)
  2127. {
  2128. BitStream bsIn(packet->data,packet->length,false);
  2129. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2130. NetworkID networkId;
  2131. bsIn.Read(networkId);
  2132. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  2133. NetworkID teamNetworkId;
  2134. bsIn.Read(teamNetworkId);
  2135. TM_Team *team = world->GetTeamByNetworkID(teamNetworkId);
  2136. if (team && teamMember)
  2137. {
  2138. teamMember->StoreLastTeams();
  2139. teamMember->UpdateTeamsRequestedToNone();
  2140. teamMember->AddToTeamList(team);
  2141. world->GetTeamManager()->PushTeamAssigned(teamMember);
  2142. }
  2143. }
  2144. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2145. void TeamManager::OnRemoveFromTeamsRequestedAndAddTeam(Packet *packet, TM_World *world)
  2146. {
  2147. BitStream bsIn(packet->data,packet->length,false);
  2148. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2149. NetworkID networkId;
  2150. bsIn.Read(networkId);
  2151. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  2152. NetworkID teamNetworkId;
  2153. bsIn.Read(teamNetworkId);
  2154. bool isTeamSwitch=false, switchSpecificTeam=false;
  2155. NetworkID teamToLeaveNetworkId;
  2156. TM_Team *teamToLeave=0;
  2157. bsIn.Read(isTeamSwitch);
  2158. if (isTeamSwitch)
  2159. {
  2160. bsIn.Read(switchSpecificTeam);
  2161. if (switchSpecificTeam)
  2162. {
  2163. bsIn.Read(teamToLeaveNetworkId);
  2164. teamToLeave = world->GetTeamByNetworkID(teamToLeaveNetworkId);
  2165. }
  2166. }
  2167. TM_Team *team = world->GetTeamByNetworkID(teamNetworkId);
  2168. if (team && teamMember)
  2169. {
  2170. teamMember->StoreLastTeams();
  2171. if (teamToLeave)
  2172. teamMember->RemoveFromSpecificTeamInternal(teamToLeave);
  2173. else if (isTeamSwitch==true && switchSpecificTeam==false)
  2174. teamMember->RemoveFromAllTeamsInternal();
  2175. RemoveFromTeamsRequestedAndAddTeam(teamMember, team, false, 0);
  2176. }
  2177. }
  2178. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2179. void TeamManager::OnAddToRequestedTeams(Packet *packet, TM_World *world)
  2180. {
  2181. BitStream bsIn(packet->data,packet->length,false);
  2182. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2183. NetworkID networkId;
  2184. bsIn.Read(networkId);
  2185. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  2186. NetworkID teamNetworkId;
  2187. bsIn.Read(teamNetworkId);
  2188. TM_Team *team = world->GetTeamByNetworkID(teamNetworkId);
  2189. bool isTeamSwitch=false;
  2190. bool switchSpecificTeam=false;
  2191. NetworkID teamToLeaveNetworkId=UNASSIGNED_NETWORK_ID;
  2192. TM_Team *teamToLeave=0;
  2193. bsIn.Read(isTeamSwitch);
  2194. if (isTeamSwitch)
  2195. {
  2196. bsIn.Read(switchSpecificTeam);
  2197. if (switchSpecificTeam)
  2198. {
  2199. bsIn.Read(teamToLeaveNetworkId);
  2200. teamToLeave = world->GetTeamByNetworkID(teamToLeaveNetworkId);
  2201. if (teamToLeave==0)
  2202. isTeamSwitch=false;
  2203. }
  2204. }
  2205. if (team && teamMember)
  2206. {
  2207. if (isTeamSwitch)
  2208. teamMember->AddToRequestedTeams(team, teamToLeave);
  2209. else
  2210. teamMember->AddToRequestedTeams(team);
  2211. }
  2212. }
  2213. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2214. bool TeamManager::OnRemoveFromRequestedTeams(Packet *packet, TM_World *world)
  2215. {
  2216. BitStream bsIn(packet->data,packet->length,false);
  2217. bsIn.IgnoreBytes(1+sizeof(WorldId));
  2218. NetworkID networkId;
  2219. bsIn.Read(networkId);
  2220. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  2221. bool hasSpecificTeam=false;
  2222. NetworkID teamNetworkId;
  2223. TM_Team *team;
  2224. bsIn.Read(hasSpecificTeam);
  2225. if (hasSpecificTeam)
  2226. {
  2227. bsIn.Read(teamNetworkId);
  2228. team = world->GetTeamByNetworkID(teamNetworkId);
  2229. if (team==0)
  2230. return false;
  2231. }
  2232. else
  2233. {
  2234. team=0;
  2235. }
  2236. if (teamMember)
  2237. {
  2238. teamMember->RemoveFromRequestedTeams(team);
  2239. // Relay as host
  2240. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified() && topology==TM_CLIENT_SERVER)
  2241. {
  2242. world->BroadcastToParticipants(packet->data, packet->length, packet->guid);
  2243. }
  2244. return true;
  2245. }
  2246. else
  2247. {
  2248. return false;
  2249. }
  2250. }
  2251. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2252. void TeamManager::OnLeaveTeam(Packet *packet, TM_World *world)
  2253. {
  2254. BitStream bsIn(packet->data,packet->length,false);
  2255. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2256. NetworkID networkId;
  2257. bsIn.Read(networkId);
  2258. TM_TeamMember *teamMember = world->GetTeamMemberByNetworkID(networkId);
  2259. NetworkID teamNetworkId;
  2260. bsIn.Read(teamNetworkId);
  2261. TM_Team *team = world->GetTeamByNetworkID(teamNetworkId);
  2262. NoTeamId noTeamId;
  2263. bsIn.Read(noTeamId);
  2264. if (team && teamMember)
  2265. {
  2266. if (teamMember->LeaveTeamCheck(team)==false)
  2267. return;
  2268. teamMember->StoreLastTeams();
  2269. teamMember->RemoveFromSpecificTeamInternal(team);
  2270. if (teamMember->GetCurrentTeamCount()==0)
  2271. {
  2272. teamMember->noTeamSubcategory=noTeamId;
  2273. teamMember->joinTeamType=JOIN_NO_TEAM;
  2274. }
  2275. PushTeamAssigned(teamMember);
  2276. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified())
  2277. {
  2278. // Rebalance teams
  2279. world->FillRequestedSlots();
  2280. world->EnforceTeamBalance(noTeamId);
  2281. // Relay as host
  2282. if (topology==TM_CLIENT_SERVER)
  2283. world->BroadcastToParticipants(packet->data, packet->length, packet->guid);
  2284. }
  2285. }
  2286. }
  2287. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2288. void TeamManager::OnSetMemberLimit(Packet *packet, TM_World *world)
  2289. {
  2290. BitStream bsIn(packet->data,packet->length,false);
  2291. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2292. NetworkID teamNetworkId;
  2293. bsIn.Read(teamNetworkId);
  2294. TeamMemberLimit teamMemberLimit;
  2295. NoTeamId noTeamId;
  2296. bsIn.Read(teamMemberLimit);
  2297. bsIn.Read(noTeamId);
  2298. TM_Team *team = world->GetTeamByNetworkID(teamNetworkId);
  2299. if (team)
  2300. {
  2301. team->teamMemberLimit=teamMemberLimit;
  2302. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified())
  2303. {
  2304. if (packet->guid==GetMyGUIDUnified())
  2305. world->BroadcastToParticipants(packet->data, packet->length, packet->guid);
  2306. else
  2307. world->BroadcastToParticipants(packet->data, packet->length, UNASSIGNED_RAKNET_GUID);
  2308. world->FillRequestedSlots();
  2309. world->KickExcessMembers(noTeamId);
  2310. }
  2311. }
  2312. }
  2313. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2314. void TeamManager::OnSetJoinPermissions(Packet *packet, TM_World *world)
  2315. {
  2316. BitStream bsIn(packet->data,packet->length,false);
  2317. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2318. NetworkID teamNetworkId;
  2319. bsIn.Read(teamNetworkId);
  2320. JoinPermissions joinPermissions;
  2321. bsIn.Read(joinPermissions);
  2322. TM_Team *team = world->GetTeamByNetworkID(teamNetworkId);
  2323. if (team)
  2324. {
  2325. team->joinPermissions=joinPermissions;
  2326. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified())
  2327. {
  2328. if (packet->guid==GetMyGUIDUnified())
  2329. world->BroadcastToParticipants(packet->data, packet->length, packet->guid);
  2330. else
  2331. world->BroadcastToParticipants(packet->data, packet->length, UNASSIGNED_RAKNET_GUID);
  2332. world->FillRequestedSlots();
  2333. }
  2334. }
  2335. }
  2336. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2337. void TeamManager::OnSetBalanceTeams(Packet *packet, TM_World *world)
  2338. {
  2339. BitStream bsIn(packet->data,packet->length,false);
  2340. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2341. bool balanceTeams=false;
  2342. bsIn.Read(balanceTeams);
  2343. NoTeamId noTeamId;
  2344. bsIn.Read(noTeamId);
  2345. world->balanceTeamsIsActive=balanceTeams;
  2346. if (world->GetHost()==world->GetTeamManager()->GetMyGUIDUnified())
  2347. {
  2348. if (packet->guid==GetMyGUIDUnified())
  2349. world->BroadcastToParticipants(packet->data, packet->length, packet->guid);
  2350. else
  2351. world->BroadcastToParticipants(packet->data, packet->length, UNASSIGNED_RAKNET_GUID);
  2352. if (balanceTeams)
  2353. world->EnforceTeamBalance(noTeamId);
  2354. else
  2355. world->FillRequestedSlots();
  2356. }
  2357. }
  2358. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2359. void TeamManager::OnSetBalanceTeamsInitial(Packet *packet, TM_World *world)
  2360. {
  2361. BitStream bsIn(packet->data,packet->length,false);
  2362. bsIn.IgnoreBytes(2+sizeof(WorldId));
  2363. bool balanceTeams=false;
  2364. bsIn.Read(balanceTeams);
  2365. world->balanceTeamsIsActive=balanceTeams;
  2366. }
  2367. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  2368. #endif // _RAKNET_SUPPORT_TeamManager==1
粤ICP备19079148号