mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
423 lines
15 KiB
C#
423 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.IO;
|
|
using SS3d_server.Modules.Client;
|
|
using SS3d_server.Modules.Map;
|
|
using SS3d_server.Modules.Items;
|
|
using SS3d_server.Modules.Mobs;
|
|
|
|
using Lidgren.Network;
|
|
using SS3D_shared;
|
|
|
|
namespace SS3d_server
|
|
{
|
|
public class SS3DNetserver
|
|
{
|
|
public NetServer netServer;
|
|
NetPeerConfiguration netConfig = new NetPeerConfiguration("SS3D_NetTag");
|
|
public Dictionary<NetConnection, Client> clientList = new Dictionary<NetConnection, Client>();
|
|
Map map;
|
|
ItemManager itemManager;
|
|
MobManager mobManager;
|
|
|
|
bool active = false;
|
|
|
|
#region Server Settings
|
|
string dataFilename = "ServerSettings.cfg";
|
|
Dictionary<string, string> serverSettings = new Dictionary<string, string>();
|
|
int serverPort = 1212;
|
|
string serverName = "SS3D Server";
|
|
string serverMapName = "SavedMap";
|
|
string serverWelcomeMessage = "Welcome to the server!";
|
|
int serverMaxPlayers = 32;
|
|
GameType gameType = GameType.Game;
|
|
#endregion
|
|
|
|
public void InitModules()
|
|
{
|
|
map = new Map();
|
|
map.InitMap(serverMapName);
|
|
|
|
itemManager = new ItemManager(this, map);
|
|
mobManager = new MobManager(this, map);
|
|
}
|
|
|
|
public bool Start()
|
|
{
|
|
try
|
|
{
|
|
LoadDataFile(dataFilename);
|
|
LoadSettings();
|
|
InitModules();
|
|
netConfig.Port = serverPort;
|
|
netServer = new NetServer(netConfig);
|
|
netServer.Start();
|
|
active = true;
|
|
return false;
|
|
}
|
|
catch
|
|
{
|
|
active = false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public void ProcessPackets()
|
|
{
|
|
try
|
|
{
|
|
NetIncomingMessage msg;
|
|
while ((msg = netServer.ReadMessage()) != null)
|
|
{
|
|
Console.Title = netServer.Statistics.SentBytes.ToString() + " " + netServer.Statistics.ReceivedBytes;
|
|
switch (msg.MessageType)
|
|
{
|
|
case NetIncomingMessageType.VerboseDebugMessage:
|
|
Console.WriteLine(msg.ReadString());
|
|
break;
|
|
|
|
case NetIncomingMessageType.DebugMessage:
|
|
Console.WriteLine(msg.ReadString());
|
|
break;
|
|
|
|
case NetIncomingMessageType.WarningMessage:
|
|
Console.WriteLine(msg.ReadString());
|
|
break;
|
|
|
|
case NetIncomingMessageType.ErrorMessage:
|
|
Console.WriteLine(msg.ReadString());
|
|
break;
|
|
|
|
case NetIncomingMessageType.Data:
|
|
if (clientList.ContainsKey(msg.SenderConnection))
|
|
{
|
|
HandleData(msg);
|
|
}
|
|
break;
|
|
|
|
case NetIncomingMessageType.StatusChanged:
|
|
HandleStatusChanged(msg);
|
|
break;
|
|
|
|
default:
|
|
Console.WriteLine("Unhandled type: " + msg.MessageType);
|
|
break;
|
|
}
|
|
netServer.Recycle(msg);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
itemManager.Update();
|
|
mobManager.Update();
|
|
}
|
|
|
|
public bool Active
|
|
{
|
|
get { return active; }
|
|
}
|
|
|
|
public void ShutDown()
|
|
{
|
|
|
|
}
|
|
|
|
public void HandleConnectionApproval(NetConnection sender)
|
|
{
|
|
clientList.Add(sender, new Client(sender));
|
|
}
|
|
|
|
public void SendWelcomeInfo(NetConnection connection)
|
|
{
|
|
NetOutgoingMessage welcomeMessage = netServer.CreateMessage();
|
|
welcomeMessage.Write((byte)NetMessage.WelcomeMessage);
|
|
welcomeMessage.Write(serverName);
|
|
welcomeMessage.Write(serverPort);
|
|
welcomeMessage.Write(serverWelcomeMessage);
|
|
welcomeMessage.Write(serverMaxPlayers);
|
|
welcomeMessage.Write(serverMapName);
|
|
welcomeMessage.Write((byte)gameType);
|
|
netServer.SendMessage(welcomeMessage, connection, NetDeliveryMethod.ReliableOrdered);
|
|
SendNewPlayerCount();
|
|
}
|
|
|
|
public void SendNewPlayerCount()
|
|
{
|
|
NetOutgoingMessage playercountMessage = netServer.CreateMessage();
|
|
playercountMessage.Write((byte)NetMessage.PlayerCount);
|
|
playercountMessage.Write((byte)clientList.Count);
|
|
foreach (NetConnection conn in clientList.Keys)
|
|
{
|
|
netServer.SendMessage(playercountMessage, conn, NetDeliveryMethod.ReliableOrdered);
|
|
}
|
|
}
|
|
|
|
public void HandleStatusChanged(NetIncomingMessage msg)
|
|
{
|
|
NetConnection sender = msg.SenderConnection;
|
|
string senderIP = sender.RemoteEndpoint.Address.ToString();
|
|
Console.WriteLine(senderIP + ": Status change");
|
|
|
|
if (sender.Status == NetConnectionStatus.Connected)
|
|
{
|
|
Console.WriteLine(senderIP + ": Connection request");
|
|
if (clientList.ContainsKey(sender))
|
|
{
|
|
Console.WriteLine(senderIP + ": Already connected");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
HandleConnectionApproval(sender);
|
|
}
|
|
// Send map
|
|
}
|
|
else if (sender.Status == NetConnectionStatus.Disconnected)
|
|
{
|
|
Console.WriteLine(senderIP + ": Disconnected");
|
|
|
|
mobManager.DeletePlayer(sender);
|
|
|
|
if (clientList.ContainsKey(sender))
|
|
{
|
|
clientList.Remove(sender);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public void HandleData(NetIncomingMessage msg)
|
|
{
|
|
NetMessage messageType = (NetMessage)msg.ReadByte();
|
|
/*if (messageType != NetMessage.MobMessage)
|
|
{
|
|
//Console.WriteLine(msg.SenderConnection.RemoteEndpoint.Address.ToString() + ": " + messageType.ToString());
|
|
}*/
|
|
switch (messageType)
|
|
{
|
|
case NetMessage.WelcomeMessage:
|
|
SendWelcomeInfo(msg.SenderConnection);
|
|
break;
|
|
case NetMessage.SendMap:
|
|
SendMap(msg.SenderConnection);
|
|
break;
|
|
case NetMessage.ChangeTile:
|
|
HandleChangeTile(msg);
|
|
break;
|
|
case NetMessage.LobbyChat:
|
|
HandleLobbyChat(msg);
|
|
break;
|
|
case NetMessage.ClientName:
|
|
HandleClientName(msg);
|
|
break;
|
|
case NetMessage.ItemMessage:
|
|
itemManager.HandleNetMessage(msg);
|
|
break;
|
|
case NetMessage.MobMessage:
|
|
mobManager.HandleNetMessage(msg);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
public void HandleClientName(NetIncomingMessage msg)
|
|
{
|
|
string name = msg.ReadString();
|
|
clientList[msg.SenderConnection].SetName(name);
|
|
}
|
|
|
|
public void HandleLobbyChat(NetIncomingMessage msg)
|
|
{
|
|
string text = clientList[msg.SenderConnection].playerName + ": ";
|
|
text += msg.ReadString();
|
|
SendLobbyChat(text);
|
|
}
|
|
|
|
public void SendLobbyChat(string text)
|
|
{
|
|
NetOutgoingMessage chatMessage = netServer.CreateMessage();
|
|
chatMessage.Write((byte)NetMessage.LobbyChat);
|
|
chatMessage.Write(text);
|
|
foreach (NetConnection connection in clientList.Keys)
|
|
{
|
|
netServer.SendMessage(chatMessage, connection, NetDeliveryMethod.Unreliable);
|
|
}
|
|
}
|
|
|
|
// The size of the map being sent is almost exaclty 1 byte per tile.
|
|
// The default 30x30 map is 900 bytes, a 100x100 one is 10,000 bytes (10kb).
|
|
public void SendMap(NetConnection connection)
|
|
{
|
|
Console.WriteLine(connection.RemoteEndpoint.Address.ToString() + ": Sending map");
|
|
NetOutgoingMessage mapMessage = netServer.CreateMessage();
|
|
mapMessage.Write((byte)NetMessage.SendMap);
|
|
|
|
TileType[,] mapObjectTypes = map.GetMapForSending();
|
|
int mapWidth = map.GetMapWidth();
|
|
int mapHeight = map.GetMapHeight();
|
|
|
|
mapMessage.Write(mapWidth);
|
|
mapMessage.Write(mapHeight);
|
|
|
|
for (int x = 0; x < mapWidth; x++)
|
|
{
|
|
for (int z = 0; z < mapHeight; z++)
|
|
{
|
|
mapMessage.Write((byte)mapObjectTypes[x, z]);
|
|
}
|
|
}
|
|
|
|
netServer.SendMessage(mapMessage, connection, NetDeliveryMethod.ReliableOrdered);
|
|
Console.WriteLine(connection.RemoteEndpoint.Address.ToString() + ": Sending map finished with message size: " + mapMessage.LengthBytes + " bytes");
|
|
|
|
// Lets also send them all the items.
|
|
itemManager.NewPlayer(connection);
|
|
mobManager.NewPlayer(connection);
|
|
}
|
|
|
|
public void HandleChangeTile(NetIncomingMessage msg)
|
|
{
|
|
Console.WriteLine(msg.SenderConnection.RemoteEndpoint.Address.ToString() + ": Tile Change Recieved");
|
|
|
|
int x = msg.ReadInt32();
|
|
int z = msg.ReadInt32();
|
|
TileType newType = (TileType)msg.ReadByte();
|
|
if (map.ChangeTile(x, z, newType))
|
|
{
|
|
SendChangeTile(x, z, newType);
|
|
}
|
|
}
|
|
|
|
public void SendChangeTile(int x, int z, TileType newType)
|
|
{
|
|
NetOutgoingMessage tileMessage = netServer.CreateMessage();
|
|
tileMessage.Write((byte)NetMessage.ChangeTile);
|
|
tileMessage.Write(x);
|
|
tileMessage.Write(z);
|
|
tileMessage.Write((byte)newType);
|
|
foreach(NetConnection connection in clientList.Keys)
|
|
{
|
|
netServer.SendMessage(tileMessage, connection, NetDeliveryMethod.ReliableOrdered);
|
|
Console.WriteLine(connection.RemoteEndpoint.Address.ToString() + ": Tile Change Being Sent");
|
|
}
|
|
}
|
|
|
|
private void LoadDataFile(string filename)
|
|
{
|
|
serverSettings = new Dictionary<string, string>();
|
|
|
|
if (!File.Exists(filename))
|
|
{
|
|
WriteNewDataFile();
|
|
}
|
|
|
|
FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
|
StreamReader sr = new StreamReader(file);
|
|
|
|
string line = sr.ReadLine();
|
|
while (line != null)
|
|
{
|
|
string[] args = line.Split("=".ToCharArray());
|
|
if (args.Length == 2 && line[0] != '#')
|
|
{
|
|
serverSettings[args[0].Trim()] = args[1].Trim();
|
|
}
|
|
line = sr.ReadLine();
|
|
}
|
|
|
|
sr.Close();
|
|
file.Close();
|
|
|
|
}
|
|
|
|
public void LoadSettings()
|
|
{
|
|
if(serverSettings.ContainsKey("Port"))
|
|
{
|
|
serverPort = int.Parse(serverSettings["Port"]);
|
|
}
|
|
Console.WriteLine("Port: " + serverPort);
|
|
if (serverSettings.ContainsKey("Name"))
|
|
{
|
|
serverName = serverSettings["Name"];
|
|
}
|
|
Console.WriteLine("Name: " + serverName);
|
|
if (serverSettings.ContainsKey("MapName"))
|
|
{
|
|
serverMapName = serverSettings["MapName"];
|
|
}
|
|
Console.WriteLine("Map: " + serverMapName);
|
|
if (serverSettings.ContainsKey("MaxPlayers"))
|
|
{
|
|
serverMaxPlayers = int.Parse(serverSettings["MaxPlayers"]);
|
|
}
|
|
Console.WriteLine("Max players: " + serverMaxPlayers);
|
|
if (serverSettings.ContainsKey("GameType"))
|
|
{
|
|
gameType = (GameType)byte.Parse(serverSettings["GameType"]);
|
|
}
|
|
Console.WriteLine("Game type: " + gameType);
|
|
if (serverSettings.ContainsKey("WelcomeMessage"))
|
|
{
|
|
serverWelcomeMessage = serverSettings["WelcomeMessage"];
|
|
}
|
|
Console.WriteLine("Welcome message: " + serverWelcomeMessage);
|
|
}
|
|
|
|
public void WriteNewDataFile()
|
|
{
|
|
Console.WriteLine("ServerSettings.config not found. Generating default file.");
|
|
FileStream fs = new FileStream(dataFilename, FileMode.Create);
|
|
StreamWriter sw = new StreamWriter(fs);
|
|
|
|
sw.WriteLine("#Server name");
|
|
sw.WriteLine("Name=" + serverName);
|
|
sw.WriteLine("#Server Port");
|
|
sw.WriteLine("Port=" + serverPort);
|
|
sw.WriteLine("#Welcome message to send to clients on connect");
|
|
sw.WriteLine("WelcomeMessage=" + serverWelcomeMessage);
|
|
sw.WriteLine("#Game Type: 0 = Map editor, 1 = Game");
|
|
sw.WriteLine("GameType=" + (byte)gameType);
|
|
sw.WriteLine("#The name of the file containing the map to load");
|
|
sw.WriteLine("MapName=" + serverMapName);
|
|
sw.WriteLine("#The max number of players allowed");
|
|
sw.WriteLine("MaxPlayers=" + serverMaxPlayers);
|
|
sw.Close();
|
|
fs.Close();
|
|
}
|
|
|
|
public void SendMessageToAll(NetOutgoingMessage message)
|
|
{
|
|
if (message == null)
|
|
{
|
|
return;
|
|
}
|
|
int i = clientList.Count;
|
|
//Console.WriteLine("Sending to all ("+i+") with size: " + message.LengthBits + " bytes");
|
|
foreach (Client client in clientList.Values)
|
|
{
|
|
netServer.SendMessage(message, client.netConnection, NetDeliveryMethod.ReliableOrdered);
|
|
}
|
|
}
|
|
|
|
public void SendMessageTo(NetOutgoingMessage message, NetConnection connection)
|
|
{
|
|
if (message == null || connection == null)
|
|
{
|
|
return;
|
|
}
|
|
Console.WriteLine("Sending to one with size: " + message.LengthBytes + " bytes");
|
|
netServer.SendMessage(message, connection, NetDeliveryMethod.ReliableOrdered);
|
|
}
|
|
}
|
|
}
|