Completely destroyed game
Looks like a lot more than just netcode is getting rewritten. Removing coroutines because there are better ways of handling asynchronous tasks, removing filestream because that's to be reimplemented later
This commit is contained in:
@@ -42,9 +42,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public List<JobPrefab> jobPreferences;
|
||||
public JobPrefab assignedJob;
|
||||
|
||||
public FileStreamSender FileStreamSender;
|
||||
|
||||
|
||||
public float deleteDisconnectedTimer;
|
||||
|
||||
public ClientPermissions Permissions;
|
||||
@@ -168,17 +166,6 @@ namespace Barotrauma.Networking
|
||||
client.kickVoters.RemoveAll(voter => !connectedClients.Contains(voter));
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelTransfer()
|
||||
{
|
||||
if (FileStreamSender == null) return;
|
||||
|
||||
FileStreamSender.CancelTransfer();
|
||||
FileStreamSender.Dispose();
|
||||
|
||||
FileStreamSender = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@ namespace Barotrauma.Networking
|
||||
private NetClient client;
|
||||
|
||||
private GUIMessageBox reconnectBox;
|
||||
|
||||
private FileStreamReceiver fileStreamReceiver;
|
||||
private Queue<Pair<string, FileTransferMessageType>> requestFileQueue;
|
||||
|
||||
|
||||
private GUIButton endRoundButton;
|
||||
private GUITickBox endVoteTickBox;
|
||||
|
||||
@@ -45,12 +42,7 @@ namespace Barotrauma.Networking
|
||||
return otherClients;
|
||||
}
|
||||
}
|
||||
|
||||
public string ActiveFileTransferName
|
||||
{
|
||||
get { return (fileStreamReceiver == null || fileStreamReceiver.Status == FileTransferStatus.Finished) ? "" : fileStreamReceiver.FileName; }
|
||||
}
|
||||
|
||||
|
||||
public GameClient(string newName)
|
||||
{
|
||||
endVoteTickBox = new GUITickBox(new Rectangle(GameMain.GraphicsWidth - 170, 20, 20, 20), "End round", Alignment.TopLeft, inGameHUD);
|
||||
@@ -76,9 +68,7 @@ namespace Barotrauma.Networking
|
||||
Hull.EditWater = false;
|
||||
|
||||
name = newName;
|
||||
|
||||
requestFileQueue = new Queue<Pair<string, FileTransferMessageType>>();
|
||||
|
||||
|
||||
characterInfo = new CharacterInfo(Character.HumanConfigFile, name);
|
||||
characterInfo.Job = null;
|
||||
|
||||
@@ -125,8 +115,7 @@ namespace Barotrauma.Networking
|
||||
netPeer = client;
|
||||
client.Start();
|
||||
|
||||
NetOutgoingMessage outmsg = client.CreateMessage();
|
||||
outmsg.Write((byte)PacketTypes.Login);
|
||||
NetOutgoingMessage outmsg = client.CreateMessage();
|
||||
|
||||
|
||||
System.Net.IPEndPoint IPEndPoint = null;
|
||||
@@ -326,16 +315,14 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else if (gameStarted)
|
||||
{
|
||||
new NetworkEvent(NetworkEventType.EntityUpdate, myCharacter.ID, true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Update current time
|
||||
updateTimer = DateTime.Now + updateInterval;
|
||||
}
|
||||
|
||||
private CoroutineHandle startGameCoroutine;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check for new incoming messages from server
|
||||
/// </summary>
|
||||
@@ -343,14 +330,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
// Create new incoming message holder
|
||||
NetIncomingMessage inc;
|
||||
|
||||
if (startGameCoroutine != null && CoroutineManager.IsCoroutineRunning(startGameCoroutine)) return;
|
||||
|
||||
if (fileStreamReceiver == null && requestFileQueue.Count > 0)
|
||||
{
|
||||
var newRequest = requestFileQueue.Dequeue();
|
||||
RequestFile(newRequest.First, newRequest.Second);
|
||||
}
|
||||
|
||||
while ((inc = client.ReadMessage()) != null)
|
||||
{
|
||||
@@ -586,96 +565,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void RequestFile(string file, FileTransferMessageType fileType)
|
||||
{
|
||||
if (fileStreamReceiver!=null)
|
||||
{
|
||||
var request = new Pair<string, FileTransferMessageType>()
|
||||
{
|
||||
First = file,
|
||||
Second = fileType
|
||||
};
|
||||
|
||||
requestFileQueue.Enqueue(request);
|
||||
return;
|
||||
}
|
||||
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.RequestFile);
|
||||
msg.Write((byte)fileType);
|
||||
|
||||
msg.Write(file);
|
||||
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
fileStreamReceiver = new FileStreamReceiver(client, Path.Combine(Submarine.SavePath, "Downloaded"), fileType, OnFileReceived);
|
||||
}
|
||||
|
||||
private void OnFileReceived(FileStreamReceiver receiver)
|
||||
{
|
||||
if (receiver.Status == FileTransferStatus.Error)
|
||||
{
|
||||
new GUIMessageBox("Error while receiving file from server", receiver.ErrorMessage, 400, 350);
|
||||
receiver.DeleteFile();
|
||||
|
||||
}
|
||||
else if (receiver.Status == FileTransferStatus.Finished)
|
||||
{
|
||||
new GUIMessageBox("Download finished", "File ''" + receiver.FileName + "'' was downloaded succesfully.");
|
||||
|
||||
switch (receiver.FileType)
|
||||
{
|
||||
case FileTransferMessageType.Submarine:
|
||||
Submarine.SavedSubmarines.RemoveAll(s => s.Name + ".sub" == receiver.FileName);
|
||||
|
||||
for (int i = 0; i<2; i++)
|
||||
{
|
||||
|
||||
var textBlock = (i == 0) ?
|
||||
GameMain.NetLobbyScreen.ShuttleList.ListBox.children.Find(c => (c.UserData as Submarine).Name+".sub" == receiver.FileName) :
|
||||
GameMain.NetLobbyScreen.SubList.children.Find(c => (c.UserData as Submarine).Name+".sub" == receiver.FileName);
|
||||
if (textBlock == null) continue;
|
||||
|
||||
(textBlock as GUITextBlock).TextColor = Color.White;
|
||||
|
||||
var newSub = new Submarine(receiver.FilePath);
|
||||
Submarine.SavedSubmarines.Add(newSub);
|
||||
textBlock.UserData = newSub;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fileStreamReceiver = null;
|
||||
}
|
||||
|
||||
private void CancelFileTransfer()
|
||||
{
|
||||
fileStreamReceiver.DeleteFile();
|
||||
fileStreamReceiver.Dispose();
|
||||
fileStreamReceiver = null;
|
||||
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.RequestFile);
|
||||
msg.Write((byte)FileTransferMessageType.Cancel);
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
public override void KickPlayer(string kickedName, bool ban)
|
||||
{
|
||||
if (!permissions.HasFlag(ClientPermissions.Kick) && !ban) return;
|
||||
if (!permissions.HasFlag(ClientPermissions.Ban) && ban) return;
|
||||
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.KickPlayer);
|
||||
msg.Write(ban);
|
||||
msg.Write(kickedName);
|
||||
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
|
||||
public bool VoteForKick(GUIButton button, object userdata)
|
||||
{
|
||||
var votedClient = otherClients.Find(c => c.Character == userdata);
|
||||
@@ -695,7 +585,7 @@ namespace Barotrauma.Networking
|
||||
public void Vote(VoteType voteType, object userData)
|
||||
{
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Vote);
|
||||
|
||||
msg.Write((byte)voteType);
|
||||
|
||||
switch (voteType)
|
||||
@@ -723,7 +613,7 @@ namespace Barotrauma.Networking
|
||||
public bool SpectateClicked(GUIButton button, object userData)
|
||||
{
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.SpectateRequest);
|
||||
|
||||
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
@@ -754,7 +644,6 @@ namespace Barotrauma.Networking
|
||||
if (characterInfo == null) return;
|
||||
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.CharacterInfo);
|
||||
|
||||
msg.Write(characterInfo.Name);
|
||||
msg.Write(characterInfo.Gender == Gender.Male);
|
||||
|
||||
@@ -351,8 +351,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
if (c.FileStreamSender != null) UpdateFileTransfer(c, deltaTime);
|
||||
|
||||
//c.ReliableChannel.Update(deltaTime);
|
||||
|
||||
//slowly reset spam timers
|
||||
@@ -365,7 +363,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
try
|
||||
{
|
||||
ReadMessage(inc);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -382,7 +380,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (gameStarted)
|
||||
{
|
||||
if (myCharacter != null && !myCharacter.IsDead) new NetworkEvent(NetworkEventType.EntityUpdate, myCharacter.ID, false);
|
||||
|
||||
float ignoreDistance = FarseerPhysics.ConvertUnits.ToDisplayUnits(NetConfig.CharacterIgnoreDistance);
|
||||
|
||||
@@ -394,7 +391,7 @@ namespace Barotrauma.Networking
|
||||
c2 => c2.IsNetworkPlayer &&
|
||||
Vector2.Distance(c2.WorldPosition, c.WorldPosition) < ignoreDistance))
|
||||
{
|
||||
new NetworkEvent(NetworkEventType.EntityUpdate, c.ID, false);
|
||||
|
||||
}
|
||||
|
||||
//todo: take multiple subs into account
|
||||
@@ -407,8 +404,7 @@ namespace Barotrauma.Networking
|
||||
if (server.ConnectionsCount > 0)
|
||||
{
|
||||
if (sparseUpdateTimer < DateTime.Now) SparseUpdate();
|
||||
|
||||
SendNetworkEvents();
|
||||
|
||||
}
|
||||
|
||||
updateTimer = DateTime.Now + updateInterval;
|
||||
@@ -444,557 +440,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
//if (FarseerPhysics.ConvertUnits.ToSimUnits(diff.Length()) > NetConfig.CharacterIgnoreDistance) continue;
|
||||
}
|
||||
|
||||
new NetworkEvent(NetworkEventType.ImportantEntityUpdate, c.ID, false);
|
||||
|
||||
}
|
||||
|
||||
sparseUpdateTimer = DateTime.Now + sparseUpdateInterval;
|
||||
}
|
||||
|
||||
private void ReadMessage(NetIncomingMessage inc)
|
||||
{
|
||||
Client sender = connectedClients.Find(x => x.Connection == inc.SenderConnection);
|
||||
|
||||
switch (inc.MessageType)
|
||||
{
|
||||
case NetIncomingMessageType.ConnectionApproval:
|
||||
HandleConnectionApproval(inc);
|
||||
break;
|
||||
case NetIncomingMessageType.StatusChanged:
|
||||
Debug.WriteLine(inc.SenderConnection + " status changed. " + (NetConnectionStatus)inc.SenderConnection.Status);
|
||||
if (inc.SenderConnection.Status == NetConnectionStatus.Disconnected)
|
||||
{
|
||||
var connectedClient = connectedClients.Find(c => c.Connection == inc.SenderConnection);
|
||||
if (connectedClient != null && !disconnectedClients.Contains(connectedClient))
|
||||
{
|
||||
connectedClient.deleteDisconnectedTimer = NetConfig.DeleteDisconnectedTime;
|
||||
disconnectedClients.Add(connectedClient);
|
||||
}
|
||||
|
||||
DisconnectClient(inc.SenderConnection,
|
||||
connectedClient != null ? connectedClient.name + " has disconnected" : "");
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.Data:
|
||||
|
||||
byte packetType = inc.ReadByte();
|
||||
|
||||
if (sender == null)
|
||||
{
|
||||
var authUser = unauthenticatedClients.Find(c => c.Connection == inc.SenderConnection);
|
||||
if (authUser == null)
|
||||
{
|
||||
unauthenticatedClients.Remove(authUser);
|
||||
inc.SenderConnection.Disconnect("Disconnected");
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckAuthentication(inc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (packetType)
|
||||
{
|
||||
case (byte)PacketTypes.NetworkEvent:
|
||||
if (!gameStarted) break;
|
||||
NetworkEvent.ReadMessage(inc, true);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.Chatmessage:
|
||||
ReadChatMessage(inc);
|
||||
break;
|
||||
case (byte)PacketTypes.PlayerLeft:
|
||||
DisconnectClient(inc.SenderConnection);
|
||||
break;
|
||||
case (byte)PacketTypes.StartGame:
|
||||
sender.ReadyToStart = true;
|
||||
break;
|
||||
case (byte)PacketTypes.EndGame:
|
||||
if (!sender.HasPermission(ClientPermissions.EndRound))
|
||||
{
|
||||
Log(sender.name+" attempted to end the round (insufficient permissions)", Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Round ended by " + sender.name, Color.Red);
|
||||
EndGame();
|
||||
}
|
||||
break;
|
||||
case (byte)PacketTypes.KickPlayer:
|
||||
bool ban = inc.ReadBoolean();
|
||||
string kickedName = inc.ReadString();
|
||||
|
||||
var kickedClient = connectedClients.Find(c => c.name.ToLowerInvariant() == kickedName.ToLowerInvariant());
|
||||
if (kickedClient == null || kickedClient == sender) return;
|
||||
|
||||
if (ban && !sender.HasPermission(ClientPermissions.Ban))
|
||||
{
|
||||
Log(sender.name + " attempted to ban " + kickedClient.name + " (insufficient permissions)", Color.Red);
|
||||
|
||||
}
|
||||
else if (!sender.HasPermission(ClientPermissions.Kick))
|
||||
{
|
||||
Log(sender.name + " attempted to kick " + kickedClient.name + " (insufficient permissions)", Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
KickClient(kickedClient, ban);
|
||||
}
|
||||
break;
|
||||
case (byte)PacketTypes.CharacterInfo:
|
||||
ReadCharacterData(inc);
|
||||
break;
|
||||
case (byte)PacketTypes.RequestFile:
|
||||
|
||||
if (!AllowFileTransfers)
|
||||
{
|
||||
SendCancelTransferMessage(sender, "File transfers have been disabled by the server.");
|
||||
break;
|
||||
}
|
||||
|
||||
byte fileType = inc.ReadByte();
|
||||
string fileName = fileType == (byte)FileTransferMessageType.Cancel ? "" : inc.ReadString();
|
||||
|
||||
switch (fileType)
|
||||
{
|
||||
case (byte)FileTransferMessageType.Submarine:
|
||||
|
||||
var requestedSubmarine = Submarine.SavedSubmarines.Find(s => s.Name == fileName);
|
||||
|
||||
if (requestedSubmarine==null)
|
||||
{
|
||||
//todo: ei voi ladata
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sender.FileStreamSender != null) sender.FileStreamSender.CancelTransfer();
|
||||
|
||||
var fileStreamSender = FileStreamSender.Create(sender.Connection, requestedSubmarine.FilePath, FileTransferMessageType.Submarine);
|
||||
if (fileStreamSender != null) sender.FileStreamSender = fileStreamSender;
|
||||
}
|
||||
break;
|
||||
case (byte)FileTransferMessageType.Cancel:
|
||||
if (sender.FileStreamSender != null)
|
||||
{
|
||||
sender.FileStreamSender.CancelTransfer();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DebugConsole.ThrowError("Unknown file type was requested ("+fileType+")");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.ResendRequest:
|
||||
break;
|
||||
case (byte)PacketTypes.LatestMessageID:
|
||||
break;
|
||||
case (byte)PacketTypes.Vote:
|
||||
Voting.RegisterVote(inc, connectedClients);
|
||||
|
||||
if (Voting.AllowEndVoting && EndVoteMax > 0 &&
|
||||
((float)EndVoteCount / (float)EndVoteMax) >= EndVoteRequiredRatio)
|
||||
{
|
||||
Log("Ending round by votes (" + EndVoteCount + "/" + (EndVoteMax - EndVoteCount) + ")", Color.Cyan);
|
||||
EndGame();
|
||||
}
|
||||
break;
|
||||
case (byte)PacketTypes.RequestNetLobbyUpdate:
|
||||
UpdateNetLobby(null, null);
|
||||
UpdateVoteStatus();
|
||||
break;
|
||||
case (byte)PacketTypes.SpectateRequest:
|
||||
if (gameStarted && AllowSpectating)
|
||||
{
|
||||
var startMessage = CreateStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset);
|
||||
server.SendMessage(startMessage, inc.SenderConnection, NetDeliveryMethod.ReliableOrdered);
|
||||
|
||||
CoroutineManager.StartCoroutine(SyncSpectator(sender));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.WarningMessage:
|
||||
Debug.WriteLine(inc.ReadString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SendMessage(NetOutgoingMessage msg, NetDeliveryMethod deliveryMethod, NetConnection excludedConnection = null)
|
||||
{
|
||||
List<NetConnection> recipients = new List<NetConnection>();
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
if (client.Connection != excludedConnection) recipients.Add(client.Connection);
|
||||
}
|
||||
|
||||
if (recipients.Count == 0) return;
|
||||
|
||||
SendMessage(msg, deliveryMethod, recipients);
|
||||
}
|
||||
|
||||
private void SendMessage(NetOutgoingMessage msg, NetDeliveryMethod deliveryMethod, List<NetConnection> recipients)
|
||||
{
|
||||
if (recipients == null) recipients = connectedClients.Select(c => c.Connection).ToList();
|
||||
|
||||
if (recipients.Count == 0) return;
|
||||
|
||||
server.SendMessage(msg, recipients, deliveryMethod, 0);
|
||||
}
|
||||
|
||||
private void SendNetworkEvents(List<Client> recipients = null)
|
||||
{
|
||||
if (NetworkEvent.Events.Count == 0) return;
|
||||
|
||||
if (recipients == null)
|
||||
{
|
||||
recipients = connectedClients.FindAll(c => c.inGame);
|
||||
}
|
||||
|
||||
if (recipients.Count == 0) return;
|
||||
|
||||
foreach (Client c in recipients)
|
||||
{
|
||||
var message = ComposeNetworkEventMessage(NetworkEventDeliveryMethod.ReliableLidgren, c.Connection);
|
||||
if (message!=null)
|
||||
{
|
||||
server.SendMessage(message, c.Connection, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
message = ComposeNetworkEventMessage(NetworkEventDeliveryMethod.Unreliable, c.Connection);
|
||||
if (message != null)
|
||||
{
|
||||
server.SendMessage(message, c.Connection, NetDeliveryMethod.Unreliable, 0);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkEvent.Events.Clear();
|
||||
}
|
||||
|
||||
private IEnumerable<object> SyncSpectator(Client sender)
|
||||
{
|
||||
yield return new WaitForSeconds(3.0f);
|
||||
|
||||
foreach (Item item in Item.Remover.removedItems)
|
||||
{
|
||||
Item.Spawner.spawnItems.Remove(item);
|
||||
}
|
||||
|
||||
SendItemRemoveMessage(Item.Remover.removedItems, new List<NetConnection>() { sender.Connection });
|
||||
SendItemSpawnMessage(Item.Spawner.spawnItems, new List<NetConnection>() { sender.Connection });
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
//save all the current events to a list and clear them
|
||||
var existingEvents = new List<NetworkEvent>(NetworkEvent.Events);
|
||||
NetworkEvent.Events.Clear();
|
||||
|
||||
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
if (!hull.FireSources.Any() && hull.Volume < 0.01f) continue;
|
||||
new NetworkEvent(NetworkEventType.ImportantEntityUpdate, hull.ID, false);
|
||||
}
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
new NetworkEvent(NetworkEventType.EntityUpdate, c.ID, false);
|
||||
if (c.Inventory != null) new NetworkEvent(NetworkEventType.InventoryUpdate, c.ID, false);
|
||||
if (c.IsDead) new NetworkEvent(NetworkEventType.KillCharacter, c.ID, false);
|
||||
}
|
||||
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
{
|
||||
bool takenDamage = false;
|
||||
for (int i = 0; i<wall.SectionCount; i++)
|
||||
{
|
||||
if (wall.SectionDamage(i) < wall.Health)
|
||||
{
|
||||
takenDamage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (takenDamage) new NetworkEvent(NetworkEventType.ImportantEntityUpdate, wall.ID, false);
|
||||
}
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
for (int i = 0; i < item.components.Count; i++)
|
||||
{
|
||||
if (!item.components[i].NetworkUpdateSent) continue;
|
||||
item.NewComponentEvent(item.components[i], false, true);
|
||||
}
|
||||
|
||||
if (item.body == null || !item.body.Enabled || item.ParentInventory!=null) continue;
|
||||
new NetworkEvent(NetworkEventType.DropItem, item.ID, false);
|
||||
}
|
||||
|
||||
List<NetworkEvent> syncMessages = new List<NetworkEvent>(NetworkEvent.Events);
|
||||
while (syncMessages.Any())
|
||||
{
|
||||
//put 5 events in the message and send them to the spectator
|
||||
NetworkEvent.Events = syncMessages.GetRange(0, Math.Min(syncMessages.Count, 5));
|
||||
SendNetworkEvents(new List<Client>() { sender });
|
||||
syncMessages.RemoveRange(0, Math.Min(syncMessages.Count, 5));
|
||||
|
||||
//restore "normal" events
|
||||
NetworkEvent.Events = existingEvents;
|
||||
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
|
||||
//save "normal" events again
|
||||
existingEvents = new List<NetworkEvent>(NetworkEvent.Events);
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
|
||||
SendRespawnManagerMsg(null, null, new List<NetConnection>() { sender.Connection });
|
||||
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
|
||||
|
||||
sender.inGame = true;
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
|
||||
public bool StartGameClicked(GUIButton button, object obj)
|
||||
{
|
||||
Submarine selectedSub = null;
|
||||
Submarine selectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle;
|
||||
|
||||
if (Voting.AllowSubVoting)
|
||||
{
|
||||
selectedSub = Voting.HighestVoted<Submarine>(VoteType.Sub, connectedClients);
|
||||
if (selectedSub == null) selectedSub = GameMain.NetLobbyScreen.SelectedSub;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedSub = GameMain.NetLobbyScreen.SelectedSub;
|
||||
}
|
||||
|
||||
if (selectedSub == null)
|
||||
{
|
||||
GameMain.NetLobbyScreen.SubList.Flash();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedShuttle == null)
|
||||
{
|
||||
GameMain.NetLobbyScreen.ShuttleList.Flash();
|
||||
return false;
|
||||
}
|
||||
|
||||
GameModePreset selectedMode = Voting.HighestVoted<GameModePreset>(VoteType.Mode, connectedClients);
|
||||
if (selectedMode == null) selectedMode = GameMain.NetLobbyScreen.SelectedMode;
|
||||
|
||||
if (selectedMode==null)
|
||||
{
|
||||
GameMain.NetLobbyScreen.ModeList.Flash();
|
||||
return false;
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitForPlayersReady(selectedSub, selectedShuttle, selectedMode), "WaitForPlayersReady");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerable<object> WaitForPlayersReady(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode)
|
||||
{
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = false;
|
||||
|
||||
NetOutgoingMessage msg = server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.CanStartGame);
|
||||
msg.Write(selectedSub.Name);
|
||||
msg.Write(selectedSub.MD5Hash.Hash);
|
||||
|
||||
msg.Write(selectedShuttle.Name);
|
||||
msg.Write(selectedShuttle.MD5Hash.Hash);
|
||||
|
||||
SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
connectedClients.ForEach(c => c.ReadyToStart = false);
|
||||
|
||||
float waitForResponseTimer = 5.0f;
|
||||
while (connectedClients.Any(c => !c.ReadyToStart) && waitForResponseTimer > 0.0f)
|
||||
{
|
||||
waitForResponseTimer -= CoroutineManager.UnscaledDeltaTime;
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
float fileTransferTimeOut = 60.0f;
|
||||
while (connectedClients.Any(c => c.FileStreamSender != null && c.FileStreamSender.FilePath == selectedSub.FilePath) && fileTransferTimeOut>0.0f)
|
||||
{
|
||||
fileTransferTimeOut -= CoroutineManager.UnscaledDeltaTime;
|
||||
|
||||
if (GUIMessageBox.MessageBoxes.Count==0)
|
||||
{
|
||||
var messageBox = new GUIMessageBox("File transfer in progress",
|
||||
"The round will be started after the submarine file has been sent to all players.", new string[] {"Cancel transfer"}, 400, 400);
|
||||
messageBox.Buttons[0].UserData = connectedClients.Find(c => c.FileStreamSender != null && c.FileStreamSender.FilePath == selectedSub.FilePath);
|
||||
messageBox.Buttons[0].OnClicked = (button, obj) =>
|
||||
{
|
||||
(button.UserData as Client).CancelTransfer();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.ShowLoading(StartGame(selectedSub, selectedShuttle, selectedMode), false);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private IEnumerable<object> StartGame(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode)
|
||||
{
|
||||
Item.Spawner.Clear();
|
||||
Item.Remover.Clear();
|
||||
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = false;
|
||||
|
||||
GUIMessageBox.CloseAll();
|
||||
|
||||
AssignJobs(connectedClients);
|
||||
|
||||
roundStartSeed = DateTime.Now.Millisecond;
|
||||
Rand.SetSyncedSeed(roundStartSeed);
|
||||
|
||||
GameMain.GameSession = new GameSession(selectedSub, "", selectedMode, Mission.MissionTypes[GameMain.NetLobbyScreen.MissionTypeIndex]);
|
||||
GameMain.GameSession.StartShift(GameMain.NetLobbyScreen.LevelSeed);
|
||||
|
||||
GameServer.Log("Starting a new round...", Color.Cyan);
|
||||
GameServer.Log("Submarine: " + selectedSub.Name, Color.Cyan);
|
||||
GameServer.Log("Game mode: " + selectedMode.Name, Color.Cyan);
|
||||
GameServer.Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, Color.Cyan);
|
||||
|
||||
if (AllowRespawn) respawnManager = new RespawnManager(this, selectedShuttle);
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
List<CharacterInfo> characterInfos = new List<CharacterInfo>();
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
client.inGame = true;
|
||||
|
||||
if (client.characterInfo == null)
|
||||
{
|
||||
client.characterInfo = new CharacterInfo(Character.HumanConfigFile, client.name);
|
||||
}
|
||||
characterInfos.Add(client.characterInfo);
|
||||
|
||||
client.characterInfo.Job = new Job(client.assignedJob);
|
||||
}
|
||||
|
||||
if (characterInfo != null)
|
||||
{
|
||||
characterInfo.Job = new Job(GameMain.NetLobbyScreen.JobPreferences[0]);
|
||||
characterInfos.Add(characterInfo);
|
||||
}
|
||||
|
||||
WayPoint[] assignedWayPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);
|
||||
|
||||
for (int i = 0; i < connectedClients.Count; i++)
|
||||
{
|
||||
connectedClients[i].Character = Character.Create(
|
||||
connectedClients[i].characterInfo, assignedWayPoints[i].WorldPosition, true, false);
|
||||
connectedClients[i].Character.GiveJobItems(assignedWayPoints[i]);
|
||||
|
||||
GameMain.GameSession.CrewManager.characters.Add(connectedClients[i].Character);
|
||||
}
|
||||
|
||||
if (characterInfo != null)
|
||||
{
|
||||
myCharacter = Character.Create(characterInfo, assignedWayPoints[assignedWayPoints.Length - 1].WorldPosition, false, false);
|
||||
Character.Controlled = myCharacter;
|
||||
|
||||
myCharacter.GiveJobItems(assignedWayPoints[assignedWayPoints.Length - 1]);
|
||||
|
||||
GameMain.GameSession.CrewManager.characters.Add(myCharacter);
|
||||
}
|
||||
|
||||
var startMessage = CreateStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset);
|
||||
|
||||
SendMessage(startMessage, NetDeliveryMethod.ReliableOrdered);
|
||||
|
||||
//SendItemSpawnMessage(allItems, inventories);
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
UpdateCrewFrame();
|
||||
|
||||
if (TraitorsEnabled == YesNoMaybe.Yes ||
|
||||
(TraitorsEnabled == YesNoMaybe.Maybe && Rand.Range(0.0f, 1.0f) < 0.5f))
|
||||
{
|
||||
TraitorManager = new TraitorManager(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
TraitorManager = null;
|
||||
}
|
||||
|
||||
//give some time for the clients to load the map
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
|
||||
gameStarted = true;
|
||||
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
if (myCharacter == null)
|
||||
{
|
||||
AddChatMessage("Press TAB to chat. Use ''d;'' to talk to dead players and spectators, "
|
||||
+ "and ''player name;'' to only send the message to a specific player.", ChatMessageType.Server);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddChatMessage("Press TAB to chat. Use ''r;'' to talk through the radio.", ChatMessageType.Server);
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = true;
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private NetOutgoingMessage CreateStartMessage(int seed, Submarine selectedSub, GameModePreset selectedMode)
|
||||
{
|
||||
NetOutgoingMessage msg = server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.StartGame);
|
||||
|
||||
msg.Write(seed);
|
||||
|
||||
msg.Write(GameMain.NetLobbyScreen.LevelSeed);
|
||||
|
||||
msg.Write((byte)GameMain.NetLobbyScreen.MissionTypeIndex);
|
||||
|
||||
msg.Write(selectedSub.Name);
|
||||
msg.Write(selectedSub.MD5Hash.Hash);
|
||||
|
||||
msg.Write(GameMain.NetLobbyScreen.SelectedShuttle.Name);
|
||||
msg.Write(GameMain.NetLobbyScreen.SelectedShuttle.MD5Hash.Hash);
|
||||
|
||||
msg.Write(selectedMode.Name);
|
||||
|
||||
msg.Write(AllowRespawn);
|
||||
|
||||
//msg.Write(GameMain.NetLobbyScreen.GameDuration.TotalMinutes);
|
||||
|
||||
var characters = Character.CharacterList.FindAll(c => !(c is AICharacter) || c.SpawnedMidRound);
|
||||
|
||||
msg.Write((byte)characters.Count);
|
||||
foreach (Character c in characters)
|
||||
{
|
||||
WriteCharacterData(msg, c.Name, c);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void EndGame()
|
||||
{
|
||||
if (!gameStarted) return;
|
||||
@@ -1029,114 +480,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(EndCinematic());
|
||||
}
|
||||
|
||||
public IEnumerable<object> EndCinematic()
|
||||
{
|
||||
float endPreviewLength = 10.0f;
|
||||
|
||||
var cinematic = new TransitionCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, endPreviewLength);
|
||||
|
||||
float secondsLeft = endPreviewLength;
|
||||
|
||||
do
|
||||
{
|
||||
secondsLeft -= CoroutineManager.UnscaledDeltaTime;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (secondsLeft > 0.0f);
|
||||
|
||||
Submarine.Unload();
|
||||
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void SendRespawnManagerMsg(List<Character> spawnedCharacters = null, List<Item> spawnedItems = null, List<NetConnection> recipients = null)
|
||||
{
|
||||
if (respawnManager == null) return;
|
||||
|
||||
NetOutgoingMessage msg = server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Respawn);
|
||||
|
||||
respawnManager.WriteNetworkEvent(msg, spawnedCharacters, spawnedItems);
|
||||
|
||||
SendMessage(msg, NetDeliveryMethod.ReliableUnordered, recipients);
|
||||
}
|
||||
|
||||
private void DisconnectClient(NetConnection senderConnection, string msg = "", string targetmsg = "")
|
||||
{
|
||||
Client client = connectedClients.Find(x => x.Connection == senderConnection);
|
||||
if (client == null) return;
|
||||
|
||||
DisconnectClient(client, msg, targetmsg);
|
||||
}
|
||||
|
||||
private void DisconnectClient(Client client, string msg = "", string targetmsg = "")
|
||||
{
|
||||
if (client == null) return;
|
||||
|
||||
if (gameStarted && client.Character != null)
|
||||
{
|
||||
client.Character.ClearInputs();
|
||||
client.Character.Kill(CauseOfDeath.Disconnected, true);
|
||||
}
|
||||
|
||||
client.Character = null;
|
||||
client.inGame = false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(msg)) msg = client.name + " has left the server";
|
||||
if (string.IsNullOrWhiteSpace(targetmsg)) targetmsg = "You have left the server";
|
||||
|
||||
Log(msg, ChatMessage.MessageColor[(int)ChatMessageType.Server]);
|
||||
|
||||
client.Connection.Disconnect(targetmsg);
|
||||
|
||||
//notify other players about the disconnected client
|
||||
NetOutgoingMessage outmsg = server.CreateMessage();
|
||||
outmsg.Write((byte)PacketTypes.PlayerLeft);
|
||||
outmsg.Write(client.ID);
|
||||
outmsg.Write(msg);
|
||||
|
||||
GameMain.NetLobbyScreen.RemovePlayer(client.name);
|
||||
|
||||
if (server.Connections.Count > 0)
|
||||
{
|
||||
server.SendMessage(outmsg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
connectedClients.Remove(client);
|
||||
if (client.FileStreamSender != null)
|
||||
{
|
||||
client.FileStreamSender.Dispose();
|
||||
client.FileStreamSender = null;
|
||||
}
|
||||
|
||||
AddChatMessage(msg, ChatMessageType.Server);
|
||||
|
||||
UpdateCrewFrame();
|
||||
|
||||
refreshMasterTimer = DateTime.Now;
|
||||
}
|
||||
|
||||
|
||||
private void UpdateCrewFrame()
|
||||
{
|
||||
List<Character> crew = new List<Character>();
|
||||
@@ -1152,92 +503,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
//if (GameMain.GameSession!=null) GameMain.GameSession.CrewManager.CreateCrewFrame(crew);
|
||||
}
|
||||
|
||||
public override void KickPlayer(string playerName, bool ban)
|
||||
{
|
||||
playerName = playerName.ToLowerInvariant();
|
||||
|
||||
Client client = connectedClients.Find(c =>
|
||||
c.name.ToLowerInvariant() == playerName ||
|
||||
(c.Character != null && c.Character.Name.ToLowerInvariant() == playerName));
|
||||
|
||||
KickClient(client, ban);
|
||||
}
|
||||
|
||||
public void KickClient(Client client, bool ban = false)
|
||||
{
|
||||
if (client == null) return;
|
||||
|
||||
if (ban)
|
||||
{
|
||||
DisconnectClient(client, client.name + " has been banned from the server", "You have been banned from the server");
|
||||
banList.BanPlayer(client.name, client.Connection.RemoteEndPoint.Address.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
DisconnectClient(client, client.name + " has been kicked from the server", "You have been kicked from the server");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFileTransfer(Client client, float deltaTime)
|
||||
{
|
||||
if (client.FileStreamSender == null) return;
|
||||
|
||||
var clientNameBox = GameMain.NetLobbyScreen.PlayerList.FindChild(client.name);
|
||||
var clientInfo = clientNameBox.FindChild(client.FileStreamSender);
|
||||
|
||||
if (clientInfo == null)
|
||||
{
|
||||
clientNameBox.ClearChildren();
|
||||
|
||||
clientInfo = new GUIFrame(new Rectangle(0, 0, 180, 0), Color.Transparent, Alignment.TopRight, null, clientNameBox);
|
||||
clientInfo.UserData = client.FileStreamSender;
|
||||
new GUIProgressBar(new Rectangle(0, 4, 160, clientInfo.Rect.Height - 8), Color.Green, GUI.Style, 0.0f, Alignment.Left, clientInfo).IsHorizontal = true;
|
||||
new GUITextBlock(new Rectangle(0, 2, 160, 0), "", GUI.Style, Alignment.TopLeft, Alignment.Left | Alignment.CenterY, clientInfo, true, GUI.SmallFont);
|
||||
|
||||
var cancelButton = new GUIButton(new Rectangle(20, 0, 14, 0), "X", Alignment.Right, GUI.Style, clientInfo);
|
||||
cancelButton.OnClicked = (GUIButton button, object userdata) =>
|
||||
{
|
||||
(cancelButton.Parent.UserData as FileStreamSender).CancelTransfer();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
var progressBar = clientInfo.GetChild<GUIProgressBar>();
|
||||
progressBar.BarSize = client.FileStreamSender.Progress;
|
||||
|
||||
var progressText = clientInfo.GetChild<GUITextBlock>();
|
||||
progressText.Text = client.FileStreamSender.FileName + " " +
|
||||
MathUtils.GetBytesReadable(client.FileStreamSender.Sent) + " / " + MathUtils.GetBytesReadable(client.FileStreamSender.FileSize);
|
||||
}
|
||||
|
||||
client.FileStreamSender.Update(deltaTime);
|
||||
|
||||
if (client.FileStreamSender.Status != FileTransferStatus.Sending &&
|
||||
client.FileStreamSender.Status != FileTransferStatus.NotStarted)
|
||||
{
|
||||
if (client.FileStreamSender.Status == FileTransferStatus.Canceled)
|
||||
{
|
||||
SendCancelTransferMessage(client, "File transfer was canceled by the server.");
|
||||
}
|
||||
|
||||
clientNameBox.RemoveChild(clientInfo);
|
||||
|
||||
client.FileStreamSender.Dispose();
|
||||
client.FileStreamSender = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void SendCancelTransferMessage(Client client, string message)
|
||||
{
|
||||
var outmsg = server.CreateMessage();
|
||||
outmsg.Write((byte)PacketTypes.RequestFile);
|
||||
outmsg.Write(false);
|
||||
outmsg.Write(message);
|
||||
server.SendMessage(outmsg, client.Connection, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
|
||||
public void NewTraitor(Character traitor, Character target)
|
||||
{
|
||||
Log(traitor.Name + " is the traitor and the target is " + target.Name, Color.Cyan);
|
||||
@@ -1249,14 +515,7 @@ namespace Barotrauma.Networking
|
||||
traitorClient = c;
|
||||
break;
|
||||
}
|
||||
|
||||
NetOutgoingMessage msg = server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Traitor);
|
||||
msg.Write(target.Info.Name);
|
||||
if (server.Connections.Count > 0)
|
||||
{
|
||||
server.SendMessage(msg, traitorClient.Connection, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||
|
||||
@@ -27,250 +27,6 @@ namespace Barotrauma.Networking
|
||||
partial class GameServer : NetworkMember, IPropertyObject
|
||||
{
|
||||
List<UnauthenticatedClient> unauthenticatedClients = new List<UnauthenticatedClient>();
|
||||
|
||||
private void HandleConnectionApproval(NetIncomingMessage inc)
|
||||
{
|
||||
if ((PacketTypes)inc.ReadByte() != PacketTypes.Login) return;
|
||||
|
||||
if (banList.IsBanned(inc.SenderEndPoint.Address.ToString()))
|
||||
{
|
||||
inc.SenderConnection.Deny("You have been banned from the server");
|
||||
DebugConsole.NewMessage("Banned player tried to join the server", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connectedClients.Any(c => c.Connection == inc.SenderConnection))
|
||||
{
|
||||
inc.SenderConnection.Deny("Connection error - already joined");
|
||||
return;
|
||||
}
|
||||
|
||||
int nonce = CryptoRandom.Instance.Next();
|
||||
var msg = server.CreateMessage();
|
||||
msg.Write(nonce);
|
||||
|
||||
unauthenticatedClients.Add(new UnauthenticatedClient(inc.SenderConnection, nonce));
|
||||
|
||||
inc.SenderConnection.Approve(msg);
|
||||
}
|
||||
|
||||
private void CheckAuthentication(NetIncomingMessage inc)
|
||||
{
|
||||
var unauthenticatedClient = unauthenticatedClients.Find(uc => uc.Connection == inc.SenderConnection);
|
||||
if (unauthenticatedClient != null)
|
||||
{
|
||||
unauthenticatedClients.Remove(unauthenticatedClient);
|
||||
|
||||
string saltedPw = password;
|
||||
saltedPw = saltedPw + Convert.ToString(unauthenticatedClient.Nonce);
|
||||
saltedPw = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(saltedPw)));
|
||||
NetEncryption algo = new NetXtea(server, saltedPw);
|
||||
inc.Decrypt(algo);
|
||||
|
||||
string rdPw = inc.ReadString();
|
||||
if (rdPw != saltedPw)
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Wrong password!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Authentication failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConnectedClients.Count>=config.MaximumConnections)
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Server full");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugConsole.NewMessage("New player has joined the server", Color.White);
|
||||
|
||||
byte userID;
|
||||
string version = "", packageName = "", packageHash = "", name = "";
|
||||
try
|
||||
{
|
||||
userID = inc.ReadByte();
|
||||
version = inc.ReadString();
|
||||
packageName = inc.ReadString();
|
||||
packageHash = inc.ReadString();
|
||||
name = Client.SanitizeName(inc.ReadString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Connection error - server failed to read your ConnectionApproval message");
|
||||
DebugConsole.NewMessage("Connection error - server failed to read the ConnectionApproval message", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Invalid username");
|
||||
DebugConsole.NewMessage(name + " couldn't join the server (name empty)", Color.Red);
|
||||
return;
|
||||
}
|
||||
else if (!Client.IsValidName(name))
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Username contains illegal symbols");
|
||||
DebugConsole.NewMessage(name + " couldn't join the server (username contains illegal symbols)", Color.Red);
|
||||
return;
|
||||
|
||||
}
|
||||
else if (version != GameMain.Version.ToString())
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Version " + GameMain.Version + " required to connect to the server (Your version: " + version + ")");
|
||||
DebugConsole.NewMessage(name + " couldn't join the server (wrong game version)", Color.Red);
|
||||
return;
|
||||
}
|
||||
else if (packageName != GameMain.SelectedPackage.Name)
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Your content package (" + packageName + ") doesn't match the server's version (" + GameMain.SelectedPackage.Name + ")");
|
||||
DebugConsole.NewMessage(name + " couldn't join the server (wrong content package name)", Color.Red);
|
||||
return;
|
||||
}
|
||||
else if (packageHash != GameMain.SelectedPackage.MD5hash.Hash)
|
||||
{
|
||||
inc.SenderConnection.Disconnect("Your content package (MD5: " + packageHash + ") doesn't match the server's version (MD5: " + GameMain.SelectedPackage.MD5hash.Hash + ")");
|
||||
DebugConsole.NewMessage(name + " couldn't join the server (wrong content package hash)", Color.Red);
|
||||
return;
|
||||
}
|
||||
else if (connectedClients.Any(c => c.name.ToLower() == name.ToLower() && c.Connection != inc.SenderConnection))
|
||||
{
|
||||
inc.SenderConnection.Disconnect("The name ''" + name + "'' is already in use. Please choose another name.");
|
||||
DebugConsole.NewMessage(name + " couldn't join the server (name already in use)", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//existing user re-joining
|
||||
if (userID > 0)
|
||||
{
|
||||
Client existingClient = connectedClients.Find(c =>
|
||||
c.ID == userID &&
|
||||
c.Connection == inc.SenderConnection);
|
||||
|
||||
if (existingClient == null)
|
||||
{
|
||||
existingClient = disconnectedClients.Find(c =>
|
||||
c.ID == userID &&
|
||||
c.Connection == inc.SenderConnection);
|
||||
|
||||
if (existingClient != null)
|
||||
{
|
||||
disconnectedClients.Remove(existingClient);
|
||||
connectedClients.Add(existingClient);
|
||||
|
||||
UpdateCrewFrame();
|
||||
}
|
||||
}
|
||||
if (existingClient != null)
|
||||
{
|
||||
existingClient.Connection = inc.SenderConnection;
|
||||
LogClientIn(inc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
userID = 1;
|
||||
while (connectedClients.Any(c => c.ID == userID))
|
||||
{
|
||||
userID++;
|
||||
}
|
||||
|
||||
Client newClient = new Client(server, name, userID);
|
||||
newClient.Connection = inc.SenderConnection;
|
||||
newClient.version = version;
|
||||
|
||||
var savedPermissions = clientPermissions.Find(cp => cp.IP == newClient.Connection.RemoteEndPoint.Address.ToString());
|
||||
if (savedPermissions != null)
|
||||
{
|
||||
newClient.SetPermissions(savedPermissions.Permissions);
|
||||
}
|
||||
|
||||
connectedClients.Add(newClient);
|
||||
|
||||
UpdateCrewFrame();
|
||||
|
||||
LogClientIn(inc);
|
||||
|
||||
refreshMasterTimer = DateTime.Now;
|
||||
}
|
||||
|
||||
private void LogClientIn(NetIncomingMessage inc)
|
||||
{
|
||||
Client sender = connectedClients.Find(x => x.Connection == inc.SenderConnection);
|
||||
|
||||
if (sender == null) return;
|
||||
|
||||
if (sender.version != GameMain.Version.ToString())
|
||||
{
|
||||
DisconnectClient(sender, sender.name + " was unable to connect to the server (nonmatching game version)",
|
||||
"Version " + GameMain.Version + " required to connect to the server (Your version: " + sender.version + ")");
|
||||
}
|
||||
else if (connectedClients.Find(x => x.name == sender.name && x != sender) != null)
|
||||
{
|
||||
DisconnectClient(sender, sender.name + " was unable to connect to the server (name already in use)",
|
||||
"The name ''" + sender.name + "'' is already in use. Please choose another name.");
|
||||
}
|
||||
else
|
||||
{
|
||||
//AssignJobs();
|
||||
|
||||
GameMain.NetLobbyScreen.RemovePlayer(sender.name);
|
||||
GameMain.NetLobbyScreen.AddPlayer(sender.name);
|
||||
|
||||
// Notify the client that they have logged in
|
||||
var outmsg = server.CreateMessage();
|
||||
|
||||
outmsg.Write((byte)PacketTypes.LoggedIn);
|
||||
outmsg.Write(sender.ID);
|
||||
outmsg.Write((int)sender.Permissions);
|
||||
outmsg.Write(gameStarted);
|
||||
outmsg.Write(gameStarted && sender.Character != null && !sender.Character.IsDead);
|
||||
outmsg.Write(AllowSpectating);
|
||||
|
||||
//notify the client about other clients already logged in
|
||||
outmsg.Write((byte)((characterInfo == null) ? connectedClients.Count - 1 : connectedClients.Count));
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
if (c.Connection == inc.SenderConnection) continue;
|
||||
outmsg.Write(c.name);
|
||||
outmsg.Write(c.ID);
|
||||
}
|
||||
|
||||
if (characterInfo != null)
|
||||
{
|
||||
outmsg.Write(characterInfo.Name);
|
||||
outmsg.Write((byte)0);
|
||||
}
|
||||
|
||||
var subs = GameMain.NetLobbyScreen.GetSubList();
|
||||
outmsg.Write((byte)subs.Count);
|
||||
foreach (Submarine sub in subs)
|
||||
{
|
||||
outmsg.Write(sub.Name);
|
||||
outmsg.Write(sub.MD5Hash.Hash);
|
||||
}
|
||||
|
||||
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);
|
||||
outmsg.Write(sender.ID);
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,8 +214,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
doc.Root.SetAttributeValue("SubSelection", subSelectionMode.ToString());
|
||||
doc.Root.SetAttributeValue("ModeSelection", modeSelectionMode.ToString());
|
||||
|
||||
doc.Root.SetAttributeValue("MaxFileTransferDuration", FileStreamSender.MaxTransferDuration.TotalSeconds);
|
||||
|
||||
XmlWriterSettings settings = new XmlWriterSettings();
|
||||
settings.Indent = true;
|
||||
@@ -250,8 +248,6 @@ namespace Barotrauma.Networking
|
||||
Enum.TryParse<SelectionMode>(ToolBox.GetAttributeString(doc.Root, "ModeSelection", "Manual"), out modeSelectionMode);
|
||||
Voting.AllowModeVoting = modeSelectionMode == SelectionMode.Vote;
|
||||
|
||||
FileStreamSender.MaxTransferDuration = new TimeSpan(0,0,ToolBox.GetAttributeInt(doc.Root, "MaxFileTransferDuration", 150));
|
||||
|
||||
showLogButton.Visible = SaveServerLogs;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,45 +9,6 @@ using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
enum PacketTypes : byte
|
||||
{
|
||||
Unknown,
|
||||
|
||||
Login, LoggedIn,
|
||||
|
||||
PlayerJoined, PlayerLeft,
|
||||
|
||||
KickPlayer,
|
||||
|
||||
Permissions,
|
||||
|
||||
RequestNetLobbyUpdate,
|
||||
|
||||
StartGame, EndGame, CanStartGame,
|
||||
|
||||
NewItem, RemoveItem,
|
||||
|
||||
NewCharacter,
|
||||
|
||||
CharacterInfo,
|
||||
|
||||
Chatmessage, UpdateNetLobby,
|
||||
|
||||
NetworkEvent,
|
||||
|
||||
Traitor,
|
||||
|
||||
Vote, VoteStatus,
|
||||
|
||||
ResendRequest, ReliableMessage, LatestMessageID,
|
||||
|
||||
RequestFile, FileStream,
|
||||
|
||||
SpectateRequest,
|
||||
|
||||
Respawn
|
||||
}
|
||||
|
||||
enum VoteType
|
||||
{
|
||||
Unknown,
|
||||
@@ -152,65 +113,6 @@ namespace Barotrauma.Networking
|
||||
Voting = new Voting();
|
||||
}
|
||||
|
||||
protected NetOutgoingMessage ComposeNetworkEventMessage(NetworkEventDeliveryMethod deliveryMethod, NetConnection excludedConnection = null)
|
||||
{
|
||||
if (netPeer == null) return null;
|
||||
|
||||
var events = NetworkEvent.Events.FindAll(e => e.DeliveryMethod == deliveryMethod);
|
||||
if (events.Count == 0) return null;
|
||||
|
||||
List<byte[]> msgBytes = new List<byte[]>();
|
||||
|
||||
foreach (NetworkEvent networkEvent in events)
|
||||
{
|
||||
if (excludedConnection != null && networkEvent.SenderConnection == excludedConnection) continue;
|
||||
|
||||
NetBuffer tempMessage = new NetBuffer();// server.CreateMessage();
|
||||
if (!networkEvent.FillData(tempMessage)) continue;
|
||||
tempMessage.WritePadBits();
|
||||
|
||||
tempMessage.Position = 0;
|
||||
msgBytes.Add(tempMessage.ReadBytes(tempMessage.LengthBytes));
|
||||
|
||||
#if DEBUG
|
||||
string msgType = networkEvent.Type.ToString();
|
||||
if (networkEvent.Type == NetworkEventType.EntityUpdate)
|
||||
{
|
||||
msgType += " (" + Entity.FindEntityByID(networkEvent.ID) + ")";
|
||||
}
|
||||
|
||||
long sentBytes = 0;
|
||||
if (!messageCount.TryGetValue(msgType, out sentBytes))
|
||||
{
|
||||
messageCount.Add(msgType, tempMessage.LengthBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
messageCount[msgType] += tempMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (msgBytes.Count == 0) return null;
|
||||
|
||||
NetOutgoingMessage message = netPeer.CreateMessage();
|
||||
message.Write((byte)PacketTypes.NetworkEvent);
|
||||
|
||||
message.Write((float)NetTime.Now);
|
||||
|
||||
message.Write((byte)msgBytes.Count);
|
||||
foreach (byte[] msgData in msgBytes)
|
||||
{
|
||||
if (msgData.Length > 255) DebugConsole.ThrowError("Too large networkevent (" + msgData.Length + " bytes)");
|
||||
|
||||
message.Write((byte)msgData.Length);
|
||||
message.Write(msgData);
|
||||
}
|
||||
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public bool TypingChatMessage(GUITextBox textBox, string text)
|
||||
{
|
||||
string tempStr;
|
||||
|
||||
@@ -161,7 +161,6 @@ namespace Barotrauma.Networking
|
||||
if (!CountdownStarted)
|
||||
{
|
||||
CountdownStarted = true;
|
||||
server.SendRespawnManagerMsg();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -209,7 +208,6 @@ namespace Barotrauma.Networking
|
||||
state = State.Returning;
|
||||
|
||||
CountdownStarted = false;
|
||||
server.SendRespawnManagerMsg();
|
||||
shuttleReturnTimer = maxTransportTime;
|
||||
shuttleTransportTimer = maxTransportTime;
|
||||
}
|
||||
@@ -275,8 +273,6 @@ namespace Barotrauma.Networking
|
||||
state = State.Waiting;
|
||||
respawnTimer = respawnInterval;
|
||||
CountdownStarted = false;
|
||||
|
||||
server.SendRespawnManagerMsg();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -459,103 +455,8 @@ namespace Barotrauma.Networking
|
||||
character.GiveJobItems(mainSubSpawnPoints[i]);
|
||||
GameMain.GameSession.CrewManager.characters.Add(character);
|
||||
}
|
||||
|
||||
server.SendRespawnManagerMsg(spawnedCharacters, spawnedItems);
|
||||
}
|
||||
|
||||
public void WriteNetworkEvent(NetOutgoingMessage msg, List<Character> spawnedCharacters, List<Item> spawnedItems)
|
||||
{
|
||||
var server = networkMember as GameServer;
|
||||
|
||||
msg.WriteRangedInteger(0, Enum.GetNames(typeof(State)).Length, (int)state);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case State.Transporting:
|
||||
msg.Write(maxTransportTime);
|
||||
|
||||
if (spawnedCharacters == null)
|
||||
{
|
||||
msg.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write((byte)spawnedCharacters.Count);
|
||||
foreach (Character character in spawnedCharacters)
|
||||
{
|
||||
if (character == server.Character)
|
||||
{
|
||||
msg.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ownerClient = server.ConnectedClients.Find(cl => cl.Character == character);
|
||||
msg.Write((byte)ownerClient.ID);
|
||||
}
|
||||
|
||||
server.WriteCharacterData(msg, character.Name, character);
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnedItems != null) GameMain.Server.SendItemSpawnMessage(spawnedItems);
|
||||
break;
|
||||
case State.Waiting:
|
||||
msg.Write(CountdownStarted);
|
||||
msg.Write(respawnTimer);
|
||||
break;
|
||||
case State.Returning:
|
||||
//CoroutineManager.StopCoroutines("forcepos");
|
||||
//CoroutineManager.StartCoroutine(
|
||||
// ForceShuttleToPos(new Vector2(Level.Loaded.StartPosition.X, Level.Loaded.Size.Y + 1000.0f), 100.0f), "forcepos");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadNetworkEvent(NetIncomingMessage inc)
|
||||
{
|
||||
var newState = (State)inc.ReadRangedInteger(0, Enum.GetNames(typeof(State)).Length);
|
||||
|
||||
switch (newState)
|
||||
{
|
||||
case State.Transporting:
|
||||
maxTransportTime = inc.ReadSingle();
|
||||
|
||||
CountdownStarted = false;
|
||||
|
||||
var client = networkMember as GameClient;
|
||||
int clientCount = inc.ReadByte();
|
||||
|
||||
//respawning characters -> reset shuttle
|
||||
if (clientCount > 0) ResetShuttle();
|
||||
|
||||
for (int i = 0; i < clientCount; i++)
|
||||
{
|
||||
byte clientId = inc.ReadByte();
|
||||
|
||||
var character = client.ReadCharacterData(inc);
|
||||
}
|
||||
|
||||
if (state != newState)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
|
||||
}
|
||||
|
||||
break;
|
||||
case State.Waiting:
|
||||
CountdownStarted = inc.ReadBoolean();
|
||||
|
||||
ResetShuttle();
|
||||
|
||||
respawnTimer = inc.ReadSingle();
|
||||
break;
|
||||
case State.Returning:
|
||||
|
||||
CountdownStarted = false;
|
||||
break;
|
||||
}
|
||||
|
||||
state = newState;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user