public void ProcessNetworkMessages()
{
//Used to store messages
NetIncomingMessage inc;
while (true) //Continously check for new messages and process them
{
//Block thread until next message
NetworkManager.NetServer.MessageReceivedEvent.WaitOne();
if ((inc = NetManager.ReadMessage()) != null)
{
//Try and find who sent the message
Player sender = inc.SenderConnection == null ?
null : Server.PlayerFromRUI(inc.SenderConnection.RemoteUniqueIdentifier, true);
switch (inc.MessageType)
{
//ConnectionApproval messages are sent when a client would like to connect to the server
case NetIncomingMessageType.ConnectionApproval:
{
MessageTypes type = (MessageTypes)Enum.Parse(typeof(MessageTypes), inc.ReadByte().ToString()); //Find message type
switch (type)
{
//If the player would like to login
case MessageTypes.Login:
{
Log.WriteLine(LogType.Server, "Login request (RUI: {0} IP: {1})",
inc.SenderConnection.RemoteUniqueIdentifier, inc.SenderEndPoint.Address); //Log message
//If the player isn't already connected, allow them to join
if (!Server.Logins.ContainsKey(inc.SenderConnection.RemoteUniqueIdentifier))
{
LoginMessage login = new LoginMessage(inc);
if (GlobalSettings.NameRegex.IsMatch(login.Username)) //Double check username is valid
{
Server.Logins.Add(inc.SenderConnection.RemoteUniqueIdentifier, login);
inc.SenderConnection.Approve();
}
else
inc.SenderConnection.Deny("Invalid Username:Kicked");
}
else
inc.SenderConnection.Deny();
break;
}
}
break;
}
//Data messages are all messages manually sent from client
//These are the bulk of the messages, used for player movement, block placing, etc
case NetIncomingMessageType.Data:
{
ProcessDataMessage(inc);
break;
}
//StatusChanged messages occur when a client connects, disconnects, is approved, etc
//NOTE: Disconnecting and Disconnected are not instant unless client is shutdown with Disconnect()
case NetIncomingMessageType.StatusChanged:
{
//Find player name
string name = Server.Logins.ContainsKey(inc.SenderConnection.RemoteUniqueIdentifier) ?
Server.Logins[inc.SenderConnection.RemoteUniqueIdentifier].Username + " (" + inc.SenderConnection.RemoteUniqueIdentifier + ")" :
"Unknown (" + inc.SenderConnection.RemoteUniqueIdentifier + ")";
//The lines below can get spammy, used to show when statuses change
//Log.WriteLine(LogType.Status, "Status: {0} changed: {1}", name, inc.SenderConnection.Status.ToString());
//When a players connection is finalized
if (inc.SenderConnection.Status == NetConnectionStatus.Connected)
{
//Log message
LoginMessage login = Server.Logins[inc.SenderConnection.RemoteUniqueIdentifier];
Log.WriteLine(LogType.Server, "User {0} authenticated (RUI: {1}, IP: {2})", login.Username, inc.SenderConnection.RemoteUniqueIdentifier, inc.SenderEndPoint.Address);
break;
}
//When a client disconnects
if (inc.SenderConnection.Status == NetConnectionStatus.Disconnected || inc.SenderConnection.Status == NetConnectionStatus.Disconnecting)
{
if (sender != null)
{
Log.WriteLine(LogType.Server, ConsoleColor.Red, "{0} disconnected. (Room: {1})", sender.Username, sender.Map.Name);
if (sender.Map.Players.Contains(sender))
{
//Remove player
sender.Map.Players.Remove(sender);
RebuildIndexes(sender.Map);
//Send to players
NetManager.Broadcast(sender.Map, new PlayerLeaveMessage(sender.ID));
sender = null;
}
}
else
{
Log.WriteLine(LogType.Server, ConsoleColor.Red, "{0} disconnected.", Server.Logins[inc.SenderConnection.RemoteUniqueIdentifier].Username);
}
Server.Logins.Remove(inc.SenderConnection.RemoteUniqueIdentifier);
}
break;
}
default:
break;
}
}
}
}
/// <summary> /// Runs/Starts the server networking /// </summary> public void Run() { IO.LoadSettings(); //Load settings //Write a welcome message Log.Write(ConsoleColor.Yellow, "Bricklayer "); Log.WriteLine("Server started on port {0} with {1} max players.", Config.Port, Config.MaxPlayers); Log.WriteBreak(); LoadPlugins(); MsgHandler = new MessageHandler(); NetManager = new NetworkManager(); //Create Networkmanager to handle networking, then start the server NetManager.Start(Config.Port, Config.MaxPlayers); //Create a PingListener to handle query requests from clients (to serve decription, players online, etc) PingListener = new PingListener(Config.Port); PingListener.Start(); //Create a default map Maps = new List <Map>(); IO.LoadMaps(); //CreateMap("Main World", "A large world for anyone to play and\nbuild! [color:SkyBlue]--Join Now!--[/color]"); Log.WriteLine(LogType.Server, "Waiting for new connections and updating world state...\n"); MsgHandler.ProcessNetworkMessages(); //Process messages for the rest of eternity }