From 08f5cdf3cdf2e6defd3071b4a6440db61e463949 Mon Sep 17 00:00:00 2001 From: teascade <teascade@gmail.com> Date: Tue, 9 May 2017 00:06:18 +0300 Subject: [PATCH] Namespace Networking and seperate Client-/Serverside --- Assets/Scripts/Networking/Client.cs | 141 -------------- Assets/Scripts/Networking/Clientside.meta | 9 + .../Scripts/Networking/Clientside/Client.cs | 142 ++++++++++++++ .../{ => Clientside}/Client.cs.meta | 0 .../Networking/Messages/TextMessage.cs | 78 ++++---- .../Scripts/Networking/NetworkEstablisher.cs | 183 +++++++++--------- Assets/Scripts/Networking/PktType.cs | 16 +- Assets/Scripts/Networking/Server.cs | 137 ------------- Assets/Scripts/Networking/Serverside.meta | 9 + .../Scripts/Networking/Serverside/Server.cs | 139 +++++++++++++ .../{ => Serverside}/Server.cs.meta | 0 11 files changed, 440 insertions(+), 414 deletions(-) delete mode 100644 Assets/Scripts/Networking/Client.cs create mode 100644 Assets/Scripts/Networking/Clientside.meta create mode 100644 Assets/Scripts/Networking/Clientside/Client.cs rename Assets/Scripts/Networking/{ => Clientside}/Client.cs.meta (100%) delete mode 100644 Assets/Scripts/Networking/Server.cs create mode 100644 Assets/Scripts/Networking/Serverside.meta create mode 100644 Assets/Scripts/Networking/Serverside/Server.cs rename Assets/Scripts/Networking/{ => Serverside}/Server.cs.meta (100%) diff --git a/Assets/Scripts/Networking/Client.cs b/Assets/Scripts/Networking/Client.cs deleted file mode 100644 index 8201b4b..0000000 --- a/Assets/Scripts/Networking/Client.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Networking; - -/// <summary> -/// Client-class used to connecting to a server and communicating to it. -/// Also handles all events incoming from the server and forwards them where they should be handled. -/// </summary> -public class Client : MonoBehaviour { - - private NetworkClient NetClient; - private bool Running = false; - - private static Client Singleton; - - /// <summary> - /// Creates the client and sets it as the signleton. - /// </summary> - public Client() { - Singleton = this; - } - - // Static interface for usage outside of Client - - /// <summary> - /// Will launch the client and attempt to connect to the server. - /// Returns false if client is already running, otherwise true. - /// - /// Generally instead of this you should use <see cref="NetworkEstablisher.StartClient(string, int)"/> - /// </summary> - /// <param name="ip"></param> - /// <param name="port"></param> - /// <returns>Weather the launch was successful or not.</returns> - public static bool Launch(string ip, int port) { - return Singleton.LaunchClient(ip, port); - } - - /// <summary> - /// Send messages to the server if the connection is active. - /// If client is not active, this will return false, otherwise true. - /// </summary> - /// <param name="msgType"></param> - /// <param name="message"></param> - /// <returns>Weather the send was successful or not.</returns> - public static bool Send(short msgType, MessageBase message) { - if (Singleton.Running) { - Singleton.NetClient.Send(msgType, message); - return true; - } - else { - return false; - } - } - - /// <summary> - /// Returns if the client is running or not. - /// This is independant weather the client is connected or not. - /// </summary> - /// <returns>Weather the client is running or not</returns> - public static bool IsRunning() { - return Singleton.Running; - } - - /// <summary> - /// Returns if the client is connected or not. - /// </summary> - /// <returns>Weather the client is connected or not.</returns> - public static bool IsConnected() { - return Singleton.NetClient.isConnected; - } - - private bool LaunchClient(string ip, int port) { - if (Running) { - return false; - } - - ConnectionConfig Config = new ConnectionConfig(); - Config.AddChannel(QosType.ReliableSequenced); - Config.AddChannel(QosType.UnreliableSequenced); - NetworkServer.Configure(Config, 10); - - NetClient = new NetworkClient(); - NetClient.Configure(Config, 10); - - Running = true; - - NetClient.RegisterHandler(PktType.TextMessage, HandlePacket); - - NetClient.RegisterHandler(MsgType.Connect, OnConnected); - NetClient.RegisterHandler(MsgType.Disconnect, OnDisconnected); - NetClient.RegisterHandler(MsgType.Error, OnError); - - NetClient.Connect(ip, port); - - Debug.Log("Client launched!"); - Term.Println("Client launched!"); - - return true; - } - - private void HandlePacket(NetworkMessage msg) { - switch (msg.msgType) { - case (PktType.TextMessage): - TextMessage TextMsg = new TextMessage(); - TextMsg.Deserialize(msg.reader); - Term.Println(TextMsg.Message); - break; - default: - Debug.LogError("Received an unknown packet, id: " + msg.msgType); - Term.Println("Received an unknown packet, id: " + msg.msgType); - break; - } - } - - // Built-in handles for some events - - private void OnConnected(NetworkMessage msg) { - Debug.Log("Connected!"); - Term.Println("Connected!"); - - Term.AddCommand("send (message)", "Send a message across the vastness of space and time!", (args) => { - Term.Println("You: " + args[0]); - NetClient.Send(PktType.TextMessage, new TextMessage("A Client: " + args[0])); - }); - } - - private void OnDisconnected(NetworkMessage msg) { - Debug.Log("Disconnected!"); - Term.Println("Disconnected!"); - Running = false; - } - - private void OnError(NetworkMessage msg) { - Debug.LogError("Encountered a network error. Shutting down."); - Term.Println("Encountered a network error. Shutting down."); - NetClient.Disconnect(); - Running = false; - } - -} diff --git a/Assets/Scripts/Networking/Clientside.meta b/Assets/Scripts/Networking/Clientside.meta new file mode 100644 index 0000000..4e4900c --- /dev/null +++ b/Assets/Scripts/Networking/Clientside.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2e91e843b32fb3e41bbe27bc2446e12c +folderAsset: yes +timeCreated: 1494276932 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Networking/Clientside/Client.cs b/Assets/Scripts/Networking/Clientside/Client.cs new file mode 100644 index 0000000..3a05916 --- /dev/null +++ b/Assets/Scripts/Networking/Clientside/Client.cs @@ -0,0 +1,142 @@ +using Cyber.Networking.Messages; +using UnityEngine; +using UnityEngine.Networking; + +namespace Cyber.Networking.Clientside { + + /// <summary> + /// Client-class used to connecting to a server and communicating to it. + /// Also handles all events incoming from the server and forwards them where they should be handled. + /// </summary> + public class Client : MonoBehaviour { + + private NetworkClient NetClient; + private bool Running = false; + + private static Client Singleton; + + /// <summary> + /// Creates the client and sets it as the signleton. + /// </summary> + public Client() { + Singleton = this; + } + + // Static interface for usage outside of Client + + /// <summary> + /// Will launch the client and attempt to connect to the server. + /// Returns false if client is already running, otherwise true. + /// + /// Generally instead of this you should use <see cref="NetworkEstablisher.StartClient(string, int)"/> + /// </summary> + /// <param name="ip"></param> + /// <param name="port"></param> + /// <returns>Weather the launch was successful or not.</returns> + public static bool Launch(string ip, int port) { + return Singleton.LaunchClient(ip, port); + } + + /// <summary> + /// Send messages to the server if the connection is active. + /// If client is not active, this will return false, otherwise true. + /// </summary> + /// <param name="msgType"></param> + /// <param name="message"></param> + /// <returns>Weather the send was successful or not.</returns> + public static bool Send(short msgType, MessageBase message) { + if (Singleton.Running) { + Singleton.NetClient.Send(msgType, message); + return true; + } + else { + return false; + } + } + + /// <summary> + /// Returns if the client is running or not. + /// This is independant weather the client is connected or not. + /// </summary> + /// <returns>Weather the client is running or not</returns> + public static bool IsRunning() { + return Singleton.Running; + } + + /// <summary> + /// Returns if the client is connected or not. + /// </summary> + /// <returns>Weather the client is connected or not.</returns> + public static bool IsConnected() { + return Singleton.NetClient.isConnected; + } + + private bool LaunchClient(string ip, int port) { + if (Running) { + return false; + } + + ConnectionConfig Config = new ConnectionConfig(); + Config.AddChannel(QosType.ReliableSequenced); + Config.AddChannel(QosType.UnreliableSequenced); + NetworkServer.Configure(Config, 10); + + NetClient = new NetworkClient(); + NetClient.Configure(Config, 10); + + Running = true; + + NetClient.RegisterHandler(PktType.TextMessage, HandlePacket); + + NetClient.RegisterHandler(MsgType.Connect, OnConnected); + NetClient.RegisterHandler(MsgType.Disconnect, OnDisconnected); + NetClient.RegisterHandler(MsgType.Error, OnError); + + NetClient.Connect(ip, port); + + Debug.Log("Client launched!"); + Term.Println("Client launched!"); + + return true; + } + + private void HandlePacket(NetworkMessage msg) { + switch (msg.msgType) { + case (PktType.TextMessage): + TextMessage TextMsg = new TextMessage(); + TextMsg.Deserialize(msg.reader); + Term.Println(TextMsg.Message); + break; + default: + Debug.LogError("Received an unknown packet, id: " + msg.msgType); + Term.Println("Received an unknown packet, id: " + msg.msgType); + break; + } + } + + // Built-in handles for some events + + private void OnConnected(NetworkMessage msg) { + Debug.Log("Connected!"); + Term.Println("Connected!"); + + Term.AddCommand("send (message)", "Send a message across the vastness of space and time!", (args) => { + Term.Println("You: " + args[0]); + NetClient.Send(PktType.TextMessage, new TextMessage("A Client: " + args[0])); + }); + } + + private void OnDisconnected(NetworkMessage msg) { + Debug.Log("Disconnected!"); + Term.Println("Disconnected!"); + Running = false; + } + + private void OnError(NetworkMessage msg) { + Debug.LogError("Encountered a network error. Shutting down."); + Term.Println("Encountered a network error. Shutting down."); + NetClient.Disconnect(); + Running = false; + } + } +} diff --git a/Assets/Scripts/Networking/Client.cs.meta b/Assets/Scripts/Networking/Clientside/Client.cs.meta similarity index 100% rename from Assets/Scripts/Networking/Client.cs.meta rename to Assets/Scripts/Networking/Clientside/Client.cs.meta diff --git a/Assets/Scripts/Networking/Messages/TextMessage.cs b/Assets/Scripts/Networking/Messages/TextMessage.cs index 33be2f1..90dae19 100644 --- a/Assets/Scripts/Networking/Messages/TextMessage.cs +++ b/Assets/Scripts/Networking/Messages/TextMessage.cs @@ -1,44 +1,46 @@ using UnityEngine.Networking; -/// <summary> -/// Generic Text Message for chat etc. -/// To be removed later when no longer necessary. -/// </summary> -public class TextMessage : MessageBase { +namespace Cyber.Networking.Messages { /// <summary> - /// Message inside the Text Message. Does not container sender information. + /// Generic Text Message for chat etc. + /// To be removed later when no longer necessary. /// </summary> - public string Message; - - /// <summary> - /// Create a TextMessage containing the message to be sent. - /// </summary> - /// <param name="message">Message to be sent.</param> - public TextMessage(string message) { - this.Message = message; + public class TextMessage : MessageBase { + + /// <summary> + /// Message inside the Text Message. Does not container sender information. + /// </summary> + public string Message; + + /// <summary> + /// Create a TextMessage containing the message to be sent. + /// </summary> + /// <param name="message">Message to be sent.</param> + public TextMessage(string message) { + this.Message = message; + } + + /// <summary> + /// Parameter-less constructor using when deserializing the message. + /// </summary> + public TextMessage() { + } + + /// <summary> + /// Used to deserialize a message received via networking. + /// </summary> + /// <param name="reader"></param> + public override void Deserialize(NetworkReader reader) { + Message = reader.ReadString(); + } + + /// <summary> + /// Used to serialize the message before it is sent. + /// </summary> + /// <param name="writer"></param> + public override void Serialize(NetworkWriter writer) { + writer.Write(Message); + } } - - /// <summary> - /// Parameter-less constructor using when deserializing the message. - /// </summary> - public TextMessage() { - } - - /// <summary> - /// Used to deserialize a message received via networking. - /// </summary> - /// <param name="reader"></param> - public override void Deserialize(NetworkReader reader) { - Message = reader.ReadString(); - } - - /// <summary> - /// Used to serialize the message before it is sent. - /// </summary> - /// <param name="writer"></param> - public override void Serialize(NetworkWriter writer) { - writer.Write(Message); - } - -} +} \ No newline at end of file diff --git a/Assets/Scripts/Networking/NetworkEstablisher.cs b/Assets/Scripts/Networking/NetworkEstablisher.cs index bc39ebb..a259c11 100644 --- a/Assets/Scripts/Networking/NetworkEstablisher.cs +++ b/Assets/Scripts/Networking/NetworkEstablisher.cs @@ -1,109 +1,112 @@ using System; -using System.Collections; -using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; +using Cyber.Networking.Clientside; +using Cyber.Networking.Serverside; -/// <summary> -/// This class is used pretty much anywhere in order to make the "first step" of networking. -/// It adds the proper components to World Root and tells them to start. -/// </summary> -public class NetworkEstablisher : MonoBehaviour { +namespace Cyber.Networking { /// <summary> - /// Input field for the IP to which connect to. + /// This class is used pretty much anywhere in order to make the "first step" of networking. + /// It adds the proper components to World Root and tells them to start. /// </summary> - [Tooltip("Required field only if StartClient() is used.")] - public InputField IPField; - /// <summary> - /// Input field for the client port - /// </summary> - [Tooltip("Required field only if StartClient() is used.")] - public InputField ClientPortField; + public class NetworkEstablisher : MonoBehaviour { - /// <summary> - /// Input field for the server port - /// </summary> - [Tooltip("Required field only if StartServer() is used.")] - public InputField ServerPortField; + /// <summary> + /// Input field for the IP to which connect to. + /// </summary> + [Tooltip("Required field only if StartClient() is used.")] + public InputField IPField; + /// <summary> + /// Input field for the client port + /// </summary> + [Tooltip("Required field only if StartClient() is used.")] + public InputField ClientPortField; - /// <summary> - /// World Root node, a GameObject. - /// </summary> - public GameObject WorldRoot; + /// <summary> + /// Input field for the server port + /// </summary> + [Tooltip("Required field only if StartServer() is used.")] + public InputField ServerPortField; - // Use this for initialization - void Start () { - Term.AddCommand("join", "joins a server at localhost:3935", (args) => { - StartClient("localhost", 3935); - }); - Term.AddCommand("join (ip)", "joins a server at given ip and port 3935", (args) => { - string ip = args[0]; - StartClient(ip, 3935); - }); - Term.AddCommand("join (ip) (port)", "joins a server at given ip and port", (args) => { - string ip = args[0]; - int port = 3935; - int.TryParse(args[1], out port); - StartClient(ip, port); - }); + /// <summary> + /// World Root node, a GameObject. + /// </summary> + public GameObject WorldRoot; - Term.AddCommand("host", "host a server at port 3935", (args) => { - StartServer(3935); - }); - Term.AddCommand("host (port)", "host a server at given port", (args) => { - int port = 3935; - int.TryParse(args[0], out port); - StartServer(port); - }); - } + // Use this for initialization + void Start () { + Term.AddCommand("join", "joins a server at localhost:3935", (args) => { + StartClient("localhost", 3935); + }); + Term.AddCommand("join (ip)", "joins a server at given ip and port 3935", (args) => { + string ip = args[0]; + StartClient(ip, 3935); + }); + Term.AddCommand("join (ip) (port)", "joins a server at given ip and port", (args) => { + string ip = args[0]; + int port = 3935; + int.TryParse(args[1], out port); + StartClient(ip, port); + }); - /// <summary> - /// Starts the client using given input fields. Otherwise functions like <see cref="StartClient(string, int)"/>. - /// </summary> - public void StartClient() { - string IP = IPField.text; - if (IP.Length == 0) { - IP = "localhost"; + Term.AddCommand("host", "host a server at port 3935", (args) => { + StartServer(3935); + }); + Term.AddCommand("host (port)", "host a server at given port", (args) => { + int port = 3935; + int.TryParse(args[0], out port); + StartServer(port); + }); } - string PortText = ClientPortField.text; - int Port = 3935; - if (PortText.Length > 0) { - Port = Int32.Parse(PortText); + + /// <summary> + /// Starts the client using given input fields. Otherwise functions like <see cref="StartClient(string, int)"/>. + /// </summary> + public void StartClient() { + string IP = IPField.text; + if (IP.Length == 0) { + IP = "localhost"; + } + string PortText = ClientPortField.text; + int Port = 3935; + if (PortText.Length > 0) { + Port = Int32.Parse(PortText); + } + StartClient(IP, Port); } - StartClient(IP, Port); - } - /// <summary> - /// Starts the client with the given ip and port. - /// This initializes the Client component and launches it properly. - /// </summary> - /// <param name="ip">IP used to connect.</param> - /// <param name="port">port of the host.</param> - public void StartClient(string ip, int port) { - WorldRoot.AddComponent<Client>(); - Client.Launch(ip, port); - } - - /// <summary> - /// Starts the server using given input fields. Otherwise functions like <see cref="StartServer(int)"/>. - /// </summary> - public void StartServer() { - string PortText = ServerPortField.text; - int Port = 3935; - if (PortText.Length > 0) { - Port = Int32.Parse(PortText); + /// <summary> + /// Starts the client with the given ip and port. + /// This initializes the Client component and launches it properly. + /// </summary> + /// <param name="ip">IP used to connect.</param> + /// <param name="port">port of the host.</param> + public void StartClient(string ip, int port) { + WorldRoot.AddComponent<Client>(); + Client.Launch(ip, port); } - StartServer(Port); - } - /// <summary> - /// Starts the server using given port. - /// This initializes the port and launches the server properly. - /// </summary> - /// <param name="port">port used for the server.</param> - public void StartServer(int port) { - WorldRoot.AddComponent<Server>(); - Server.Launch(port); + /// <summary> + /// Starts the server using given input fields. Otherwise functions like <see cref="StartServer(int)"/>. + /// </summary> + public void StartServer() { + string PortText = ServerPortField.text; + int Port = 3935; + if (PortText.Length > 0) { + Port = Int32.Parse(PortText); + } + StartServer(Port); + } + + /// <summary> + /// Starts the server using given port. + /// This initializes the port and launches the server properly. + /// </summary> + /// <param name="port">port used for the server.</param> + public void StartServer(int port) { + WorldRoot.AddComponent<Server>(); + Server.Launch(port); + } } } diff --git a/Assets/Scripts/Networking/PktType.cs b/Assets/Scripts/Networking/PktType.cs index 92f010d..90b21a0 100644 --- a/Assets/Scripts/Networking/PktType.cs +++ b/Assets/Scripts/Networking/PktType.cs @@ -1,11 +1,11 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; + +namespace Cyber.Networking { -/// <summary> -/// Types of custom created packets. -/// </summary> -public class PktType { + /// <summary> + /// Types of custom created packets. + /// </summary> + public class PktType { - public const short TextMessage = 200; + public const short TextMessage = 200; + } } \ No newline at end of file diff --git a/Assets/Scripts/Networking/Server.cs b/Assets/Scripts/Networking/Server.cs deleted file mode 100644 index cf3d7a5..0000000 --- a/Assets/Scripts/Networking/Server.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Networking; - -/// <summary> -/// Server-class used to host a server and communicate to clients. -/// </summary> -public class Server : MonoBehaviour { - - private static Server Singleton; - - /// <summary> - /// Creates the server-component, and sets the singleton as itself. - /// </summary> - public Server() { - Singleton = this; - } - - // Static methods for public usage - - /// <summary> - /// Launches the server if not already launched. - /// Returns false if the server was already launched, true otherwise. - /// - /// Generally instead of this you should use <see cref="NetworkEstablisher.StartServer(int)"/> - /// </summary> - /// <param name="port">Port used to host the server.</param> - /// <returns>Weather the launch was successful.</returns> - public static bool Launch(int port) { - return Singleton.LaunchServer(port); - } - - /// <summary> - /// Attempts to send a message to all clients who are listening. - /// Returns false if server wasn't active, true otherwise. - /// </summary> - /// <param name="msgType">Type of the message being sent.</param> - /// <param name="message">The message being sent.</param> - /// <returns>Weather sending was successful.</returns> - public static bool SendToAll(short msgType, MessageBase message) { - if (NetworkServer.active) { - NetworkServer.SendToAll(msgType, message); - return true; - } - else { - return false; - } - } - - /// <summary> - /// Attempts to send a message to a specific client. - /// Returns false if server wasn't active, true otherwise. - /// </summary> - /// <param name="clientID">ID of the client which to send this message.</param> - /// <param name="msgType">Type of message being sent.</param> - /// <param name="message">The message being sent.</param> - /// <returns>Weather sending was successful.</returns> - public static bool Send(int clientID, short msgType, MessageBase message) { - if (NetworkServer.active) { - NetworkServer.SendToClient(clientID, msgType, message); - return true; - } - else { - return false; - } - } - - /// <summary> - /// Is the server currently active. - /// </summary> - /// <returns>Weather the server is running or not</returns> - public static bool IsRunning() { - return NetworkServer.active; - } - - private bool LaunchServer(int port) { - if (NetworkServer.active) { - return false; - } - - ConnectionConfig Config = new ConnectionConfig(); - Config.AddChannel(QosType.ReliableSequenced); - Config.AddChannel(QosType.UnreliableSequenced); - NetworkServer.Configure(Config, 10); - - NetworkServer.Listen(port); - - NetworkServer.RegisterHandler(PktType.TextMessage, HandlePacket); - - NetworkServer.RegisterHandler(MsgType.Connect, OnConnected); - NetworkServer.RegisterHandler(MsgType.Disconnect, OnDisconnected); - NetworkServer.RegisterHandler(MsgType.Error, OnError); - - Debug.Log("Server started on port " + port); - Term.Println("Server started on port " + port); - - Term.AddCommand("send (message)", "Howl at the darkness of space. Does it echo though?", (args) => { - Term.Println("You: " + args[0]); - SendToAll(PktType.TextMessage, new TextMessage("Server: " + args[0])); - }); - - return true; - } - - private void HandlePacket(NetworkMessage msg) { - - switch(msg.msgType) { - case PktType.TextMessage: - TextMessage TextMsg = new TextMessage(); - TextMsg.Deserialize(msg.reader); - Term.Println(TextMsg.Message); - break; - default: - Debug.LogError("Received an unknown packet, id: " + msg.msgType); - Term.Println("Received an unknown packet, id: " + msg.msgType); - break; - } - } - - // Internal built-in event handler - - private void OnConnected(NetworkMessage msg) { - Debug.Log("Someone connected!"); - Term.Println("Someone connected!"); - } - - private void OnDisconnected(NetworkMessage msg) { - Debug.Log("Someone disconnected."); - Term.Println("Someone disconnected."); - } - - private void OnError(NetworkMessage msg) { - Debug.LogError("Encountered a network error on server"); - Term.Println("Encountered a network error on server"); - } -} diff --git a/Assets/Scripts/Networking/Serverside.meta b/Assets/Scripts/Networking/Serverside.meta new file mode 100644 index 0000000..dd71434 --- /dev/null +++ b/Assets/Scripts/Networking/Serverside.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 07f9f599ce8d74247ae4ab534cc671af +folderAsset: yes +timeCreated: 1494276932 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Networking/Serverside/Server.cs b/Assets/Scripts/Networking/Serverside/Server.cs new file mode 100644 index 0000000..9820d17 --- /dev/null +++ b/Assets/Scripts/Networking/Serverside/Server.cs @@ -0,0 +1,139 @@ +using Cyber.Networking.Messages; +using UnityEngine; +using UnityEngine.Networking; + +namespace Cyber.Networking.Serverside { + + /// <summary> + /// Server-class used to host a server and communicate to clients. + /// </summary> + public class Server : MonoBehaviour { + + private static Server Singleton; + + /// <summary> + /// Creates the server-component, and sets the singleton as itself. + /// </summary> + public Server() { + Singleton = this; + } + + // Static methods for public usage + + /// <summary> + /// Launches the server if not already launched. + /// Returns false if the server was already launched, true otherwise. + /// + /// Generally instead of this you should use <see cref="NetworkEstablisher.StartServer(int)"/> + /// </summary> + /// <param name="port">Port used to host the server.</param> + /// <returns>Weather the launch was successful.</returns> + public static bool Launch(int port) { + return Singleton.LaunchServer(port); + } + + /// <summary> + /// Attempts to send a message to all clients who are listening. + /// Returns false if server wasn't active, true otherwise. + /// </summary> + /// <param name="msgType">Type of the message being sent.</param> + /// <param name="message">The message being sent.</param> + /// <returns>Weather sending was successful.</returns> + public static bool SendToAll(short msgType, MessageBase message) { + if (NetworkServer.active) { + NetworkServer.SendToAll(msgType, message); + return true; + } + else { + return false; + } + } + + /// <summary> + /// Attempts to send a message to a specific client. + /// Returns false if server wasn't active, true otherwise. + /// </summary> + /// <param name="clientID">ID of the client which to send this message.</param> + /// <param name="msgType">Type of message being sent.</param> + /// <param name="message">The message being sent.</param> + /// <returns>Weather sending was successful.</returns> + public static bool Send(int clientID, short msgType, MessageBase message) { + if (NetworkServer.active) { + NetworkServer.SendToClient(clientID, msgType, message); + return true; + } + else { + return false; + } + } + + /// <summary> + /// Is the server currently active. + /// </summary> + /// <returns>Weather the server is running or not</returns> + public static bool IsRunning() { + return NetworkServer.active; + } + + private bool LaunchServer(int port) { + if (NetworkServer.active) { + return false; + } + + ConnectionConfig Config = new ConnectionConfig(); + Config.AddChannel(QosType.ReliableSequenced); + Config.AddChannel(QosType.UnreliableSequenced); + NetworkServer.Configure(Config, 10); + + NetworkServer.Listen(port); + + NetworkServer.RegisterHandler(PktType.TextMessage, HandlePacket); + + NetworkServer.RegisterHandler(MsgType.Connect, OnConnected); + NetworkServer.RegisterHandler(MsgType.Disconnect, OnDisconnected); + NetworkServer.RegisterHandler(MsgType.Error, OnError); + + Debug.Log("Server started on port " + port); + Term.Println("Server started on port " + port); + + Term.AddCommand("send (message)", "Howl at the darkness of space. Does it echo though?", (args) => { + Term.Println("You: " + args[0]); + SendToAll(PktType.TextMessage, new TextMessage("Server: " + args[0])); + }); + + return true; + } + + private void HandlePacket(NetworkMessage msg) { + + switch (msg.msgType) { + case PktType.TextMessage: + TextMessage TextMsg = new TextMessage(); + TextMsg.Deserialize(msg.reader); + Term.Println(TextMsg.Message); + break; + default: + Debug.LogError("Received an unknown packet, id: " + msg.msgType); + Term.Println("Received an unknown packet, id: " + msg.msgType); + break; + } + } + + // Internal built-in event handler + + private void OnConnected(NetworkMessage msg) { + Debug.Log("Someone connected!"); + Term.Println("Someone connected!"); + } + + private void OnDisconnected(NetworkMessage msg) { + Debug.Log("Someone disconnected."); + Term.Println("Someone disconnected."); + } + + private void OnError(NetworkMessage msg) { + Debug.LogError("Encountered a network error on server"); + Term.Println("Encountered a network error on server"); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Networking/Server.cs.meta b/Assets/Scripts/Networking/Serverside/Server.cs.meta similarity index 100% rename from Assets/Scripts/Networking/Server.cs.meta rename to Assets/Scripts/Networking/Serverside/Server.cs.meta