First commit
This commit is contained in:
@@ -0,0 +1,384 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Subsurface.Networking
|
||||
{
|
||||
|
||||
|
||||
class GameClient : NetworkMember
|
||||
{
|
||||
NetClient Client;
|
||||
|
||||
private Character myCharacter;
|
||||
private CharacterInfo characterInfo;
|
||||
|
||||
string name;
|
||||
|
||||
// Create timer that tells client, when to send update
|
||||
// System.Timers.Timer update;
|
||||
|
||||
public Character Character
|
||||
{
|
||||
get { return myCharacter; }
|
||||
set { myCharacter = value; }
|
||||
}
|
||||
|
||||
public CharacterInfo CharacterInfo
|
||||
{
|
||||
get { return characterInfo; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return;
|
||||
name = value;
|
||||
}
|
||||
}
|
||||
|
||||
public GameClient(string name)
|
||||
{
|
||||
this.name = name;
|
||||
|
||||
this.characterInfo = new CharacterInfo("Content/Characters/Human/human.xml", name);
|
||||
}
|
||||
|
||||
public bool ConnectToServer(string hostIP)
|
||||
{
|
||||
myCharacter = Character.Controlled;
|
||||
|
||||
// Create new instance of configs. Parameter is "application Id". It has to be same on client and server.
|
||||
NetPeerConfiguration Config = new NetPeerConfiguration("subsurface");
|
||||
|
||||
//Config.SimulatedLoss = 0.2f;
|
||||
//Config.SimulatedMinimumLatency = 0.25f;
|
||||
|
||||
// Create new client, with previously created configs
|
||||
Client = new NetClient(Config);
|
||||
|
||||
NetOutgoingMessage outmsg = Client.CreateMessage();
|
||||
Client.Start();
|
||||
|
||||
outmsg.Write((byte)PacketTypes.Login);
|
||||
outmsg.Write(Game1.version.ToString());
|
||||
outmsg.Write(name);
|
||||
|
||||
// Connect client, to ip previously requested from user
|
||||
try
|
||||
{
|
||||
Client.Connect(hostIP, 14242, outmsg);
|
||||
}
|
||||
catch (ArgumentNullException e)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't connect to "+hostIP+". Error message: "+e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create timespan of 30ms
|
||||
updateInterval = new TimeSpan(0, 0, 0, 0, 200);
|
||||
|
||||
// Set timer to tick every 50ms
|
||||
//update = new System.Timers.Timer(50);
|
||||
|
||||
// When time has elapsed ( 50ms in this case ), call "update_Elapsed" funtion
|
||||
//update.Elapsed += new System.Timers.ElapsedEventHandler(Update);
|
||||
|
||||
// Funtion that waits for connection approval info from server
|
||||
WaitForStartingInfo();
|
||||
|
||||
if (Client.ConnectionStatus!=NetConnectionStatus.Connected)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't connect to server");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Start the timer
|
||||
//update.Start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Before main looping starts, we loop here and wait for approval message
|
||||
private void WaitForStartingInfo()
|
||||
{
|
||||
// When this is set to true, we are approved and ready to go
|
||||
bool CanStart = false;
|
||||
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0,0,5);
|
||||
|
||||
// Loop untill we are approved
|
||||
while (!CanStart)
|
||||
{
|
||||
if (DateTime.Now>timeOut) return;
|
||||
|
||||
NetIncomingMessage inc;
|
||||
// If new messages arrived
|
||||
if ((inc = Client.ReadMessage()) == null) continue;
|
||||
|
||||
// Switch based on the message types
|
||||
switch (inc.MessageType)
|
||||
{
|
||||
// All manually sent messages are type of "Data"
|
||||
case NetIncomingMessageType.Data:
|
||||
if (inc.ReadByte() == (byte)PacketTypes.LoggedIn)
|
||||
{
|
||||
//add the names of other connected clients to the lobby screen
|
||||
int existingClients = inc.ReadInt32();
|
||||
for (int i = 1; i <= existingClients; i++)
|
||||
{
|
||||
Game1.netLobbyScreen.AddPlayer(inc.ReadString());
|
||||
}
|
||||
|
||||
//add the name of own client to the lobby screen
|
||||
Game1.netLobbyScreen.AddPlayer(name);
|
||||
|
||||
CanStart = true;
|
||||
}
|
||||
else if (inc.ReadByte() == (byte)PacketTypes.KickedOut)
|
||||
{
|
||||
string msg = inc.ReadString();
|
||||
DebugConsole.ThrowError(msg);
|
||||
|
||||
Game1.mainMenuScreen.Select();
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.StatusChanged:
|
||||
Debug.WriteLine((NetConnectionStatus)inc.ReadByte());
|
||||
|
||||
break;
|
||||
default:
|
||||
// Should not happen and if happens, don't care
|
||||
Console.WriteLine(inc.ReadString() + " Strange message");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (updateTimer > DateTime.Now) return;
|
||||
|
||||
if (myCharacter!=null)
|
||||
{
|
||||
if (myCharacter.IsDead)
|
||||
{
|
||||
Character.Controlled = null;
|
||||
Game1.gameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
Game1.gameScreen.Cam.Zoom = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gameStarted) new NetworkEvent(myCharacter.ID, true);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (NetworkEvent networkEvent in NetworkEvent.events)
|
||||
{
|
||||
NetOutgoingMessage message = Client.CreateMessage();
|
||||
message.Write((byte)PacketTypes.NetworkEvent);
|
||||
|
||||
|
||||
if (networkEvent.FillData(message))
|
||||
{
|
||||
Client.SendMessage(message,
|
||||
(networkEvent.IsImportant) ? NetDeliveryMethod.ReliableUnordered : NetDeliveryMethod.Unreliable);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkEvent.events.Clear();
|
||||
|
||||
|
||||
CheckServerMessages();
|
||||
|
||||
// Update current time
|
||||
updateTimer = DateTime.Now + updateInterval;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for new incoming messages from server
|
||||
/// </summary>
|
||||
private void CheckServerMessages()
|
||||
{
|
||||
// Create new incoming message holder
|
||||
NetIncomingMessage inc;
|
||||
|
||||
while ((inc = Client.ReadMessage()) != null)
|
||||
{
|
||||
if (inc.MessageType != NetIncomingMessageType.Data) continue;
|
||||
|
||||
switch (inc.ReadByte())
|
||||
{
|
||||
case (byte)PacketTypes.StartGame:
|
||||
if (gameStarted) continue;
|
||||
|
||||
int seed = inc.ReadInt32();
|
||||
Game1.random = new Random(seed);
|
||||
|
||||
string mapFile = inc.ReadString();
|
||||
Map.Load(mapFile);
|
||||
|
||||
double durationMinutes = inc.ReadDouble();
|
||||
|
||||
TimeSpan duration = new TimeSpan(0,(int)durationMinutes,0);
|
||||
|
||||
//int gameModeIndex = inc.ReadInt32();
|
||||
Game1.gameSession = new GameSession("", false, duration);
|
||||
Game1.gameSession.StartShift(1);
|
||||
|
||||
myCharacter = ReadCharacterData(inc);
|
||||
Character.Controlled = myCharacter;
|
||||
|
||||
int count = inc.ReadInt32();
|
||||
for (int n = 0; n < count; n++)
|
||||
{
|
||||
ReadCharacterData(inc);
|
||||
}
|
||||
|
||||
gameStarted = true;
|
||||
|
||||
Game1.gameScreen.Select();
|
||||
|
||||
AddChatMessage("Press TAB to chat", ChatMessageType.Server);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.EndGame:
|
||||
string endMessage = inc.ReadString();
|
||||
EndGame(endMessage);
|
||||
break;
|
||||
case (byte)PacketTypes.PlayerJoined:
|
||||
|
||||
Client otherClient = new Client();
|
||||
otherClient.name = inc.ReadString();
|
||||
|
||||
Game1.netLobbyScreen.AddPlayer(otherClient.name);
|
||||
|
||||
//string newPlayerName = inc.ReadString();
|
||||
//int newPlayerID = inc.ReadInt32();
|
||||
|
||||
//CharacterInfo ch = new CharacterInfo("Content/Characters/Human/human.xml", newPlayerName);
|
||||
//ch.ID = newPlayerID;
|
||||
|
||||
//Character.newCharacterQueue.Enqueue(ch);
|
||||
|
||||
AddChatMessage(otherClient.name + " has joined the server", ChatMessageType.Server);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.PlayerLeft:
|
||||
string leavingName = inc.ReadString();
|
||||
|
||||
AddChatMessage(inc.ReadString(), ChatMessageType.Server);
|
||||
Game1.netLobbyScreen.RemovePlayer(leavingName);
|
||||
break;
|
||||
|
||||
case (byte)PacketTypes.KickedOut:
|
||||
string msg= inc.ReadString();
|
||||
|
||||
DebugConsole.ThrowError(msg);
|
||||
|
||||
Game1.mainMenuScreen.Select();
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.Chatmessage:
|
||||
ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
|
||||
AddChatMessage(inc.ReadString(), messageType);
|
||||
break;
|
||||
case (byte)PacketTypes.NetworkEvent:
|
||||
//read the data from the message and update client state accordingly
|
||||
if (!gameStarted) break;
|
||||
NetworkEvent.ReadData(inc);
|
||||
break;
|
||||
case (byte)PacketTypes.UpdateNetLobby:
|
||||
if (gameStarted) continue;
|
||||
Game1.netLobbyScreen.ReadData(inc);
|
||||
break;
|
||||
case (byte)PacketTypes.Traitor:
|
||||
string targetName = inc.ReadString();
|
||||
|
||||
Game1.gameSession.NewChatMessage("You are an agent of Ordo Europae", messageColor[(int)ChatMessageType.Server]);
|
||||
Game1.gameSession.NewChatMessage("Your secret task is to assassinate " + targetName + "!", messageColor[(int)ChatMessageType.Server]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void EndGame(string endMessage)
|
||||
{
|
||||
Map.Clear();
|
||||
|
||||
Game1.netLobbyScreen.Select();
|
||||
|
||||
if (Game1.gameSession!=null) Game1.gameSession.EndShift(null, null);
|
||||
|
||||
DebugConsole.ThrowError(endMessage);
|
||||
|
||||
myCharacter = null;
|
||||
|
||||
gameStarted = false;
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
NetOutgoingMessage msg = Client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.PlayerLeft);
|
||||
|
||||
Client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
public void SendCharacterData()
|
||||
{
|
||||
if (characterInfo == null) return;
|
||||
|
||||
NetOutgoingMessage msg = Client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.CharacterInfo);
|
||||
msg.Write(characterInfo.name);
|
||||
msg.Write(characterInfo.gender == Gender.Male);
|
||||
|
||||
Client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
}
|
||||
|
||||
private Character ReadCharacterData(NetIncomingMessage inc)
|
||||
{
|
||||
string newName = inc.ReadString();
|
||||
int ID = inc.ReadInt32();
|
||||
bool isFemale = inc.ReadBoolean();
|
||||
int inventoryID = inc.ReadInt32();
|
||||
Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat());
|
||||
|
||||
CharacterInfo ch = new CharacterInfo("Content/Characters/Human/human.xml", newName, isFemale ? Gender.Female : Gender.Male);
|
||||
Character character = new Character(ch, position);
|
||||
character.ID = ID;
|
||||
character.Inventory.ID = inventoryID;
|
||||
|
||||
return character;
|
||||
}
|
||||
|
||||
public void SendChatMessage(string message)
|
||||
{
|
||||
//AddChatMessage(message);
|
||||
|
||||
ChatMessageType type = (gameStarted && myCharacter != null && myCharacter.IsDead) ? ChatMessageType.Dead : ChatMessageType.Default;
|
||||
|
||||
NetOutgoingMessage msg = Client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Chatmessage);
|
||||
msg.Write((byte)type);
|
||||
msg.Write(message);
|
||||
|
||||
Client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,509 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Subsurface.Networking
|
||||
{
|
||||
class GameServer : NetworkMember
|
||||
{
|
||||
|
||||
// Server object
|
||||
NetServer Server;
|
||||
// Configuration object
|
||||
NetPeerConfiguration Config;
|
||||
|
||||
public List<Client> connectedClients = new List<Client>();
|
||||
|
||||
//NetIncomingMessage inc;
|
||||
|
||||
const int sparseUpdateInterval = 150;
|
||||
int sparseUpdateTimer;
|
||||
|
||||
Client myClient;
|
||||
|
||||
public GameServer()
|
||||
{
|
||||
Config = new NetPeerConfiguration("subsurface");
|
||||
|
||||
Config.Port = 14242;
|
||||
|
||||
//Config.SimulatedLoss = 0.2f;
|
||||
//Config.SimulatedMinimumLatency = 0.25f;
|
||||
|
||||
Config.MaximumConnections = 10;
|
||||
|
||||
Config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
|
||||
|
||||
try
|
||||
{
|
||||
Server = new NetServer(Config);
|
||||
Server.Start();
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't start the server", e);
|
||||
}
|
||||
|
||||
|
||||
updateInterval = new TimeSpan(0, 0, 0, 0, 30);
|
||||
|
||||
DebugConsole.NewMessage("Server started", Color.Green);
|
||||
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Server.ReadMessage() Returns new messages, that have not yet been read.
|
||||
// If "inc" is null -> ReadMessage returned null -> Its null, so dont do this :)
|
||||
|
||||
NetIncomingMessage inc = Server.ReadMessage();
|
||||
if (inc != null) ReadMessage(inc);
|
||||
|
||||
// if 30ms has passed
|
||||
if ((updateTimer) < DateTime.Now)
|
||||
{
|
||||
if (Server.ConnectionsCount > 0)
|
||||
{
|
||||
if (sparseUpdateTimer <= 0) SparseUpdate();
|
||||
|
||||
SendNetworkEvents();
|
||||
}
|
||||
|
||||
sparseUpdateTimer -= 1;
|
||||
updateTimer = DateTime.Now + updateInterval;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadMessage(NetIncomingMessage inc)
|
||||
{
|
||||
NetOutgoingMessage outmsg;
|
||||
|
||||
switch (inc.MessageType)
|
||||
{
|
||||
case NetIncomingMessageType.ConnectionApproval:
|
||||
if (inc.ReadByte() != (byte)PacketTypes.Login) break;
|
||||
|
||||
DebugConsole.NewMessage("New player has joined the server", Color.White);
|
||||
|
||||
//Character ch = new Character("Content/Characters/Human/human.xml");
|
||||
|
||||
Client newClient = new Client();
|
||||
newClient.version = inc.ReadString();
|
||||
newClient.name = inc.ReadString();
|
||||
newClient.Connection = inc.SenderConnection;
|
||||
|
||||
connectedClients.Add(newClient);
|
||||
|
||||
inc.SenderConnection.Approve();
|
||||
break;
|
||||
case NetIncomingMessageType.StatusChanged:
|
||||
Debug.WriteLine(inc.SenderConnection + " status changed. " + (NetConnectionStatus)inc.SenderConnection.Status);
|
||||
if (inc.SenderConnection.Status == NetConnectionStatus.Connected)
|
||||
{
|
||||
|
||||
|
||||
Client sender = connectedClients.Find(x => x.Connection == inc.SenderConnection);
|
||||
|
||||
if (sender == null) break;
|
||||
|
||||
if (sender.version != Game1.version.ToString())
|
||||
{
|
||||
DisconnectClient(sender, sender.name+" was unable to connect to the server (nonmatching game version)",
|
||||
"Subsurface version " + Game1.version + " required to connect to the server (Your version: " + sender.version + ")");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Game1.netLobbyScreen.AddPlayer(sender.name);
|
||||
|
||||
// Notify the client that they have logged in
|
||||
outmsg = Server.CreateMessage();
|
||||
|
||||
outmsg.Write((byte)PacketTypes.LoggedIn);
|
||||
|
||||
//notify the client about other clients already logged in
|
||||
outmsg.Write((myClient == null) ? connectedClients.Count - 1 : connectedClients.Count);
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
if (c.Connection == inc.SenderConnection) continue;
|
||||
outmsg.Write(c.name);
|
||||
}
|
||||
|
||||
if (myClient != null) outmsg.Write(myClient.name);
|
||||
|
||||
Server.SendMessage(outmsg, inc.SenderConnection, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
|
||||
|
||||
//notify other clients about the new client
|
||||
outmsg = Server.CreateMessage();
|
||||
outmsg.Write((byte)PacketTypes.PlayerJoined);
|
||||
|
||||
outmsg.Write(sender.name);
|
||||
|
||||
//send the message to everyone except the client who just logged in
|
||||
SendMessage(outmsg, NetDeliveryMethod.ReliableUnordered, inc.SenderConnection);
|
||||
|
||||
AddChatMessage(sender.name + " has joined the server", ChatMessageType.Server);
|
||||
|
||||
UpdateNetLobby(null);
|
||||
}
|
||||
}
|
||||
else if (inc.SenderConnection.Status == NetConnectionStatus.Disconnected)
|
||||
{
|
||||
DisconnectClient(inc.SenderConnection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
break;
|
||||
case NetIncomingMessageType.Data:
|
||||
|
||||
switch (inc.ReadByte())
|
||||
{
|
||||
case (byte)PacketTypes.NetworkEvent:
|
||||
if (!gameStarted) break;
|
||||
if (!NetworkEvent.ReadData(inc)) break;
|
||||
|
||||
outmsg = Server.CreateMessage();
|
||||
outmsg.Write(inc);
|
||||
|
||||
List<NetConnection> recipients = new List<NetConnection>();
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
if (client.Connection == inc.SenderConnection) continue;
|
||||
if (!client.inGame) continue;
|
||||
|
||||
recipients.Add(client.Connection);
|
||||
}
|
||||
|
||||
if (recipients.Count == 0) break;
|
||||
Server.SendMessage(outmsg, recipients, inc.DeliveryMethod, 0);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.Chatmessage:
|
||||
ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
|
||||
string message = inc.ReadString();
|
||||
|
||||
SendChatMessage(message, messageType);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.PlayerLeft:
|
||||
DisconnectClient(inc.SenderConnection);
|
||||
break;
|
||||
case (byte)PacketTypes.CharacterInfo:
|
||||
ReadCharacterData(inc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.WarningMessage:
|
||||
Debug.WriteLine(inc.ReadString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SparseUpdate()
|
||||
{
|
||||
foreach (Character c in Character.characterList)
|
||||
{
|
||||
bool isClient = false;
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
if (client.character != c) continue;
|
||||
isClient = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isClient)
|
||||
{
|
||||
c.largeUpdateTimer = 0;
|
||||
new NetworkEvent(c.ID, false);
|
||||
}
|
||||
}
|
||||
|
||||
sparseUpdateTimer = sparseUpdateInterval;
|
||||
}
|
||||
|
||||
private void SendMessage(NetOutgoingMessage msg, NetDeliveryMethod deliveryMethod, NetConnection excludedConnection)
|
||||
{
|
||||
List<NetConnection> recipients = new List<NetConnection>();
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
if (client.Connection != excludedConnection) recipients.Add(client.Connection);
|
||||
}
|
||||
|
||||
if (recipients.Count == 0) return;
|
||||
|
||||
Server.SendMessage(msg, recipients, deliveryMethod, 0);
|
||||
|
||||
}
|
||||
|
||||
private void SendNetworkEvents()
|
||||
{
|
||||
if (NetworkEvent.events.Count == 0) return;
|
||||
|
||||
//System.Diagnostics.Debug.WriteLine("*************************");
|
||||
foreach (NetworkEvent networkEvent in NetworkEvent.events)
|
||||
{
|
||||
//System.Diagnostics.Debug.WriteLine("networkevent "+networkEvent.ID);
|
||||
|
||||
NetOutgoingMessage message = Server.CreateMessage();
|
||||
message.Write((byte)PacketTypes.NetworkEvent);
|
||||
//if (!networkEvent.IsClient) continue;
|
||||
|
||||
networkEvent.FillData(message);
|
||||
|
||||
Server.SendMessage(message, Server.Connections,
|
||||
(networkEvent.IsImportant) ? NetDeliveryMethod.Unreliable : NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
NetworkEvent.events.Clear();
|
||||
}
|
||||
|
||||
|
||||
public bool StartGame(GUIButton button, object obj)
|
||||
{
|
||||
int seed = DateTime.Now.Millisecond;
|
||||
Game1.random = new Random(seed);
|
||||
|
||||
Map.Load(Game1.netLobbyScreen.SelectedMap);
|
||||
|
||||
Game1.gameSession = new GameSession("", false, Game1.netLobbyScreen.GameDuration, Game1.netLobbyScreen.SelectedMode);
|
||||
Game1.gameSession.StartShift(1);
|
||||
//EventManager.SelectEvent(Game1.netLobbyScreen.SelectedEvent);
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
client.inGame = true;
|
||||
|
||||
WayPoint spawnPoint = WayPoint.GetRandom(WayPoint.SpawnType.Human);
|
||||
|
||||
if (client.characterInfo==null)
|
||||
{
|
||||
client.characterInfo = new CharacterInfo("Content/Characters/Human/human.xml", client.name);
|
||||
}
|
||||
|
||||
client.character = new Character(client.characterInfo, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition, true);
|
||||
}
|
||||
|
||||
if (myClient != null)
|
||||
{
|
||||
WayPoint spawnPoint = WayPoint.GetRandom(WayPoint.SpawnType.Human);
|
||||
CharacterInfo ch = new CharacterInfo("Content/Characters/Human/human.xml", myClient.name);
|
||||
myClient.character = new Character(ch, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition);
|
||||
}
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
NetOutgoingMessage msg = Server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.StartGame);
|
||||
|
||||
msg.Write(seed);
|
||||
|
||||
msg.Write(Game1.netLobbyScreen.SelectedMap);
|
||||
msg.Write(Game1.netLobbyScreen.GameDuration.TotalMinutes);
|
||||
|
||||
WriteCharacterData(msg, client.name, client.character);
|
||||
|
||||
msg.Write((myClient == null) ? connectedClients.Count - 1 : connectedClients.Count);
|
||||
foreach (Client otherClient in connectedClients)
|
||||
{
|
||||
if (otherClient == client) continue;
|
||||
WriteCharacterData(msg, otherClient.name, otherClient.character);
|
||||
}
|
||||
|
||||
if (myClient!=null)
|
||||
{
|
||||
WriteCharacterData(msg, myClient.name, myClient.character);
|
||||
}
|
||||
|
||||
Server.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
gameStarted = true;
|
||||
|
||||
Game1.gameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
|
||||
Game1.gameScreen.Select();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void EndGame(string endMessage)
|
||||
{
|
||||
Map.Clear();
|
||||
|
||||
gameStarted = false;
|
||||
|
||||
if (connectedClients.Count>0)
|
||||
{
|
||||
NetOutgoingMessage msg = Server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.EndGame);
|
||||
msg.Write(endMessage);
|
||||
|
||||
if (Server.ConnectionsCount > 0)
|
||||
{
|
||||
Server.SendMessage(msg, Server.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
client.character = null;
|
||||
client.inGame = false;
|
||||
}
|
||||
}
|
||||
|
||||
Game1.netLobbyScreen.Select();
|
||||
|
||||
DebugConsole.ThrowError(endMessage);
|
||||
}
|
||||
|
||||
private void DisconnectClient(NetConnection senderConnection)
|
||||
{
|
||||
Client client = connectedClients.Find(x => x.Connection == senderConnection);
|
||||
if (client != null) DisconnectClient(client);
|
||||
}
|
||||
|
||||
private void DisconnectClient(Client client, string msg = "", string targetmsg = "")
|
||||
{
|
||||
if (client == null) return;
|
||||
|
||||
if (gameStarted && client.character != null) client.character.Kill(true);
|
||||
|
||||
if (msg == "") msg = client.name + " has left the server";
|
||||
if (targetmsg == "") targetmsg = "You have left the server";
|
||||
|
||||
NetOutgoingMessage outmsg = Server.CreateMessage();
|
||||
outmsg.Write((byte)PacketTypes.KickedOut);
|
||||
outmsg.Write(targetmsg);
|
||||
Server.SendMessage(outmsg, client.Connection, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
|
||||
connectedClients.Remove(client);
|
||||
|
||||
outmsg = Server.CreateMessage();
|
||||
outmsg.Write((byte)PacketTypes.PlayerLeft);
|
||||
outmsg.Write(client.name);
|
||||
outmsg.Write(msg);
|
||||
|
||||
Game1.netLobbyScreen.RemovePlayer(client.name);
|
||||
|
||||
if (Server.Connections.Count > 0)
|
||||
{
|
||||
Server.SendMessage(outmsg, Server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
AddChatMessage(msg, ChatMessageType.Server);
|
||||
}
|
||||
|
||||
public void KickPlayer(string playerName)
|
||||
{
|
||||
playerName = playerName.ToLower();
|
||||
Client client = null;
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
if (c.name.ToLower() != playerName) continue;
|
||||
client = c;
|
||||
break;
|
||||
}
|
||||
|
||||
if (client == null) return;
|
||||
|
||||
DisconnectClient(client, client.name + " has been kicked from the server", "You have been kicked from the server");
|
||||
}
|
||||
|
||||
public void NewTraitor(Client traitor, Client target)
|
||||
{
|
||||
NetOutgoingMessage msg = Server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Traitor);
|
||||
msg.Write(target.name);
|
||||
if (Server.Connections.Count > 0)
|
||||
{
|
||||
Server.SendMessage(msg, traitor.Connection, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateNetLobby(object obj)
|
||||
{
|
||||
NetOutgoingMessage msg = Server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.UpdateNetLobby);
|
||||
Game1.netLobbyScreen.WriteData(msg);
|
||||
|
||||
if (Server.Connections.Count > 0)
|
||||
{
|
||||
Server.SendMessage(msg, Server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void SendChatMessage(string message, ChatMessageType type = ChatMessageType.Server)
|
||||
{
|
||||
AddChatMessage(message, type);
|
||||
|
||||
NetOutgoingMessage msg = Server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Chatmessage);
|
||||
msg.Write((byte)type);
|
||||
msg.Write(message);
|
||||
|
||||
if (Server.Connections.Count == 0) return;
|
||||
|
||||
if (type==ChatMessageType.Dead)
|
||||
{
|
||||
List<NetConnection> recipients = new List<NetConnection>();
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
if (c.character != null && c.character.IsDead) recipients.Add(c.Connection);
|
||||
}
|
||||
if (recipients.Count>0)
|
||||
{
|
||||
Server.SendMessage(msg, recipients, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Server.SendMessage(msg, Server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ReadCharacterData(NetIncomingMessage message)
|
||||
{
|
||||
string name = message.ReadString();
|
||||
Gender gender = message.ReadBoolean() ? Gender.Male : Gender.Female;
|
||||
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
if (c.Connection != message.SenderConnection) continue;
|
||||
c.characterInfo = new CharacterInfo("Content/Characters/Human/human.xml", name, gender);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteCharacterData(NetOutgoingMessage message, string name, Character character)
|
||||
{
|
||||
message.Write(name);
|
||||
message.Write(character.ID);
|
||||
message.Write(character.info.gender==Gender.Female);
|
||||
message.Write(character.Inventory.ID);
|
||||
message.Write(character.SimPosition.X);
|
||||
message.Write(character.SimPosition.Y);
|
||||
}
|
||||
}
|
||||
|
||||
class Client
|
||||
{
|
||||
public string name;
|
||||
|
||||
public Character character;
|
||||
public CharacterInfo characterInfo;
|
||||
public NetConnection Connection { get; set; }
|
||||
public string version;
|
||||
public bool inGame;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using System.Collections.Generic;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace Subsurface.Networking
|
||||
{
|
||||
enum NetworkEventType
|
||||
{
|
||||
UpdateEntity = 0,
|
||||
KillCharacter = 1,
|
||||
UpdateComponent = 2,
|
||||
DropItem = 3,
|
||||
InventoryUpdate = 4,
|
||||
PickItem = 5
|
||||
}
|
||||
|
||||
class NetworkEvent
|
||||
{
|
||||
public static List<NetworkEvent> events = new List<NetworkEvent>();
|
||||
|
||||
private static bool[] isImportant = { false, true, true, true, true, true };
|
||||
|
||||
private int id;
|
||||
|
||||
private NetworkEventType eventType;
|
||||
|
||||
private bool isClientEvent;
|
||||
|
||||
private object data;
|
||||
|
||||
//private NetOutgoingMessage message;
|
||||
|
||||
public int ID
|
||||
{
|
||||
get { return id; }
|
||||
}
|
||||
|
||||
public bool IsClient
|
||||
{
|
||||
get { return isClientEvent; }
|
||||
}
|
||||
|
||||
public bool IsImportant
|
||||
{
|
||||
get { return isImportant[(int)eventType]; }
|
||||
}
|
||||
|
||||
public NetworkEvent(int id, bool isClient)
|
||||
: this(NetworkEventType.UpdateEntity, id, isClient)
|
||||
{
|
||||
}
|
||||
|
||||
public NetworkEvent(NetworkEventType type, int id, bool isClient, object data = null)
|
||||
{
|
||||
if (isClient)
|
||||
{
|
||||
if (Game1.server != null) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Game1.server == null) return;
|
||||
}
|
||||
|
||||
this.eventType = type;
|
||||
|
||||
foreach (NetworkEvent e in events)
|
||||
{
|
||||
if (!isImportant[(int)type] && e.id == id && e.eventType == type) return;
|
||||
}
|
||||
|
||||
this.id = id;
|
||||
this.isClientEvent = isClient;
|
||||
|
||||
this.data = data;
|
||||
|
||||
events.Add(this);
|
||||
}
|
||||
|
||||
public bool FillData(NetOutgoingMessage message)
|
||||
{
|
||||
message.Write((byte)eventType);
|
||||
|
||||
Entity e = Entity.FindEntityByID(id);
|
||||
if (e == null) return false;
|
||||
|
||||
message.Write(id);
|
||||
|
||||
e.FillNetworkData(eventType, message, data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ReadData(NetIncomingMessage message)
|
||||
{
|
||||
NetworkEventType eventType = (NetworkEventType)message.ReadByte();
|
||||
|
||||
int id;
|
||||
try
|
||||
{
|
||||
id = message.ReadInt32();
|
||||
}
|
||||
catch
|
||||
{
|
||||
DebugConsole.ThrowError("Received invalid network message");
|
||||
return false;
|
||||
}
|
||||
|
||||
Entity e = Entity.FindEntityByID(id);
|
||||
if (e == null)
|
||||
{
|
||||
//DebugConsole.ThrowError("Couldn't find an entity matching the ID ''" + id + "''");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//System.Diagnostics.Debug.WriteLine("new message: " + eventType +" - "+e);
|
||||
|
||||
e.ReadNetworkData(eventType, message);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Subsurface.Networking
|
||||
{
|
||||
enum PacketTypes
|
||||
{
|
||||
Login,
|
||||
LoggedIn,
|
||||
LogOut,
|
||||
|
||||
PlayerJoined,
|
||||
PlayerLeft,
|
||||
KickedOut,
|
||||
|
||||
StartGame,
|
||||
EndGame,
|
||||
|
||||
CharacterInfo,
|
||||
|
||||
Chatmessage,
|
||||
UpdateNetLobby,
|
||||
|
||||
NetworkEvent,
|
||||
|
||||
Traitor
|
||||
}
|
||||
|
||||
class NetworkMember
|
||||
{
|
||||
protected static Color[] messageColor = { Color.Black, Color.DarkRed, Color.DarkBlue, Color.DarkGreen };
|
||||
|
||||
protected TimeSpan updateInterval;
|
||||
protected DateTime updateTimer;
|
||||
|
||||
protected bool gameStarted;
|
||||
|
||||
public void AddChatMessage(string message, ChatMessageType messageType)
|
||||
{
|
||||
Game1.netLobbyScreen.NewChatMessage(message, messageColor[(int)messageType]);
|
||||
if (Game1.gameSession != null) Game1.gameSession.NewChatMessage(message, messageColor[(int)messageType]);
|
||||
|
||||
GUI.PlayMessageSound();
|
||||
}
|
||||
}
|
||||
|
||||
enum ChatMessageType
|
||||
{
|
||||
Default, Admin, Dead, Server
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user