diff --git a/README.md b/README.md index 2fe7343..f927bb7 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,200 @@ # Server Standard - -This is a central server and client model based server. The basis of the networking is on msgpack. works on IPv4 only at the moment. In a future release I might add IPV6 but not on any roadmap. Fully threaded and asynchrous to scale easily. - -## Library - -This is a library with a CLI attached to it to show usage. You can send and receive any data type except the standard 'Object' type - -## Usage + +This is a central server and client model based server. The basis of the networking is on msgpack. works on IPv4 only at the moment. In a future release I might add IPV6 but not on any roadmap. Fully threaded and asynchrous to scale easily. + +## Library + +This is a library with a CLI attached to it to show usage. You can send and receive any data type except the standard 'Object' type + +## Usage Follow the example listed in Program.cs inside the CLI Note: All datatypes that are sent to the server, The server needs to be aware of when in Athouritative mode. Create the server ```c# -IMistoxServer serverobj = mServer.newServer( int Port, ServerMode mode ) +ServerInterface serverobj = mServer.newServer( string serverName, int port ) ``` Create the client ```c# -IMistoxServer serverobj = mServer.newClient( string HostNameOrIP, int Port ) +ClientInterface clientobj = mServer.newClient( string HostNameOrIP, int Port ) ``` -Sending data +Sending data from the server ```c# -serverobj.Send( dynamic Object, SendType Speed ) +serverobj.SendClient( string UserName, dynamic Object ) // Sent as a TCP packet to the client +serverobj.SendAllClients( dynamic Object ) // Sent as a TCP packet to all clients ``` -Connected and Disconnected +Sending data from the client +```c# +clientobj.SendServer( dynamic Object ) // Sent as a TCP packet to the server +clientobj.SendClient( string UserName, dynamic Object ) // Sent as a UDP packet directly to the client +clientobj.SendAllClients( dynamic Object ) // Sent as a UDP packet directly to all clients +``` + +Wiring up the event handlers + +Users Connecting and Disconnecting ```c# -serverobj.onConnected += OnConnected; -serverobj.onDisconnected += OnDisconnected; -void OnConnected( object Data, EventArgs e ){ - // Sender and e are always null - // Put on connected funtions here - // such as when connected spawn a player -} -void OnDisconnected( object Data, EventArgs e ){ - // Sender and e are always null - // Put on disconnected funtions here - // such as when disconnected return to main menu -} +serverobj.onUserConnected += (TcpClientConnection connection) => { + // When a new user joins the server this fires +}; + +serverobj.onUserDisconnected += (TcpClientConnection connection) => { + // When a user leaves the server this fires +}; + +clientobj.onUserConnected += (UDPEndpoint remoteUser) => { + // When a new user joins the server this fires +}; + +clientobj.onUserDisconnected += (UDPEndpoint remoteUser) => { + // When a user leaves the server this fires +}; + +``` + +The client also gets the ability to see if the server disconnected +```c# + +clientobj.onServerConnected += () => { + // When the client establishes a connection with the server +}; + +clientobj.onServerDisconnected += () => { + // fires if the connection drops +}; + ``` Receiving data ```c# -serverobj.onSlowReceive += SlowReceivedData; -serverobj.onFastReceive += FastReceivedData; -void SlowReceivedData( object Data, EventArgs e ){ - if (Data is Datatype dt){ // Only works in Athoritative mode on server | will always work on client - - } -} -void FastReceivedData( object Data, EventArgs e ){ - if (Data is Datatype dt){ // Only works in Athoritative mode on server | will always work on client - - } -} +// When a packet is received from either the Server or another user this fires +// 'data' here can be any function tagged mPacket +// use this format as an example +serverobj.onDataReceived += (dynamic data) => { + switch (data as object) { + case UserConnectionPacket packet: + userConnected(packet); + break; + + case UserDisconnectedPacket packet: + userDisconnected(packet); + break; + + case null: + Console.WriteLine("Received a null packet."); + break; + + default: + Console.WriteLine($"Packet of type {data.GetType().Name} not accounted for"); + break; + } +}; + ``` -SendType *Enumeration +In order to send a packet you need to define the packet as an mPacket +an mPacket requires a unique ID, This ID allows the packet to be decyphered on the receving side +Therefore every mPacket requires a unique ID. The ID field is 8 bytes so the biggest number is 0xFF. - Where SlowUpdate is sent over TCP +By default the mPacket will work on both the server connection and the client connections. But due +to the limited function space you can reuse ID's if you map them out correcty because there are 2 +packet scopes as shown below. +```c# +public enum PacketUsage { + ClientToClient = 0x01, // Used only for Client To Client Connections + ClientToServer = 0x10, // Used only for Server To Client and Client To Server connections +} +// ClientToServer packets are also used for ServerToClient connections as well + +// If you would like to send a packet to both the clients and to the server you need to either use +// the base function or add the bitwise or. Some examples are listed below + +[mPacket(0x01, PacketUsage.ClientToClient)] // Exclusivly for client to client usage +[mPacket(0x01, PacketUsage.ClientToServer)] // Exclusivly for client to server usage +// These 2 packets can exist at the same time becuase the scope is different even though the packet id is already used + +[mPacket(0x02)] // This can be used for both connection types therefor the ID needs to be unique +[mPacket(0x03, PacketUsage.ClientToClient | PacketUsage.ClientToServer)] // Same as the line just before +``` - And FastUpate is sent over UDP +## Full example to tie it all together + ```c# -public enum SendType { - SlowUpdate, - FastUpdate +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Mistox; +using Mistox.Attributes; +using Mistox.Server; + +[mPacket(0x01)] +class HelloPacket { + public string Name { get; set; } = ""; } + +[mPacket(0x02, PacketUsage.ClientToServer)] +class GoodbyePacket { + public string Name { get; set; } = ""; +} + +class Main { + + ServerInterface serverobj; + List connectedUsers = new List(); + + public async Task Main(){ + serverobj = mServer.newServer( "serverName", 1234 ); + serverobj.onDataReceived += ReceiveThread; + serverobj.onUserConnected += (TcpClientConnection user) => { + connectedUsers.Add(user); + }; + serverobj.onUserDisconnected += (TcpClientConnection user) => { + connectedUsers.Add(user); + }; + + await serverobj.SendAllClients(new HelloPacket { + Name = "Jeffey" + }); + } + + void ReceiveThread(dynamic data){ + switch (data as object) { + case HelloPacket packet: + HelloWasCalled(packet); + break; + + case GoodbyePacket packet: + GoodbyeWasCalled(packet); + break; + + default: + Console.WriteLine($"Packet of type {data.GetType().Name} not accounted for"); + break; + } + } + + void HelloWasCalled(HelloPacket packet) { + connectedUsers[0].UserName = packet.Name; + } + + void GoodbyeWasCalled(GoodbyePacket packet) { + foreach(var cur in connectedUsers) { + if (cur.UserName == packet.Name) { + connectedUsers.Remove(cur); + } + } + } + +} + ``` -ServerMode *Enumeration - The Servermode tells the server if it should Deserialize examine then Reserialize the data passing through. - This can be useful to make sure data is - - 1 actually belonging to the server - - 2 the ability to keep track of objects within the server [ prevent cheating ] - - This requires alot of overhead on the server though. - - Passive doesnt use a serdes and instead just passes the data in and out - In this mode the server doesnt need to know data types - - Athoritative will Deserialize and Serialize the data - Refer to the CLI/Program.CS for reference - In this mode the server needs to know the data types being sent - Therefore you need to put all your data classes into a library and and the library to both the application and the server -```c# -public enum ServerMode { - Passive, - Authoritative -} -``` - -## Setup - -Place all your networked data types into a library -Copy the library to the application and to the server -reference the library for the networked data types ## Contributing