Author Topic: Set Up Teams in a Lobby  (Read 6512 times)

Katalyst

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Set Up Teams in a Lobby
« on: January 16, 2014, 06:47:48 PM »
Alright, I finally got my server browser operational and players are able to join channels. Unfortunately, the code I have to handle the assigning of teams and displaying the players is not working as intended. What I need is for the host to keep track of when players join and assign them to a team. Team One for the host and the next 4 who join and then Team Two for the next 5 people. Then I need the players names to be displayed under their appropriate team.

I modified TNet's TNPlayer class to contain an integer for a team, ie 1 or 2. The hard part for me is making sure that what team every player is assigned to is synced across the network so that the script can display everyone correctly.

This is the code I currently have handling it but it isn't syncing across the network so the clients that join don't have any players listed, not even themselves. The host can see himself and all the players as they join though. I'm new to scripting and even newer to networking so I'm sure there are mistakes in there.
  1. using UnityEngine;
  2. using TNet;
  3. using System.IO;
  4. using System.Net;
  5.  
  6. public class LobbyManager : MonoBehaviour
  7. {
  8.         public GameObject playerNamePrefab;
  9.         public GameObject teamOneParent;
  10.         public GameObject teamTwoParent;
  11.         public int playerCount = 0;
  12.        
  13.         TNObject tno;
  14.  
  15.         List<PlayerName> onePlayers = new List<PlayerName>();
  16.         List<PlayerName> twoPlayers = new List<PlayerName>();
  17.         bool mRebuild = true;
  18.         bool mShown = false;
  19.  
  20.         void OnNetworkJoinChannel (bool result, string message) {
  21.                 if(TNManager.isHosting) {
  22.                         playerCount++;
  23.                         TNManager.player.team = 1;
  24.                 }
  25.                 mRebuild = true;
  26.         }
  27.        
  28.         void OnNetworkPlayerJoin (Player p) {
  29.                 if(TNManager.isHosting) {
  30.                         playerCount++;
  31.                         tno.Send("UpdatePlayerCount", Target.OthersSaved, playerCount);
  32.                        
  33.                         if(playerCount <= 5) {
  34.                                 p.team = 1;
  35.                                 tno.Send("UpdatePlayerTeam", Target.OthersSaved, p.team);
  36.                         }
  37.                         else {
  38.                                 p.team = 2;
  39.                                 tno.Send("UpdatePlayerTeam", Target.OthersSaved, p.team);
  40.                         }
  41.                 }
  42.                 mRebuild = true;
  43.         }
  44.        
  45.         void OnNetworkPlayerLeave (Player p) {
  46.                 if(TNManager.isHosting) {
  47.                         playerCount--;
  48.                         tno.Send("UpdatePlayerCount", Target.OthersSaved, playerCount);
  49.                         p.team = 0;
  50.                         tno.Send("UpdatePlayerTeam", Target.OthersSaved, p.team);
  51.                 }
  52.                 mRebuild = true;
  53.         }
  54.        
  55.         void Start() { tno = GetComponent<TNObject>(); }
  56.        
  57.         void Update ()
  58.         {
  59.                 if (mRebuild)
  60.                 {
  61.                         mRebuild = false;
  62.  
  63.                         for (int i = 0; i < onePlayers.size; ++i)
  64.                         {
  65.                                 PlayerName p = onePlayers[i];
  66.                                 Destroy(p.gameObject);
  67.                         }
  68.                         for (int i = 0; i < twoPlayers.size; ++i)
  69.                         {
  70.                                 PlayerName p = twoPlayers[i];
  71.                                 Destroy(p.gameObject);
  72.                         }
  73.                         onePlayers.Clear();
  74.                         twoPlayers.Clear();
  75.  
  76.                         AddPlayer(TNManager.player);
  77.  
  78.                         for (int i = 0; i < TNManager.players.size; ++i)
  79.                                 AddPlayer(TNManager.players[i]);
  80.                 }
  81.         }
  82.        
  83.         void AddPlayer (Player p)
  84.         {
  85.                 PlayerName pn = GetPlayerEntry(p);
  86.                
  87.                 if (pn == null)
  88.                 {
  89.                         if(p.team == 1) {
  90.                                 GameObject go = MainMenuNetwork.AddChild(teamOneParent, playerNamePrefab);
  91.                                 pn = go.GetComponent<PlayerName>();
  92.                                 pn.player = p;
  93.                                 pn.UpdateInfo(mShown);
  94.                                 onePlayers.Add(pn);
  95.                         }
  96.                         else if (p.team == 2) {
  97.                                 GameObject go = MainMenuNetwork.AddChild(teamTwoParent, playerNamePrefab);
  98.                                 pn = go.GetComponent<PlayerName>();
  99.                                 pn.player = p;
  100.                                 pn.UpdateInfo(mShown);
  101.                                 twoPlayers.Add(pn);
  102.                         }
  103.                 }
  104.         }
  105.        
  106.         PlayerName GetPlayerEntry (Player p)
  107.         {
  108.                 if(p.team == 1) {
  109.                         for (int i = 0; i < onePlayers.size; ++i)
  110.                         {
  111.                                 PlayerName pn = onePlayers[i];
  112.                                 if (pn.player == p) return pn;
  113.                         }
  114.                 }
  115.                 else if (p.team == 2) {
  116.                         for (int i = 0; i < twoPlayers.size; ++i)
  117.                         {
  118.                                 PlayerName pn = twoPlayers[i];
  119.                                 if (pn.player == p) return pn;
  120.                         }
  121.                 }
  122.                         return null;
  123.         }
  124.        
  125.         [RFC] void UpdatePlayerCount(int count) { playerCount = count; }
  126.        
  127.         [RFC] void UpdatePlayerTeam(int team) { TNManager.player.team = team; }
  128. }

Any help for what I'm doing wrong here is greatly appreciated!
« Last Edit: January 16, 2014, 07:01:14 PM by Katalyst »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #1 on: January 17, 2014, 12:43:30 AM »
You're sending "UpdatePlayerTeam" to "others". Don't you mean to send it to the target player instead?

Katalyst

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #2 on: January 17, 2014, 05:13:22 PM »
I guess that depends. If I do this:
  1. void OnNetworkPlayerJoin (Player p) {
  2.                 if(TNManager.isHosting) {
  3.                         playerCount++;
  4.                         tno.Send("UpdatePlayerCount", Target.Others, playerCount);
  5.  
  6.                         if(playerCount <= 5)
  7.                                 tno.Send("UpdatePlayerTeam", p, 1);
  8.                         else
  9.                                 tno.Send("UpdatePlayerTeam", p, 2);
  10.                 }
  11.                 mRebuild = true;
  12.         }
instead of whats above, it should set the joining players team to 1. However, later on when that team is checked in AddPlayer, everyone is coming up as 0 and thus not being displayed. When I set and check a players team this way, is the info inside of that Player updated across the network automatically or only for the person sending and receiving the RFC, the host in this instance? If only for the sender/receiver, then how would I update everyone in the channel to this players team after it has been assigned to by the host?

Katalyst

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #3 on: January 19, 2014, 01:54:39 PM »
Upon some further research, it seems the RFC isn't reaching its destination. I'm not sure why, I'm testing all this on a local network using 127.0.0.1 and have been following the way its laid out in the docs. Player hosts a game, a channel is created holding the pre-game lobby, it shows up in the channel browser list for all other clients, and they can connect to it just fine.

I created just a simple RFC to set a bool to true when it was received and its never being set true when I directed at a joining player via OnNetworkPlayerJoin.

Anyone have ideas?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #4 on: January 20, 2014, 01:23:19 AM »
Did you give the TNObject a unique ID? TNOs that you don't instantiate via TNManager.Create must have unique non-zero IDs.

Katalyst

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #5 on: January 20, 2014, 03:19:30 AM »
Quote
Did you give the TNObject a unique ID? TNOs that you don't instantiate via TNManager.Create must have unique non-zero IDs.

That did the trick, thanks. Well, at least on the RFC front. The local player still seems to be the only name tag showing up in the lobby for each client but the teams are being set correctly, at least locally.
Other than just adding
  1. public int team = 0;
to the TNPlayer class, is there somewhere else I need to edit to make that persistent across the network? Or is there a way to use the data variable that says its for custom data to track the teams instead? If so, how?
« Last Edit: January 20, 2014, 01:25:10 PM by Katalyst »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #6 on: January 20, 2014, 04:35:37 PM »
Adding a field to the TNPlayer isn't going to do much. It won't be sync'd unless you sync it via RFCs. Even so, I don't recommend modifyin the TNPlayer. Have your own list of game players, referencing TNPlayer and their team within.

Katalyst

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #7 on: January 20, 2014, 09:55:37 PM »
How do I make sure everyone has the same list? I tried sending the list but all I got was:

  1. Unable to write type TNet.List`1[TNet.Player]
  2. UnityEngine.Debug:LogError(Object)
  3. TNet.UnityTools:Write(BinaryWriter, Object[]) (at Assets/TNet/Client/TNUnityTools.cs:282)
  4. TNObject:SendRFC(Byte, String, Target, Boolean, Object[]) (at Assets/TNet/Client/TNObject.cs:559)
  5. TNObject:Send(String, Target, Object[]) (at Assets/TNet/Client/TNObject.cs:429)
  6. LobbyManager:OnNetworkPlayerLeave(Player) (at Assets/Scripts/LobbyManager.cs:76)
  7. System.Reflection.MethodBase:Invoke(Object, Object[])
  8. TNet.UnityTools:Broadcast(String, Object[]) (at Assets/TNet/Client/TNUnityTools.cs:223)
  9. TNManager:OnPlayerLeft(Player) (at Assets/TNet/Client/TNManager.cs:908)
  10. TNet.GameClient:ProcessPacket(Buffer, IPEndPoint) (at Assets/TNet/Client/TNGameClient.cs:767)
  11. TNet.GameClient:ProcessPackets() (at Assets/TNet/Client/TNGameClient.cs:647)
  12. TNManager:Update() (at Assets/TNet/Client/TNManager.cs:850)

So I tried sending just the Player and ran it through a loop to populate the list and got the same error but for
  1. Unable to write type TNet.Player
  1. Unable to write type TNet.TcpProtocol

Here is what I'm doing.
  1. void OnNetworkPlayerJoin (Player p) {
  2.                 if(TNManager.isHosting) {
  3.                         //playerCount++;
  4.                         if(teamOneCount < 5) {
  5.                                 Player pn = GetPlayer(p);
  6.                                 if(pn == null) {
  7.                                         pn = p;
  8.                                         pn.team = 1;
  9.                                         teamOneCount++;
  10.                                         playersList.Add (pn);
  11.                                 }
  12.                         }
  13.                         else if(teamTwoCount < 5) {
  14.                                 Player pn = GetPlayer(p);
  15.                                 if(pn == null) {
  16.                                         pn = p;
  17.                                         pn.team = 1;
  18.                                         teamTwoCount++;
  19.                                         playersList.Add (pn);
  20.                                 }
  21.                         }
  22.                         for(int i = 0; i < playersList.size; i++) {
  23.                                 tno.Send("UpdatePlayerTeam", Target.Others, playersList[i], i);
  24.                         }
  25.                 }
  26.                 mRebuild = true;
  27.         }

  1. [RFC] void UpdatePlayerTeam(Player p, int index) {
  2.                 playersList[index] = p;
  3.                 mRebuild = true;
  4.         }

Like I said, I got an error with sending the list so I tried doing it with a loop instead. Same problem.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #8 on: January 21, 2014, 04:24:07 AM »
All players have an integer ID. That's what you should be sending, not the Player class. TNet has a limited number of types it knows how to serialize. Also, it's best to send an array. Not a TNet.List, but just an array. You can use TNet's List ToArray() function.

Katalyst

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: Set Up Teams in a Lobby
« Reply #9 on: January 22, 2014, 05:21:17 PM »
Well, after a 5 day trek of learning and discovery, I can't thank you enough for your help. I'd of been stuck here for weeks instead of days without it. I got it working using your Arrays with ID's suggestion.

I like that your responses were just enough to tell me what to work on so I can learn it as I go instead of just giving me the answer. :)

Much thanks!