From a1342fdc454dc7cb456960e2be4b8f1f3ea01699 Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 10 Mar 2017 19:16:17 +0200 Subject: [PATCH] Server-side file transfer UI, server notifies the recipient of a file transfer if the transfer is cancelled, fixed TextGetter not working on wrapped GUITextBlocks --- Subsurface/Source/GUI/GUITextBlock.cs | 2 +- .../Networking/FileTransfer/FileReceiver.cs | 7 ++- .../Networking/FileTransfer/FileSender.cs | 24 ++++++++- Subsurface/Source/Networking/GameServer.cs | 53 +++++++++++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/Subsurface/Source/GUI/GUITextBlock.cs b/Subsurface/Source/GUI/GUITextBlock.cs index 5e3ef7697..36e58fb40 100644 --- a/Subsurface/Source/GUI/GUITextBlock.cs +++ b/Subsurface/Source/GUI/GUITextBlock.cs @@ -259,7 +259,7 @@ namespace Barotrauma base.Draw(spriteBatch); - if (TextGetter != null) text = TextGetter(); + if (TextGetter != null) Text = TextGetter(); if (!string.IsNullOrEmpty(text)) { diff --git a/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs b/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs index f6d32d702..2708c43a2 100644 --- a/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs +++ b/Subsurface/Source/Networking/FileTransfer/FileReceiver.cs @@ -266,8 +266,11 @@ namespace Barotrauma.Networking case (byte)FileTransferMessageType.Cancel: byte sequenceChannel = inc.ReadByte(); var matchingTransfer = activeTransfers.Find(t => t.Connection == inc.SenderConnection && t.SequenceChannel == sequenceChannel); - if (matchingTransfer != null) StopTransfer(matchingTransfer); - + if (matchingTransfer != null) + { + new GUIMessageBox("File transfer cancelled", "The server has cancelled the transfer of the file \"" + matchingTransfer.FileName + "\"."); + StopTransfer(matchingTransfer); + } break; } } diff --git a/Subsurface/Source/Networking/FileTransfer/FileSender.cs b/Subsurface/Source/Networking/FileTransfer/FileSender.cs index 2fe9085b9..0368f60f0 100644 --- a/Subsurface/Source/Networking/FileTransfer/FileSender.cs +++ b/Subsurface/Source/Networking/FileTransfer/FileSender.cs @@ -102,6 +102,10 @@ namespace Barotrauma.Networking const int MaxTransferCountPerRecipient = 5; public static TimeSpan MaxTransferDuration = new TimeSpan(0, 2, 0); + + public delegate void FileTransferDelegate(FileTransferOut fileStreamReceiver); + public FileTransferDelegate OnStarted; + public FileTransferDelegate OnEnded; private List activeTransfers; @@ -156,6 +160,8 @@ namespace Barotrauma.Networking DebugConsole.ThrowError("Failed to initiate file transfer", e); } + OnStarted(transfer); + return transfer; } @@ -163,6 +169,18 @@ namespace Barotrauma.Networking { activeTransfers.RemoveAll(t => t.Connection.Status != NetConnectionStatus.Connected); + var endedTransfers = activeTransfers.FindAll(t => + t.Connection.Status != NetConnectionStatus.Connected || + t.Status == FileTransferStatus.Finished || + t.Status == FileTransferStatus.Canceled || + t.Status == FileTransferStatus.Error); + + foreach (FileTransferOut transfer in endedTransfers) + { + activeTransfers.Remove(transfer); + OnEnded(transfer); + } + foreach (FileTransferOut transfer in activeTransfers) { transfer.WaitTimer -= deltaTime; @@ -223,14 +241,16 @@ namespace Barotrauma.Networking transfer.Status = FileTransferStatus.Finished; } } - - activeTransfers.RemoveAll(t => t.Status == FileTransferStatus.Finished); } public void CancelTransfer(FileTransferOut transfer) { transfer.Status = FileTransferStatus.Canceled; activeTransfers.Remove(transfer); + + OnEnded(transfer); + + GameMain.Server.SendCancelTransferMsg(transfer); } public void ReadFileRequest(NetIncomingMessage inc) diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 3e207f174..aadc2134c 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -153,7 +153,10 @@ namespace Barotrauma.Networking Log("Starting the server...", Color.Cyan); server = new NetServer(config); netPeer = server; + fileSender = new FileSender(this); + fileSender.OnEnded += FileTransferChanged; + fileSender.OnStarted += FileTransferChanged; server.Start(); } @@ -1695,7 +1698,57 @@ namespace Barotrauma.Networking netStats.AddValue(NetStats.NetStatType.ReceivedBytes, server.Statistics.ReceivedBytes); netStats.Draw(spriteBatch, new Rectangle(200,0,800,200), this); + } + private void FileTransferChanged(FileSender.FileTransferOut transfer) + { + Client recipient = connectedClients.Find(c => c.Connection == transfer.Connection); + UpdateFileTransferIndicator(recipient); + } + + public void SendCancelTransferMsg(FileSender.FileTransferOut transfer) + { + NetOutgoingMessage msg = server.CreateMessage(); + msg.Write((byte)ServerPacketHeader.FILE_TRANSFER); + msg.Write((byte)FileTransferMessageType.Cancel); + msg.Write((byte)transfer.SequenceChannel); + server.SendMessage(msg, transfer.Connection, NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel); + } + + private void UpdateFileTransferIndicator(Client client) + { + var transfers = fileSender.ActiveTransfers.FindAll(t => t.Connection == client.Connection); + + var clientNameBox = GameMain.NetLobbyScreen.PlayerList.FindChild(client.name); + + var clientInfo = clientNameBox.FindChild("filetransfer"); + if (clientInfo == null) + { + clientNameBox.ClearChildren(); + clientInfo = new GUIFrame(new Rectangle(0, 0, 180, 0), Color.Transparent, Alignment.TopRight, null, clientNameBox); + clientInfo.UserData = "filetransfer"; + } + else if (transfers.Count == 0) + { + clientInfo.Parent.RemoveChild(clientInfo); + } + + clientInfo.ClearChildren(); + + var progressBar = new GUIProgressBar(new Rectangle(0, 4, 160, clientInfo.Rect.Height - 8), Color.Green, GUI.Style, 0.0f, Alignment.Left, clientInfo); + progressBar.IsHorizontal = true; + progressBar.ProgressGetter = () => { return transfers.Sum(t => t.Progress) / transfers.Count; }; + + var textBlock = new GUITextBlock(new Rectangle(0, 2, 160, 0), "", GUI.Style, Alignment.TopLeft, Alignment.Left | Alignment.CenterY, clientInfo, true, GUI.SmallFont); + textBlock.TextGetter = () => + { return MathUtils.GetBytesReadable(transfers.Sum(t => t.SentOffset)) + " / " + MathUtils.GetBytesReadable(transfers.Sum(t => t.Data.Length)); }; + + var cancelButton = new GUIButton(new Rectangle(-5, 0, 14, 0), "X", Alignment.Right, GUI.Style, clientInfo); + cancelButton.OnClicked = (GUIButton button, object userdata) => + { + transfers.ForEach(t => fileSender.CancelTransfer(t)); + return true; + }; } public void UpdateVoteStatus()