diff --git a/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs b/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs index 40d499b0d..f6d32d702 100644 --- a/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs +++ b/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs @@ -154,6 +154,11 @@ namespace Barotrauma.Networking public FileReceiver(string downloadFolder) { + if (GameMain.Server != null) + { + throw new InvalidOperationException("Creating a file receiver is not allowed when a server is running."); + } + activeTransfers = new List(); this.downloadFolder = downloadFolder; @@ -161,6 +166,11 @@ namespace Barotrauma.Networking public void ReadMessage(NetIncomingMessage inc) { + if (GameMain.Server != null) + { + throw new InvalidOperationException("Receiving files when a server is running is not allowed"); + } + System.Diagnostics.Debug.Assert(!activeTransfers.Any(t => t.Status == FileTransferStatus.Error || t.Status == FileTransferStatus.Canceled || diff --git a/Subsurface/Source/Networking/FileTransfer/FileSender.cs b/Subsurface/Source/Networking/FileTransfer/FileSender.cs index 1517cb215..2fe9085b9 100644 --- a/Subsurface/Source/Networking/FileTransfer/FileSender.cs +++ b/Subsurface/Source/Networking/FileTransfer/FileSender.cs @@ -109,6 +109,11 @@ namespace Barotrauma.Networking private NetPeer peer; + public List ActiveTransfers + { + get { return activeTransfers; } + } + public FileSender(NetworkMember networkMember) { peer = networkMember.netPeer; diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index e37f7a63f..aceb21c97 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -629,6 +629,10 @@ namespace Barotrauma.Networking { if (Character != null) Character.Remove(); + //enable spectate button in case we fail to start the round now + //(for example, due to a missing sub file or an error) + GameMain.NetLobbyScreen.ShowSpectateButton(); + Entity.Spawner.Clear(); entityEventManager.Clear(); LastSentEntityEventID = 0; @@ -999,6 +1003,15 @@ namespace Barotrauma.Networking client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); } + public void CancelFileTransfer(FileReceiver.FileTransferIn transfer) + { + NetOutgoingMessage msg = client.CreateMessage(); + msg.Write((byte)ClientPacketHeader.FILE_REQUEST); + msg.Write((byte)FileTransferMessageType.Cancel); + msg.Write((byte)transfer.SequenceChannel); + client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); + } + private void OnFileReceived(FileReceiver.FileTransferIn transfer) { new GUIMessageBox("Download finished", "File \"" + transfer.FileName + "\" was downloaded succesfully."); @@ -1062,8 +1075,9 @@ namespace Barotrauma.Networking MathUtils.GetBytesReadable((long)transfer.Received) + " / " + MathUtils.GetBytesReadable((long)transfer.FileSize), Color.White, null, 0, GUI.SmallFont); - if (GUI.DrawButton(spriteBatch, new Rectangle((int)pos.X + 140, (int)pos.Y + 15, 60, 15), "Cancel", new Color(0.47f, 0.13f, 0.15f, 0.08f))) + if (GUI.DrawButton(spriteBatch, new Rectangle((int)pos.X + 140, (int)pos.Y + 18, 60, 15), "Cancel", new Color(0.47f, 0.13f, 0.15f, 0.08f))) { + CancelFileTransfer(transfer); fileReceiver.StopTransfer(transfer); } @@ -1210,12 +1224,12 @@ namespace Barotrauma.Networking public bool SpectateClicked(GUIButton button, object userData) { if (button != null) button.Enabled = false; - + NetOutgoingMessage readyToStartMsg = client.CreateMessage(); readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME); - //correct sub & shuttle files found - //TODO: check if they're actually found + //assume we have the required sub files to start the round + //(if not, we'll find out when the server sends the STARTGAME message and can initiate a file transfer) readyToStartMsg.Write(true); WriteCharacterInfo(readyToStartMsg); diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 104b87252..779f15832 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -982,14 +982,32 @@ namespace Barotrauma.Networking server.SendMessage(msg, connectedClients.Select(c => c.Connection).ToList(), NetDeliveryMethod.ReliableUnordered, 0); //give the clients a few seconds to request missing sub/shuttle files before starting the round - float waitForResponseTimer = 3.0f; + float waitForResponseTimer = 5.0f; while (connectedClients.Any(c => !c.ReadyToStart) && waitForResponseTimer > 0.0f) { waitForResponseTimer -= CoroutineManager.UnscaledDeltaTime; yield return CoroutineStatus.Running; } - //todo: wait until file transfers are finished/cancelled + if (fileSender.ActiveTransfers.Count > 0) + { + var msgBox = new GUIMessageBox("", "Waiting for file transfers to finish before starting the round...", new string[] { "Start now" }); + msgBox.Buttons[0].OnClicked += msgBox.Close; + + float waitForTransfersTimer = 20.0f; + while (fileSender.ActiveTransfers.Count > 0 && waitForTransfersTimer > 0.0f) + { + waitForTransfersTimer -= CoroutineManager.UnscaledDeltaTime; + + //message box close, break and start the round immediately + if (!GUIMessageBox.MessageBoxes.Contains(msgBox)) + { + break; + } + + yield return CoroutineStatus.Running; + } + } } GameMain.ShowLoading(StartGame(selectedSub, selectedShuttle, selectedMode), false); diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs index ee4b9f324..d076b539d 100644 --- a/Subsurface/Source/Screens/NetLobbyScreen.cs +++ b/Subsurface/Source/Screens/NetLobbyScreen.cs @@ -473,6 +473,16 @@ namespace Barotrauma base.Select(); } + public void ShowSpectateButton() + { + if (GameMain.Client == null) return; + + infoFrame.RemoveChild(infoFrame.children.Find(c => c.UserData as string == "spectateButton")); + GUIButton spectateButton = new GUIButton(new Rectangle(0, 0, 80, 30), "Spectate", Alignment.BottomRight, GUI.Style, infoFrame); + spectateButton.OnClicked = GameMain.Client.SpectateClicked; + spectateButton.UserData = "spectateButton"; + } + private void UpdatePlayerFrame(CharacterInfo characterInfo) { if (myPlayerFrame.children.Count <= 1) @@ -1227,16 +1237,14 @@ namespace Barotrauma errorMsg += "Do you want to download the file from the server host?"; - if (GUIMessageBox.MessageBoxes.Count > 0) + //already showing a message about the same sub + if (GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "request" + subName)) { - var currentMessageBox = GUIMessageBox.VisibleBox; - if (currentMessageBox != null && currentMessageBox.UserData as string == subName) - { - return false; - } + return false; } var requestFileBox = new GUIMessageBox("Submarine not found!", errorMsg, new string[] { "Yes", "No" }, 400, 300); + requestFileBox.UserData = "request" + subName; requestFileBox.Buttons[0].UserData = subName; requestFileBox.Buttons[0].OnClicked += requestFileBox.Close; requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>