Update ReadMe

This commit is contained in:
derek committed 2026-07-03 17:46:22 -07:00
1 parent 392a33eb9e
commit 531fd2572f
1 file changed
+159 -65
+159 -65
View File
@@ -13,94 +13,188 @@ Note: All datatypes that are sent to the server, The server needs to be aware of
Create the server Create the server
```c# ```c#
IMistoxServer serverobj = mServer.newServer( int Port, ServerMode mode ) ServerInterface serverobj = mServer.newServer( string serverName, int port )
``` ```
Create the client Create the client
```c# ```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# ```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# ```c#
serverobj.onConnected += OnConnected; serverobj.onUserConnected += (TcpClientConnection connection) => {
serverobj.onDisconnected += OnDisconnected; // When a new user joins the server this fires
void OnConnected( object Data, EventArgs e ){ };
// Sender and e are always null
// Put on connected funtions here serverobj.onUserDisconnected += (TcpClientConnection connection) => {
// such as when connected spawn a player // When a user leaves the server this fires
} };
void OnDisconnected( object Data, EventArgs e ){
// Sender and e are always null clientobj.onUserConnected += (UDPEndpoint remoteUser) => {
// Put on disconnected funtions here // When a new user joins the server this fires
// such as when disconnected return to main menu };
}
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 Receiving data
```c# ```c#
serverobj.onSlowReceive += SlowReceivedData; // When a packet is received from either the Server or another user this fires
serverobj.onFastReceive += FastReceivedData; // 'data' here can be any function tagged mPacket
void SlowReceivedData( object Data, EventArgs e ){ // use this format as an example
if (Data is Datatype dt){ // Only works in Athoritative mode on server | will always work on client 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;
} }
} };
void FastReceivedData( object Data, EventArgs e ){
if (Data is Datatype dt){ // Only works in Athoritative mode on server | will always work on client
```
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.
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
```
## Full example to tie it all together
```c#
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<TcpClientConnection> connectedUsers = new List<TcpClientConnection>();
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);
}
}
}
} }
``` ```
SendType *Enumeration
Where SlowUpdate is sent over TCP
And FastUpate is sent over UDP
```c#
public enum SendType {
SlowUpdate,
FastUpdate
}
```
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 ## Contributing