|
|
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- using UnityEngine.Networking;
-
- namespace Networking.Server
- {
- [CreateAssetMenu(menuName = "Major Project/Networking/ClientList", order = 150)]
- public class ClientList : ScriptableObject, IEnumerable<ClientData>
- {
-
- #if UNITY_EDITOR
-
- [SerializeField]
- [Multiline]
- private string DevNotes;
-
- #endif
-
- [SerializeField]
- private Inventory StartInventory;
-
- #region Public Variables
- /// <summary>
- /// All Clients which are Currently Connected;
- /// </summary>
- public List<ClientData> ConnectedClients;
-
-
- /// <summary>
- /// Clients which connected at one point but no longer are
- /// Usefull if a client needs to reconnect
- /// </summary>
- public List<ClientData> DisconnectedClients;
-
-
- private List<NetworkConnection> PotentialClients = new List<NetworkConnection>();
-
- /// <summary>
- /// Called when a client connects or disconnet
- /// </summary>
- public System.Action<List<ClientData>> OnClientsChange;
-
-
- #endregion Public Variables
-
- #region Private Variables
- public ServerObject server;
- #endregion Private Variables
-
-
- /// <summary>
- /// Clears the lists
- /// </summary>
- public void Reset()
- {
- ConnectedClients = new List<ClientData>();
- DisconnectedClients = new List<ClientData>();
- PotentialClients = new List<NetworkConnection>();
- }
-
- /// <summary>
- /// Resets the client list + registers handlers with the server
- /// </summary>
- /// <param name="serverObject">Server to register handlers with</param>
- public void SetUp(ServerObject serverObject)
- {
- this.server = serverObject;
- Reset();
- server.RegisterHandler(MsgType.Connect, OnClientConnect);
- server.RegisterHandler(MsgType.Disconnect, OnClientDisconnect);
- server.RegisterHandler(LoginProtocols.SendingLoginDetails, OnClientLogin);
- }
-
- public void OnClientConnect(NetworkMessage msg)
- {
-
- //Debug.Log("newClient: " + msg.conn.address + ", " + msg.conn.Hash() + ", " + msg.conn.hostId);
-
- if (ConnectedClients.Any(p => p.ID == msg.channelId))
- {
- Debug.LogError("Client[" + msg.channelId + "] already connected");
- msg.conn.Send(LoginProtocols.LoginFail, new LoginProtocols.EmptyMsg());
- return;
- }
-
- if (!PotentialClients.Contains(msg.conn))
- PotentialClients.Add(msg.conn);
-
- msg.conn.Send(LoginProtocols.RequestLoginDetails, new LoginProtocols.EmptyMsg());
- ConnectedClients.ForEach(p => msg.conn.Send(LoginProtocols.OtherClientConnected, new LoginProtocols.LoginMsg(p.Name, p.Color, p.characterAnimal)));
- }
-
- public void OnClientDisconnect(NetworkMessage msg)
- {
- PotentialClients.RemoveAll(p => p == msg.conn);
-
- if (!ConnectedClients.Any(p => p.ID == msg.conn.Hash()))
- {
- Debug.LogError("Unknown client disconnect [" + msg.conn.Hash() + "]");
- return;
- }
-
- ClientData client = ConnectedClients.FirstOrDefault(p => p.ID == msg.conn.Hash());
-
- client.Lives = 0;
- if (client.playerCharacter != null)
- {
- client.playerCharacter.lives = 0;
- }
- ConnectedClients.Remove(client);
- DisconnectedClients.Add(client);
-
- ConnectedClients.ForEach(p => p.conn.Send(LoginProtocols.OtherClientDisconnected, new LoginProtocols.LoginMsg(client.Name, client.Color, client.characterAnimal)));
- PotentialClients.ForEach(p => p.Send(LoginProtocols.OtherClientDisconnected, new LoginProtocols.LoginMsg(client.Name, client.Color, client.characterAnimal)));
- Debug.Log("Disconnected: " + client.Name);
- //somewhere here we need to remove the disconnected client from the client list and update such things
- OnClientsChange?.Invoke(ConnectedClients);
- }
-
- public void OnClientLogin(NetworkMessage msg)
- {
- LoginProtocols.LoginMsg loginMsg;
- if (!msg.TryRead(out loginMsg))
- {
- msg.conn.Send(LoginProtocols.LoginFail, new LoginProtocols.EmptyMsg());
- return;
- }
-
-
-
- if (ConnectedClients.Any(p => p.ID == msg.conn.Hash()))
- {
- Debug.LogError("Client[" + msg.channelId + "] already connected");
- msg.conn.Send(LoginProtocols.LoginFail, new LoginProtocols.EmptyMsg());
- return;
- }
-
- ClientData newClient = DisconnectedClients.FirstOrDefault(p => p.ID == msg.conn.Hash());
- if (newClient != default)
- {
- Debug.Log("Reconnection: " + loginMsg.Name + ((loginMsg.Name != newClient.Name) ? (" (Prev. " + newClient.Name +")") : ""));
- DisconnectedClients.Remove(newClient);
- }
- else
- {
- //Debug.Log("new Connection: " + loginMsg.Name);
- newClient = new ClientData();
- newClient.Inventory = Inventory.Clone(StartInventory);
- }
-
- newClient.Color = loginMsg.Color;
- newClient.characterAnimal = loginMsg.Animal;
- newClient.Name = loginMsg.Name;
- newClient.conn = msg.conn;
-
-
-
- ConnectedClients.Add(newClient);
- ConnectedClients.ForEach(p => p.conn.Send(LoginProtocols.OtherClientConnected, new LoginProtocols.LoginMsg(newClient.Name, newClient.Color, newClient.characterAnimal)));
- PotentialClients.RemoveAll(p => p == newClient.conn);
- PotentialClients.ForEach(p => p.Send(LoginProtocols.OtherClientConnected, new LoginProtocols.LoginMsg(newClient.Name, newClient.Color, newClient.characterAnimal)));
-
- newClient.conn.Send(LoginProtocols.LoginSuccess, new LoginProtocols.LoginMsg(newClient.Name, newClient.Color, newClient.characterAnimal));
- OnClientsChange.Invoke(ConnectedClients);
- newClient.SendInventory();
- newClient.SendLives();
- newClient.ChangeScene("LobbyWait");
- }
-
-
- #region IEnumerable Implementation
- public IEnumerator<ClientData> GetEnumerator()
- {
- return ((IEnumerable<ClientData>)ConnectedClients).GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable<ClientData>)ConnectedClients).GetEnumerator();
- }
- #endregion IEnumerable Implementation
-
- /// <summary>
- /// Returns client with id
- /// </summary>
- /// <param name="id">id to find client with</param>
- /// <returns>client with provided id else null</returns>
- public ClientData this[int id] {
- get {
- return ConnectedClients.FirstOrDefault(p => p.ID == id);
- }
- }
- }
-
- [System.Serializable]
- public class ClientData
- {
- /// <summary>
- /// Client Name
- /// </summary>
- public string Name;
-
- /// <summary>
- /// Color which represents player, picked by player
- /// </summary>
- public Color Color;
-
- /// <summary>
- /// Clients Current Score
- /// </summary>
- public int Score;
-
- /// <summary>
- /// Clients Current Lives
- /// </summary>
- public int Lives = 3;
-
- /// <summary>
- /// Clients character animal - needed for instantiation
- /// </summary>
- public string characterAnimal = "Bear";
-
- /// <summary>
- /// Network connection ID
- /// </summary>
- public int ID { get { return (conn != null) ? conn.Hash() : -1; }}
-
- /// <summary>
- /// Connection to Client
- /// </summary>
- public NetworkConnection conn;
-
- /// <summary>
- /// Current Logic elements held by player
- /// </summary>
- public Inventory Inventory;
-
- public Character playerCharacter;
-
- public void SendInventory()
- {
- //Debug.Log("Sending inventory");
- conn.SendByChannel(LogicProtocols.SendInventory, new LogicProtocols.InventoryMsg(Inventory), TransportConfigure.ReliableFragmented);
- }
-
- public void SendLives()
- {
- conn.Send(LogicProtocols.SendLives, new LogicProtocols.FloatMsg(Lives));
- }
-
- public void ChangeScene(string scene, bool Additive = false)
- {
- conn.Send(LoginProtocols.SceneChange, new LoginProtocols.SceneMsg(scene,Additive));
- }
- }
- }
|