Progress on file transfers (class for receiving files, FileSender can transfer multiple files to the same recipient simultaneously)
This commit is contained in:
@@ -155,6 +155,7 @@
|
|||||||
<Compile Include="Source\Networking\BanList.cs" />
|
<Compile Include="Source\Networking\BanList.cs" />
|
||||||
<Compile Include="Source\Networking\ChatMessage.cs" />
|
<Compile Include="Source\Networking\ChatMessage.cs" />
|
||||||
<Compile Include="Source\Networking\Client.cs" />
|
<Compile Include="Source\Networking\Client.cs" />
|
||||||
|
<Compile Include="Source\Networking\FileTransfer\FileReceiver.cs" />
|
||||||
<Compile Include="Source\Networking\FileTransfer\FileSender.cs" />
|
<Compile Include="Source\Networking\FileTransfer\FileSender.cs" />
|
||||||
<Compile Include="Source\Networking\GameServerLogin.cs" />
|
<Compile Include="Source\Networking\GameServerLogin.cs" />
|
||||||
<Compile Include="Source\Networking\INetSerializable.cs" />
|
<Compile Include="Source\Networking\INetSerializable.cs" />
|
||||||
|
|||||||
@@ -0,0 +1,343 @@
|
|||||||
|
using Lidgren.Network;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Barotrauma.Networking
|
||||||
|
{
|
||||||
|
class FileReceiver
|
||||||
|
{
|
||||||
|
public class FileTransferIn : IDisposable
|
||||||
|
{
|
||||||
|
public delegate void OnFinishedDelegate(FileTransferIn fileStreamReceiver);
|
||||||
|
public OnFinishedDelegate OnFinished;
|
||||||
|
|
||||||
|
public string FileName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FilePath
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong FileSize
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong Received
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileTransferType FileType
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileTransferStatus Status
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float BytesPerSecond
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Progress
|
||||||
|
{
|
||||||
|
get { return Received / (float)FileSize; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileStream WriteStream
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int TimeStarted
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SequenceChannel;
|
||||||
|
|
||||||
|
public FileTransferIn(string filePath, FileTransferType fileType, OnFinishedDelegate onFinished)
|
||||||
|
{
|
||||||
|
FilePath = filePath;
|
||||||
|
FileName = Path.GetFileName(FilePath);
|
||||||
|
FileType = fileType;
|
||||||
|
|
||||||
|
this.OnFinished = onFinished;
|
||||||
|
|
||||||
|
WriteStream = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||||
|
TimeStarted = Environment.TickCount;
|
||||||
|
|
||||||
|
Status = FileTransferStatus.NotStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadBytes(NetIncomingMessage inc)
|
||||||
|
{
|
||||||
|
byte[] all = inc.ReadBytes(inc.LengthBytes - inc.PositionInBytes);
|
||||||
|
Received += (ulong)all.Length;
|
||||||
|
WriteStream.Write(all, 0, all.Length);
|
||||||
|
|
||||||
|
int passed = Environment.TickCount - TimeStarted;
|
||||||
|
float psec = passed / 1000.0f;
|
||||||
|
|
||||||
|
BytesPerSecond = Received / psec;
|
||||||
|
|
||||||
|
Status = Received >= FileSize ? FileTransferStatus.Finished : FileTransferStatus.Receiving;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool disposed = false;
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposed) return;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (WriteStream != null)
|
||||||
|
{
|
||||||
|
WriteStream.Flush();
|
||||||
|
WriteStream.Close();
|
||||||
|
WriteStream.Dispose();
|
||||||
|
WriteStream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MaxFileSize = 1000000;
|
||||||
|
|
||||||
|
private List<FileTransferIn> activeTransfers;
|
||||||
|
|
||||||
|
private string downloadFolder;
|
||||||
|
|
||||||
|
public FileReceiver(string downloadFolder)
|
||||||
|
{
|
||||||
|
activeTransfers = new List<FileTransferIn>();
|
||||||
|
|
||||||
|
this.downloadFolder = downloadFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadMessage(NetIncomingMessage inc)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.Assert(!activeTransfers.Any(t =>
|
||||||
|
t.Status == FileTransferStatus.Error ||
|
||||||
|
t.Status == FileTransferStatus.Canceled ||
|
||||||
|
t.Status == FileTransferStatus.Finished), "List of active file transfers contains entires that should have been removed");
|
||||||
|
|
||||||
|
byte transferMessageType = inc.ReadByte();
|
||||||
|
switch (transferMessageType)
|
||||||
|
{
|
||||||
|
case (byte)FileTransferMessageType.Initiate:
|
||||||
|
var existingTransfer = activeTransfers.Find(t => t.SequenceChannel == inc.SequenceChannel);
|
||||||
|
if (existingTransfer != null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("File transfer error: file transfer initiated on a sequence channel that's already in use");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte fileType = inc.ReadByte();
|
||||||
|
ushort chunkLen = inc.ReadUInt16();
|
||||||
|
ulong fileSize = inc.ReadUInt64();
|
||||||
|
string fileName = inc.ReadString();
|
||||||
|
|
||||||
|
string errorMsg;
|
||||||
|
if (!ValidateInitialData(fileType, fileName, fileSize, out errorMsg))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("File transfer failed ("+errorMsg+")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newTransfer = new FileTransferIn(Path.Combine(downloadFolder, fileName), (FileTransferType)fileType, null);
|
||||||
|
newTransfer.SequenceChannel = inc.SequenceChannel;
|
||||||
|
newTransfer.Status = FileTransferStatus.Receiving;
|
||||||
|
|
||||||
|
activeTransfers.Add(newTransfer);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case (byte)FileTransferMessageType.Data:
|
||||||
|
var activeTransfer = activeTransfers.Find(t => t.SequenceChannel == inc.SequenceChannel);
|
||||||
|
if (activeTransfer == null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("File transfer error: received data without a transfer initiation message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeTransfer.Received + (ulong)inc.LengthBytes > activeTransfer.FileSize * 1.1f)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("File transfer error: Received more data than expected");
|
||||||
|
activeTransfer.Status = FileTransferStatus.Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
activeTransfer.ReadBytes(inc);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("File transfer error: "+e.Message);
|
||||||
|
activeTransfer.Status = FileTransferStatus.Error;
|
||||||
|
StopTransfer(activeTransfer, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeTransfer.Status == FileTransferStatus.Finished)
|
||||||
|
{
|
||||||
|
string errorMessage = "";
|
||||||
|
if (ValidateReceivedData(activeTransfer, out errorMessage))
|
||||||
|
{
|
||||||
|
activeTransfer.OnFinished(activeTransfer);
|
||||||
|
StopTransfer(activeTransfer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activeTransfer.Status = FileTransferStatus.Error;
|
||||||
|
StopTransfer(activeTransfer, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidateInitialData(byte type, string fileName, ulong fileSize, out string errorMessage)
|
||||||
|
{
|
||||||
|
errorMessage = "";
|
||||||
|
|
||||||
|
if (fileSize > MaxFileSize)
|
||||||
|
{
|
||||||
|
errorMessage = "File too large (" + MathUtils.GetBytesReadable((long)fileSize) + ")";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Enum.IsDefined(typeof(FileTransferType), type))
|
||||||
|
{
|
||||||
|
errorMessage = "Unknown file type";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Regex.Match(fileName, @"^[\w\- ]+[\w\-. ]*$").Success)
|
||||||
|
{
|
||||||
|
errorMessage = "Illegal characters in file name ''" + fileName + "''";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (byte)FileTransferType.Submarine:
|
||||||
|
if (Path.GetExtension(fileName) != ".sub")
|
||||||
|
{
|
||||||
|
errorMessage = "Wrong file extension ''" + Path.GetExtension(fileName) + "''! (Expected .sub)";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidateReceivedData(FileTransferIn fileTransfer, out string ErrorMessage)
|
||||||
|
{
|
||||||
|
ErrorMessage = "";
|
||||||
|
switch (fileTransfer.FileType)
|
||||||
|
{
|
||||||
|
case FileTransferType.Submarine:
|
||||||
|
Stream stream = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stream = SaveUtil.DecompressFiletoStream(fileTransfer.FilePath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Loading received submarine ''" + fileTransfer.FileName + "'' failed! {" + e.Message + "}";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream == null)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Decompressing received submarine file''" + fileTransfer.FilePath + "'' failed!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stream.Position = 0;
|
||||||
|
|
||||||
|
XmlReaderSettings settings = new XmlReaderSettings();
|
||||||
|
settings.DtdProcessing = DtdProcessing.Prohibit;
|
||||||
|
settings.IgnoreProcessingInstructions = true;
|
||||||
|
|
||||||
|
using (var reader = XmlReader.Create(stream, settings))
|
||||||
|
{
|
||||||
|
while (reader.Read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
stream.Close();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
ErrorMessage = "Parsing file ''" + fileTransfer.FilePath + "'' failed! The file may not be a valid submarine file.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Close();
|
||||||
|
stream.Dispose();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopTransfer(FileTransferIn transfer, bool deleteFile = false)
|
||||||
|
{
|
||||||
|
if (deleteFile && File.Exists(transfer.FilePath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(transfer.FilePath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Failed to delete file \""+transfer.FilePath+"\" ("+e.Message+")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transfer.Status != FileTransferStatus.Finished &&
|
||||||
|
transfer.Status != FileTransferStatus.Error)
|
||||||
|
{
|
||||||
|
transfer.Status = FileTransferStatus.Canceled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeTransfers.Contains(transfer)) activeTransfers.Remove(transfer);
|
||||||
|
transfer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
enum FileTransferStatus
|
enum FileTransferStatus
|
||||||
{
|
{
|
||||||
NotStarted, Sending, Receiving, Finished, Canceled
|
NotStarted, Sending, Receiving, Finished, Canceled, Error
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FileTransferMessageType
|
enum FileTransferMessageType
|
||||||
@@ -27,7 +27,6 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
public class FileTransferOut
|
public class FileTransferOut
|
||||||
{
|
{
|
||||||
private byte[] tempBuffer;
|
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
|
|
||||||
private DateTime startingTime;
|
private DateTime startingTime;
|
||||||
@@ -56,7 +55,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public float Progress
|
public float Progress
|
||||||
{
|
{
|
||||||
get { return 0.0f; }//inputStream == null ? 0.0f : (float)sentOffset / (float)inputStream.Length; }
|
get { return SentOffset / (float)Data.Length; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float WaitTimer
|
public float WaitTimer
|
||||||
@@ -81,6 +80,8 @@ namespace Barotrauma.Networking
|
|||||||
get { return connection; }
|
get { return connection; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int SequenceChannel;
|
||||||
|
|
||||||
public FileTransferOut(NetConnection recipient, FileTransferType fileType, string filePath)
|
public FileTransferOut(NetConnection recipient, FileTransferType fileType, string filePath)
|
||||||
{
|
{
|
||||||
connection = recipient;
|
connection = recipient;
|
||||||
@@ -115,6 +116,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public FileTransferOut StartTransfer(NetConnection recipient, FileTransferType fileType, string filePath)
|
public FileTransferOut StartTransfer(NetConnection recipient, FileTransferType fileType, string filePath)
|
||||||
{
|
{
|
||||||
|
//TODO: set a limit on the amount of active transfers
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to initiate file transfer (file \""+filePath+"\" not found.");
|
DebugConsole.ThrowError("Failed to initiate file transfer (file \""+filePath+"\" not found.");
|
||||||
@@ -125,6 +127,11 @@ namespace Barotrauma.Networking
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
transfer = new FileTransferOut(recipient, fileType, filePath);
|
transfer = new FileTransferOut(recipient, fileType, filePath);
|
||||||
|
transfer.SequenceChannel = 1;
|
||||||
|
while (activeTransfers.Any(t => t.Connection == recipient && t.SequenceChannel == transfer.SequenceChannel))
|
||||||
|
{
|
||||||
|
transfer.SequenceChannel++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -136,6 +143,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public void Update(float deltaTime)
|
public void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
|
activeTransfers.RemoveAll(t => t.Connection.Status != NetConnectionStatus.Connected);
|
||||||
|
|
||||||
foreach (FileTransferOut transfer in activeTransfers)
|
foreach (FileTransferOut transfer in activeTransfers)
|
||||||
{
|
{
|
||||||
transfer.WaitTimer -= deltaTime;
|
transfer.WaitTimer -= deltaTime;
|
||||||
@@ -161,9 +170,10 @@ namespace Barotrauma.Networking
|
|||||||
message.Write((ushort)chunkLen);
|
message.Write((ushort)chunkLen);
|
||||||
message.Write((ulong)transfer.Data.Length);
|
message.Write((ulong)transfer.Data.Length);
|
||||||
message.Write(transfer.FileName);
|
message.Write(transfer.FileName);
|
||||||
transfer.Connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
|
transfer.Connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel);
|
||||||
|
|
||||||
transfer.Status = FileTransferStatus.Sending;
|
transfer.Status = FileTransferStatus.Sending;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
message = peer.CreateMessage(sendByteCount + 8 + 1);
|
message = peer.CreateMessage(sendByteCount + 8 + 1);
|
||||||
@@ -175,7 +185,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
message.Write(sendBytes);
|
message.Write(sendBytes);
|
||||||
|
|
||||||
transfer.Connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
|
transfer.Connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel);
|
||||||
transfer.SentOffset += sendByteCount;
|
transfer.SentOffset += sendByteCount;
|
||||||
|
|
||||||
if (remaining - sendByteCount <= 0)
|
if (remaining - sendByteCount <= 0)
|
||||||
@@ -193,5 +203,33 @@ namespace Barotrauma.Networking
|
|||||||
activeTransfers.Remove(transfer);
|
activeTransfers.Remove(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ReadFileRequest(NetIncomingMessage inc)
|
||||||
|
{
|
||||||
|
byte messageType = inc.ReadByte();
|
||||||
|
|
||||||
|
if (messageType == (byte)FileTransferMessageType.Cancel)
|
||||||
|
{
|
||||||
|
byte sequenceChannel = inc.ReadByte();
|
||||||
|
var matchingTransfer = activeTransfers.Find(t => t.Connection == inc.SenderConnection && t.SequenceChannel == sequenceChannel);
|
||||||
|
if (matchingTransfer != null) CancelTransfer(matchingTransfer);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte fileType = inc.ReadByte();
|
||||||
|
switch (fileType)
|
||||||
|
{
|
||||||
|
case (byte)FileTransferType.Submarine:
|
||||||
|
string fileName = inc.ReadString();
|
||||||
|
var requestedSubmarine = Submarine.SavedSubmarines.Find(s => s.Name == fileName);
|
||||||
|
|
||||||
|
if (requestedSubmarine != null)
|
||||||
|
{
|
||||||
|
StartTransfer(inc.SenderConnection, FileTransferType.Submarine, requestedSubmarine.FilePath);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
private ServerEntityEventManager entityEventManager;
|
private ServerEntityEventManager entityEventManager;
|
||||||
|
|
||||||
|
private FileSender fileSender;
|
||||||
|
|
||||||
public override List<Client> ConnectedClients
|
public override List<Client> ConnectedClients
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -132,6 +134,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
entityEventManager = new ServerEntityEventManager(this);
|
entityEventManager = new ServerEntityEventManager(this);
|
||||||
|
|
||||||
|
fileSender = new FileSender(this);
|
||||||
|
|
||||||
whitelist = new WhiteList();
|
whitelist = new WhiteList();
|
||||||
banList = new BanList();
|
banList = new BanList();
|
||||||
|
|
||||||
@@ -341,7 +345,6 @@ namespace Barotrauma.Networking
|
|||||||
if (settingsFrame != null) settingsFrame.Update(deltaTime);
|
if (settingsFrame != null) settingsFrame.Update(deltaTime);
|
||||||
if (log.LogFrame != null) log.LogFrame.Update(deltaTime);
|
if (log.LogFrame != null) log.LogFrame.Update(deltaTime);
|
||||||
|
|
||||||
|
|
||||||
if (!started) return;
|
if (!started) return;
|
||||||
|
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
@@ -355,7 +358,9 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unauthenticatedClients.RemoveAll(uc => uc.AuthTimer <= 0.0f);
|
unauthenticatedClients.RemoveAll(uc => uc.AuthTimer <= 0.0f);
|
||||||
|
|
||||||
|
fileSender.Update(deltaTime);
|
||||||
|
|
||||||
if (gameStarted)
|
if (gameStarted)
|
||||||
{
|
{
|
||||||
@@ -550,6 +555,12 @@ namespace Barotrauma.Networking
|
|||||||
case ClientPacketHeader.SERVER_COMMAND:
|
case ClientPacketHeader.SERVER_COMMAND:
|
||||||
ClientReadServerCommand(inc);
|
ClientReadServerCommand(inc);
|
||||||
break;
|
break;
|
||||||
|
case ClientPacketHeader.FILE_REQUEST:
|
||||||
|
if (AllowFileTransfers)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1902,7 +1913,7 @@ namespace Barotrauma.Networking
|
|||||||
Log("Shutting down server...", Color.Cyan);
|
Log("Shutting down server...", Color.Cyan);
|
||||||
log.Save();
|
log.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
server.Shutdown("The server has been shut down");
|
server.Shutdown("The server has been shut down");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ namespace Barotrauma.Networking
|
|||||||
REQUEST_INIT, //ask the server to give you initialization
|
REQUEST_INIT, //ask the server to give you initialization
|
||||||
UPDATE_LOBBY, //update state in lobby
|
UPDATE_LOBBY, //update state in lobby
|
||||||
UPDATE_INGAME, //update state ingame
|
UPDATE_INGAME, //update state ingame
|
||||||
|
|
||||||
|
FILE_REQUEST, //request a (submarine) file from the server
|
||||||
|
|
||||||
RESPONSE_STARTGAME, //tell the server whether you're ready to start
|
RESPONSE_STARTGAME, //tell the server whether you're ready to start
|
||||||
SERVER_COMMAND //tell the server to end a round or kick/ban someone (special permissions required)
|
SERVER_COMMAND //tell the server to end a round or kick/ban someone (special permissions required)
|
||||||
|
|||||||
Reference in New Issue
Block a user