diff --git a/Subsurface/Source/Camera.cs b/Subsurface/Source/Camera.cs index 12aacd1be..c8b75de5b 100644 --- a/Subsurface/Source/Camera.cs +++ b/Subsurface/Source/Camera.cs @@ -127,11 +127,11 @@ namespace Barotrauma //UpdateTransform(); } - public void UpdateTransform() + public void UpdateTransform(bool interpolate = true) { - Vector2 interpolatedPosition = Physics.Interpolate(prevPosition, position); + Vector2 interpolatedPosition = interpolate ? Physics.Interpolate(prevPosition, position) : position; - float interpolatedZoom = Physics.Interpolate(prevZoom, zoom); + float interpolatedZoom = interpolate ? Physics.Interpolate(prevZoom, zoom) : zoom; worldView.X = (int)(interpolatedPosition.X - worldView.Width / 2.0); worldView.Y = (int)(interpolatedPosition.Y + worldView.Height / 2.0); @@ -149,6 +149,12 @@ namespace Barotrauma viewMatrix; Sound.CameraPos = new Vector3(WorldViewCenter.X, WorldViewCenter.Y, 0.0f); + + if (!interpolate) + { + prevPosition = position; + prevZoom = zoom; + } } public void MoveCamera(float deltaTime) diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index d7af79305..dbcc754f9 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -713,37 +713,42 @@ namespace Barotrauma } } - Vector2 topLeft = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y); - Vector2 bottomRight = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y); - foreach (Hull hull in Hull.hullList) + Vector2 center = Vector2.Zero; + + if (Hull.hullList.Any()) { - if (hull.Rect.X < topLeft.X) topLeft.X = hull.Rect.X; - if (hull.Rect.Y > topLeft.Y) topLeft.Y = hull.Rect.Y; - - if (hull.Rect.Right > bottomRight.X) bottomRight.X = hull.Rect.Right; - if (hull.Rect.Y - hull.Rect.Height < bottomRight.Y) bottomRight.Y = hull.Rect.Y - hull.Rect.Height; - } - - Vector2 center = (topLeft + bottomRight) / 2.0f; - center.X -= center.X % GridSize.X; - center.Y -= center.Y % GridSize.Y; - - foreach (Item item in Item.ItemList) - { - var wire = item.GetComponent(); - if (wire == null) continue; - - for (int i = 0; i < wire.Nodes.Count; i++) + Vector2 topLeft = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y); + Vector2 bottomRight = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y); + foreach (Hull hull in Hull.hullList) { - wire.Nodes[i] -= center; - } - } + if (hull.Rect.X < topLeft.X) topLeft.X = hull.Rect.X; + if (hull.Rect.Y > topLeft.Y) topLeft.Y = hull.Rect.Y; - for (int i = 0; i < MapEntity.mapEntityList.Count; i++) - { - if (MapEntity.mapEntityList[i].Submarine == null) continue; + if (hull.Rect.Right > bottomRight.X) bottomRight.X = hull.Rect.Right; + if (hull.Rect.Y - hull.Rect.Height < bottomRight.Y) bottomRight.Y = hull.Rect.Y - hull.Rect.Height; + } + + center = (topLeft + bottomRight) / 2.0f; + center.X -= center.X % GridSize.X; + center.Y -= center.Y % GridSize.Y; + + foreach (Item item in Item.ItemList) + { + var wire = item.GetComponent(); + if (wire == null) continue; + + for (int i = 0; i < wire.Nodes.Count; i++) + { + wire.Nodes[i] -= center; + } + } + + for (int i = 0; i < MapEntity.mapEntityList.Count; i++) + { + if (MapEntity.mapEntityList[i].Submarine == null) continue; - MapEntity.mapEntityList[i].Move(-center); + MapEntity.mapEntityList[i].Move(-center); + } } subBody = new SubmarineBody(this); diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 7e45546b9..9fb1fcbb9 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -226,25 +226,32 @@ namespace Barotrauma if (dist > 1000.0f) { Vector2 moveAmount = ConvertUnits.ToSimUnits((Vector2)targetPosition) - body.Position; - Vector2 displayerMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount); + Vector2 displayMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount); body.SetTransform(body.Position + moveAmount, 0.0f); - if (Character.Controlled != null) Character.Controlled.CursorPosition += displayerMoveAmount; + if (Character.Controlled != null) Character.Controlled.CursorPosition += displayMoveAmount; - GameMain.GameScreen.Cam.Position += displayerMoveAmount; - GameMain.GameScreen.Cam.UpdateTransform(); + GameMain.GameScreen.Cam.Position += displayMoveAmount; + if (GameMain.GameScreen.Cam.TargetPos!=Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += displayMoveAmount; + GameMain.GameScreen.Cam.UpdateTransform(false); + + submarine.SetPrevTransform(submarine.Position); + submarine.UpdateTransform(); targetPosition = null; } else if (dist > 50.0f) { Vector2 moveAmount = Vector2.Normalize((Vector2)targetPosition - Position); moveAmount *= ConvertUnits.ToSimUnits(Math.Min(dist, 100.0f)); - Vector2 displayerMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount); + Vector2 displayMoveAmount = ConvertUnits.ToDisplayUnits(moveAmount); body.SetTransform(body.Position + moveAmount * deltaTime, 0.0f); - GameMain.GameScreen.Cam.Position += displayerMoveAmount * deltaTime; - if (Character.Controlled != null) Character.Controlled.CursorPosition += displayerMoveAmount; + GameMain.GameScreen.Cam.Position += displayMoveAmount * deltaTime; + if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += displayMoveAmount; + if (Character.Controlled != null) Character.Controlled.CursorPosition += displayMoveAmount; + + //GameMain.GameScreen.Cam.UpdateTransform(false); } else { diff --git a/Subsurface/Source/Networking/FileStreamReceiver.cs b/Subsurface/Source/Networking/FileStreamReceiver.cs index 45cfbe9e1..886d5c8e4 100644 --- a/Subsurface/Source/Networking/FileStreamReceiver.cs +++ b/Subsurface/Source/Networking/FileStreamReceiver.cs @@ -4,13 +4,36 @@ using System.IO; namespace Barotrauma.Networking { - class FileStreamReceiver + class FileStreamReceiver : IDisposable { - private NetClient s_client; - private ulong s_length; - private ulong s_received; - private FileStream s_writeStream; - private int s_timeStarted; + public delegate void OnFinished(FileStreamReceiver fileStreamReceiver); + private OnFinished onFinished; + + private NetClient client; + private ulong length; + private ulong received; + private FileStream writeStream; + private int timeStarted; + + private string filePath; + + private FileTransferType fileType; + + public string FileName + { + get; + private set; + } + + public ulong FileSize + { + get { return length; } + } + + public ulong Received + { + get { return received; } + } public FileTransferStatus Status { @@ -24,47 +47,97 @@ namespace Barotrauma.Networking private set; } - public FileStreamReceiver(NetClient client) + public float Progress { - s_client = client; + get { return length / (float)received; } + + } + + public FileStreamReceiver(NetClient client, string filePath, FileTransferType fileType, OnFinished onFinished) + { + client = client; + + this.filePath = filePath; + this.fileType = fileType; + + this.onFinished = onFinished; Status = FileTransferStatus.NotStarted; } public void ReadMessage(NetIncomingMessage inc) { - int chunkLen = inc.LengthBytes; - if (s_length == 0) + try { - s_length = inc.ReadUInt64(); - string filename = inc.ReadString(); - s_writeStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); - s_timeStarted = Environment.TickCount; + TryReadMessage(inc); + } + catch (Exception e) + { + DebugConsole.ThrowError("Error while receiving file ''"+FileName+"''", e); + Status = FileTransferStatus.Error; + } + } + + private void TryReadMessage(NetIncomingMessage inc) + { + //int chunkLen = inc.LengthBytes; + if (length == 0) + { + + if (!Directory.Exists(filePath)) + { + Directory.CreateDirectory(filePath); + } + + byte fileTypeByte = inc.ReadByte(); + if (fileTypeByte != (byte)fileType) + { + Status = FileTransferStatus.Error; + return; + } + + length = inc.ReadUInt64(); + FileName = inc.ReadString(); + writeStream = new FileStream(Path.Combine(filePath, FileName), FileMode.Create, FileAccess.Write, FileShare.None); + timeStarted = Environment.TickCount; Status = FileTransferStatus.NotStarted; return; } - byte[] all = inc.ReadBytes(inc.LengthBytes); - s_received += (ulong)all.Length; - s_writeStream.Write(all, 0, all.Length); + byte[] all = inc.ReadBytes(inc.LengthBytes - inc.PositionInBytes); + received += (ulong)all.Length; + writeStream.Write(all, 0, all.Length); - int passed = Environment.TickCount - s_timeStarted; + int passed = Environment.TickCount - timeStarted; float psec = passed / 1000.0f; - BytesPerSecond = s_received / psec; + BytesPerSecond = received / psec; Status = FileTransferStatus.Receiving; - if (s_received >= s_length) + if (received >= length) { - s_writeStream.Flush(); - s_writeStream.Close(); - s_writeStream.Dispose(); - - Status = FileTransferStatus.Finished; + Status = FileTransferStatus.Finished; + if (onFinished!=null) onFinished(this); } } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + writeStream.Flush(); + writeStream.Close(); + writeStream.Dispose(); + } } + + } diff --git a/Subsurface/Source/Networking/FileStreamSender.cs b/Subsurface/Source/Networking/FileStreamSender.cs index 7eaf60a97..24eb282da 100644 --- a/Subsurface/Source/Networking/FileStreamSender.cs +++ b/Subsurface/Source/Networking/FileStreamSender.cs @@ -1,4 +1,5 @@ using Lidgren.Network; +using System; using System.IO; namespace Barotrauma.Networking @@ -8,7 +9,12 @@ namespace Barotrauma.Networking NotStarted, Sending, Receiving, Finished, Error } - class FileStreamSender + enum FileTransferType + { + Unknown, Submarine + } + + class FileStreamSender : IDisposable { private FileStream inputStream; private int sentOffset; @@ -16,6 +22,9 @@ namespace Barotrauma.Networking private byte[] tempBuffer; private NetConnection connection; + + private FileTransferType fileType; + public FileTransferStatus Status { get; @@ -28,8 +37,8 @@ namespace Barotrauma.Networking private set; } - - public static FileStreamSender Create(NetConnection conn, string fileName) + + public static FileStreamSender Create(NetConnection conn, string fileName, FileTransferType fileType) { if (!File.Exists(fileName)) { @@ -37,19 +46,21 @@ namespace Barotrauma.Networking return null; } - return new FileStreamSender(conn, fileName); + return new FileStreamSender(conn, fileName, fileType); } - private FileStreamSender(NetConnection conn, string fileName) + private FileStreamSender(NetConnection conn, string fileName, FileTransferType fileType) { connection = conn; inputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); - chunkLen = connection.Peer.Configuration.MaximumTransmissionUnit - 20; + chunkLen = connection.Peer.Configuration.MaximumTransmissionUnit - 100; tempBuffer = new byte[chunkLen]; sentOffset = 0; FileName = fileName; + this.fileType = fileType; + Status = FileTransferStatus.NotStarted; } @@ -70,7 +81,9 @@ namespace Barotrauma.Networking if (sentOffset == 0) { // first message; send length, chunk length and file name - message = connection.Peer.CreateMessage(sendBytes + 8); + message = connection.Peer.CreateMessage(sendBytes + 8 + 1); + message.Write((byte)PacketTypes.FileStream); + message.Write((byte)fileType); message.Write((ulong)inputStream.Length); message.Write(Path.GetFileName(inputStream.Name)); connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1); @@ -78,7 +91,8 @@ namespace Barotrauma.Networking Status = FileTransferStatus.Sending; } - message = connection.Peer.CreateMessage(sendBytes + 8); + message = connection.Peer.CreateMessage(sendBytes + 8 + 1); + message.Write((byte)PacketTypes.FileStream); message.Write(tempBuffer, 0, sendBytes); connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1); @@ -88,12 +102,25 @@ namespace Barotrauma.Networking if (remaining - sendBytes <= 0) { - inputStream.Close(); - inputStream.Dispose(); - inputStream = null; + //Dispose(); Status = FileTransferStatus.Finished; } } + + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + inputStream.Close(); + inputStream.Dispose(); + inputStream = null; + } } } diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 63ad27adb..29ca1f730 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -4,6 +4,7 @@ using Microsoft.Xna.Framework; using System.Collections.Generic; using Barotrauma.Networking.ReliableMessages; using FarseerPhysics; +using System.IO; namespace Barotrauma.Networking { @@ -15,6 +16,8 @@ namespace Barotrauma.Networking private ReliableChannel reliableChannel; + private FileStreamReceiver fileStreamReceiver; + private GUITickBox endRoundButton; private bool connected; @@ -99,7 +102,7 @@ namespace Barotrauma.Networking NetOutgoingMessage outmsg = client.CreateMessage(); client.Start(); - outmsg.WriteEnum(PacketTypes.Login); + outmsg.Write((byte)PacketTypes.Login); outmsg.Write(myID); outmsg.Write(password); outmsg.Write(GameMain.Version.ToString()); @@ -221,7 +224,7 @@ namespace Barotrauma.Networking { // All manually sent messages are type of "Data" case NetIncomingMessageType.Data: - byte packetType = (byte)inc.ReadEnum(); + byte packetType = inc.ReadByte(); if (packetType == (byte)PacketTypes.LoggedIn) { myID = inc.ReadByte(); @@ -262,7 +265,7 @@ namespace Barotrauma.Networking CanStart = true; NetOutgoingMessage lobbyUpdateRequest = client.CreateMessage(); - lobbyUpdateRequest.WriteEnum(PacketTypes.RequestNetLobbyUpdate); + lobbyUpdateRequest.Write((byte)PacketTypes.RequestNetLobbyUpdate); client.SendMessage(lobbyUpdateRequest, NetDeliveryMethod.ReliableUnordered); } else if (packetType == (byte)PacketTypes.KickedOut) @@ -445,12 +448,12 @@ namespace Barotrauma.Networking { if (inc.MessageType != NetIncomingMessageType.Data) continue; - byte packetType = (byte)inc.ReadEnum(); + byte packetType = inc.ReadByte(); if (packetType == (byte)PacketTypes.ReliableMessage) { if (!reliableChannel.CheckMessage(inc)) continue; - packetType = (byte)inc.ReadEnum(); + packetType = inc.ReadByte(); } switch (packetType) @@ -474,6 +477,22 @@ namespace Barotrauma.Networking AddChatMessage(otherClient.name + " has joined the server", ChatMessageType.Server); + break; + case (byte)PacketTypes.RequestFile: + new GUIMessageBox("Couldn't the file from the server", "Sharing files has been disabled by the server."); + break; + case (byte)PacketTypes.FileStream: + if (fileStreamReceiver == null) + { + //todo: unexpected file + } + else + { + + fileStreamReceiver.ReadMessage(inc); + } + + break; case (byte)PacketTypes.PlayerLeft: byte leavingID = inc.ReadByte(); @@ -510,7 +529,7 @@ namespace Barotrauma.Networking break; case (byte)PacketTypes.Chatmessage: - ChatMessageType messageType = inc.ReadEnum(); + ChatMessageType messageType = (ChatMessageType)inc.ReadByte(); AddChatMessage(inc.ReadString(), messageType); break; @@ -691,24 +710,59 @@ namespace Barotrauma.Networking spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White); spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); - + + if (fileStreamReceiver!=null) + { + GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth / 2 - 100, 20), "Downloading "+fileStreamReceiver.FileName, Color.White); + GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth / 2 - 100, 20), + MathUtils.GetBytesReadable((long)fileStreamReceiver.Received)+" / "+MathUtils.GetBytesReadable((long)fileStreamReceiver.FileSize), Color.White); + GUI.DrawProgressBar(spriteBatch, new Vector2(GameMain.GraphicsWidth / 2 - 100, 20), new Vector2(200, 15), fileStreamReceiver.Progress, Color.Green); + } + } + + private void OnFileReceived(FileStreamReceiver receiver) + { + if (receiver.Status == FileTransferStatus.Error) + { + + } + else if (receiver.Status == FileTransferStatus.Finished) + { + new GUIMessageBox("Download finished", "File ''"+receiver.FileName+"'' was downloaded succesfully."); + } + + receiver.Dispose(); + fileStreamReceiver = null; } public override void Disconnect() { NetOutgoingMessage msg = client.CreateMessage(); - msg.WriteEnum(PacketTypes.PlayerLeft); + msg.Write((byte)PacketTypes.PlayerLeft); client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); client.Shutdown(""); GameMain.NetworkMember = null; } + public void RequestFile(string file, FileTransferType fileType) + { + 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); + } + public void Vote(VoteType voteType, object userData) { NetOutgoingMessage msg = client.CreateMessage(); - msg.WriteEnum(PacketTypes.Vote); - msg.WriteEnum(voteType); + msg.Write((byte)PacketTypes.Vote); + msg.Write((byte)voteType); switch (voteType) { @@ -729,7 +783,7 @@ namespace Barotrauma.Networking public bool SpectateClicked(GUIButton button, object userData) { NetOutgoingMessage msg = client.CreateMessage(); - msg.WriteEnum(PacketTypes.SpectateRequest); + msg.Write((byte)PacketTypes.SpectateRequest); client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); @@ -760,7 +814,7 @@ namespace Barotrauma.Networking if (characterInfo == null) return; NetOutgoingMessage msg = client.CreateMessage(); - msg.WriteEnum(PacketTypes.CharacterInfo); + msg.Write((byte)PacketTypes.CharacterInfo); msg.Write(characterInfo.Name); msg.Write(characterInfo.Gender == Gender.Male); @@ -837,8 +891,8 @@ namespace Barotrauma.Networking (myCharacter == null || myCharacter.IsDead)) ? ChatMessageType.Dead : ChatMessageType.Default; ReliableMessage msg = reliableChannel.CreateMessage(); - msg.InnerMessage.WriteEnum(PacketTypes.Chatmessage); - msg.InnerMessage.WriteEnum(type); + msg.InnerMessage.Write((byte)PacketTypes.Chatmessage); + msg.InnerMessage.Write((byte)type); msg.InnerMessage.Write(message); reliableChannel.SendMessage(msg, client.ServerConnection); @@ -848,41 +902,41 @@ namespace Barotrauma.Networking /// sends some random data to the server (can be a networkevent or just something completely random) /// use for debugging purposes /// - public void SendRandomData() - { - NetOutgoingMessage msg = client.CreateMessage(); - switch (Rand.Int(5)) - { - case 0: - msg.WriteEnum(PacketTypes.NetworkEvent); - msg.WriteEnum(NetworkEventType.EntityUpdate); - msg.Write(Rand.Int(MapEntity.mapEntityList.Count)); - break; - case 1: - msg.WriteEnum(PacketTypes.NetworkEvent); - msg.Write((byte)Enum.GetNames(typeof(NetworkEventType)).Length); - msg.Write(Rand.Int(MapEntity.mapEntityList.Count)); - break; - case 2: - msg.WriteEnum(PacketTypes.NetworkEvent); - msg.WriteEnum(NetworkEventType.ComponentUpdate); - msg.Write((int)Item.ItemList[Rand.Int(Item.ItemList.Count)].ID); - msg.Write(Rand.Int(8)); - break; - case 3: - msg.Write((byte)Enum.GetNames(typeof(PacketTypes)).Length); - break; - } + //public void SendRandomData() + //{ + // NetOutgoingMessage msg = client.CreateMessage(); + // switch (Rand.Int(5)) + // { + // case 0: + // msg.WriteEnum(PacketTypes.NetworkEvent); + // msg.WriteEnum(NetworkEventType.EntityUpdate); + // msg.Write(Rand.Int(MapEntity.mapEntityList.Count)); + // break; + // case 1: + // msg.WriteEnum(PacketTypes.NetworkEvent); + // msg.Write((byte)Enum.GetNames(typeof(NetworkEventType)).Length); + // msg.Write(Rand.Int(MapEntity.mapEntityList.Count)); + // break; + // case 2: + // msg.WriteEnum(PacketTypes.NetworkEvent); + // msg.WriteEnum(NetworkEventType.ComponentUpdate); + // msg.Write((int)Item.ItemList[Rand.Int(Item.ItemList.Count)].ID); + // msg.Write(Rand.Int(8)); + // break; + // case 3: + // msg.Write((byte)Enum.GetNames(typeof(PacketTypes)).Length); + // break; + // } - int bitCount = Rand.Int(100); - for (int i = 0; i c.Connection == inc.SenderConnection); if (dataSender == null) return; - byte packetType = (byte)inc.ReadEnum(); + byte packetType = inc.ReadByte(); if (packetType == (byte)PacketTypes.ReliableMessage) { if (!dataSender.ReliableChannel.CheckMessage(inc)) return; - packetType = (byte)inc.ReadEnum(); + packetType = inc.ReadByte(); } switch (packetType) @@ -490,7 +504,7 @@ namespace Barotrauma.Networking break; case (byte)PacketTypes.Chatmessage: - ChatMessageType messageType = inc.ReadEnum(); + ChatMessageType messageType = (ChatMessageType)inc.ReadByte(); SendChatMessage(inc.ReadString(), messageType); @@ -500,6 +514,33 @@ namespace Barotrauma.Networking break; case (byte)PacketTypes.CharacterInfo: ReadCharacterData(inc); + break; + case (byte)PacketTypes.RequestFile: + string fileName = inc.ReadString(); + byte fileType = inc.ReadByte(); + + switch (fileType) + { + case (byte)FileTransferType.Submarine: + + var requestedSubmarine = Submarine.SavedSubmarines.Find(s => s.Name == fileName); + + if (requestedSubmarine==null) + { + //todo: ei voi ladata + } + else + { + var fileStreamSender = FileStreamSender.Create(dataSender.Connection, requestedSubmarine.FilePath, FileTransferType.Submarine); + if (fileStreamSender != null) dataSender.FileStreamSender = fileStreamSender; + } + break; + default: + DebugConsole.ThrowError("Unknown file type was requested ("+fileType+")"); + break; + } + + break; case (byte)PacketTypes.ResendRequest: @@ -541,7 +582,7 @@ namespace Barotrauma.Networking private void HandleConnectionApproval(NetIncomingMessage inc) { - if (inc.ReadEnum() != PacketTypes.Login) return; + if ((PacketTypes)inc.ReadByte() != PacketTypes.Login) return; DebugConsole.NewMessage("New player has joined the server", Color.White); @@ -649,6 +690,8 @@ namespace Barotrauma.Networking UpdateCrewFrame(); inc.SenderConnection.Approve(); + + refreshMasterTimer = DateTime.Now; } @@ -886,7 +929,7 @@ namespace Barotrauma.Networking private NetOutgoingMessage CreateStartMessage(int seed, Submarine selectedSub, GameModePreset selectedMode) { NetOutgoingMessage msg = server.CreateMessage(); - msg.WriteEnum(PacketTypes.StartGame); + msg.Write((byte)PacketTypes.StartGame); msg.Write(seed); @@ -910,7 +953,7 @@ namespace Barotrauma.Networking if (myCharacter != null) { - msg.Write(0); + msg.Write((byte)0); WriteCharacterData(msg, myCharacter.Info.Name, myCharacter); } @@ -949,7 +992,7 @@ namespace Barotrauma.Networking if (ConnectedClients.Count > 0) { NetOutgoingMessage msg = server.CreateMessage(); - msg.WriteEnum(PacketTypes.EndGame); + msg.Write((byte)PacketTypes.EndGame); msg.Write(endMessage); if (server.ConnectionsCount > 0) @@ -989,7 +1032,9 @@ namespace Barotrauma.Networking private void DisconnectClient(NetConnection senderConnection, string msg = "", string targetmsg = "") { Client client = ConnectedClients.Find(x => x.Connection == senderConnection); - if (client != null) DisconnectClient(client, msg, targetmsg); + if (client == null) return; + + DisconnectClient(client, msg, targetmsg); } private void DisconnectClient(Client client, string msg = "", string targetmsg = "") @@ -1007,14 +1052,14 @@ namespace Barotrauma.Networking Log(msg, messageColor[(int)ChatMessageType.Server]); NetOutgoingMessage outmsg = server.CreateMessage(); - outmsg.WriteEnum(PacketTypes.KickedOut); + outmsg.Write((byte)PacketTypes.KickedOut); outmsg.Write(targetmsg); server.SendMessage(outmsg, client.Connection, NetDeliveryMethod.ReliableUnordered, 0); ConnectedClients.Remove(client); outmsg = server.CreateMessage(); - outmsg.WriteEnum(PacketTypes.PlayerLeft); + outmsg.Write((byte)PacketTypes.PlayerLeft); outmsg.Write(client.ID); outmsg.Write(msg); @@ -1028,6 +1073,8 @@ namespace Barotrauma.Networking AddChatMessage(msg, ChatMessageType.Server); UpdateCrewFrame(); + + refreshMasterTimer = DateTime.Now; } private void UpdateCrewFrame() @@ -1086,7 +1133,7 @@ namespace Barotrauma.Networking } NetOutgoingMessage msg = server.CreateMessage(); - msg.WriteEnum(PacketTypes.Traitor); + msg.Write((byte)PacketTypes.Traitor); msg.Write(target.Info.Name); if (server.Connections.Count > 0) { @@ -1175,7 +1222,7 @@ namespace Barotrauma.Networking try { NetOutgoingMessage msg = server.CreateMessage(); - msg.WriteEnum(PacketTypes.VoteStatus); + msg.Write((byte)PacketTypes.VoteStatus); Voting.WriteData(msg, ConnectedClients); server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0); @@ -1199,7 +1246,7 @@ namespace Barotrauma.Networking if (server.Connections.Count == 0) return true; NetOutgoingMessage msg = server.CreateMessage(); - msg.WriteEnum(PacketTypes.UpdateNetLobby); + msg.Write((byte)PacketTypes.UpdateNetLobby); GameMain.NetLobbyScreen.WriteData(msg); server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0); @@ -1275,8 +1322,8 @@ namespace Barotrauma.Networking foreach (Client c in recipients) { ReliableMessage msg = c.ReliableChannel.CreateMessage(); - msg.InnerMessage.WriteEnum(PacketTypes.Chatmessage); - msg.InnerMessage.WriteEnum(type); + msg.InnerMessage.Write((byte)PacketTypes.Chatmessage); + msg.InnerMessage.Write((byte)type); msg.InnerMessage.Write(message); c.ReliableChannel.SendMessage(msg, c.Connection); @@ -1343,7 +1390,7 @@ namespace Barotrauma.Networking if (items == null || !items.Any()) return; NetOutgoingMessage message = server.CreateMessage(); - message.WriteEnum(PacketTypes.NewItem); + message.Write((byte)PacketTypes.NewItem); Item.Spawner.FillNetworkData(message, items, inventories); @@ -1460,38 +1507,38 @@ namespace Barotrauma.Networking /// sends some random data to the clients /// use for debugging purposes /// - public void SendRandomData() - { - NetOutgoingMessage msg = server.CreateMessage(); - switch (Rand.Int(5)) - { - case 0: - msg.WriteEnum(PacketTypes.NetworkEvent); - msg.Write(Rand.Int(Enum.GetNames(typeof(NetworkEventType)).Length)); - msg.Write(Rand.Int(MapEntity.mapEntityList.Count)); - break; - case 1: - msg.WriteEnum(PacketTypes.NetworkEvent); - msg.WriteEnum(NetworkEventType.ComponentUpdate); - msg.Write((int)Item.ItemList[Rand.Int(Item.ItemList.Count)].ID); - msg.Write(Rand.Int(8)); - break; - case 2: - msg.Write((byte)Enum.GetNames(typeof(PacketTypes)).Length); - break; - case 3: - msg.Write((byte)PacketTypes.UpdateNetLobby); - break; - } + //public void SendRandomData() + //{ + // NetOutgoingMessage msg = server.CreateMessage(); + // switch (Rand.Int(5)) + // { + // case 0: + // msg.WriteEnum(PacketTypes.NetworkEvent); + // msg.Write(Rand.Int(Enum.GetNames(typeof(NetworkEventType)).Length)); + // msg.Write(Rand.Int(MapEntity.mapEntityList.Count)); + // break; + // case 1: + // msg.WriteEnum(PacketTypes.NetworkEvent); + // msg.WriteEnum(NetworkEventType.ComponentUpdate); + // msg.Write((int)Item.ItemList[Rand.Int(Item.ItemList.Count)].ID); + // msg.Write(Rand.Int(8)); + // break; + // case 2: + // msg.Write((byte)Enum.GetNames(typeof(PacketTypes)).Length); + // break; + // case 3: + // msg.Write((byte)PacketTypes.UpdateNetLobby); + // break; + // } - int bitCount = Rand.Int(100); - for (int i = 0; i < bitCount; i++) - { - msg.Write(Rand.Int(2) == 0); - } - SendMessage(msg, (Rand.Int(2) == 0) ? NetDeliveryMethod.ReliableOrdered : NetDeliveryMethod.Unreliable, null); + // int bitCount = Rand.Int(100); + // for (int i = 0; i < bitCount; i++) + // { + // msg.Write(Rand.Int(2) == 0); + // } + // SendMessage(msg, (Rand.Int(2) == 0) ? NetDeliveryMethod.ReliableOrdered : NetDeliveryMethod.Unreliable, null); - } + //} public override void Disconnect() { @@ -1523,6 +1570,8 @@ namespace Barotrauma.Networking public List jobPreferences; public JobPrefab assignedJob; + public FileStreamSender FileStreamSender; + public bool Spectating; public ReliableChannel ReliableChannel; diff --git a/Subsurface/Source/Networking/NetBufferExtensions.cs b/Subsurface/Source/Networking/NetBufferExtensions.cs index 0bec997fb..b328e20a5 100644 --- a/Subsurface/Source/Networking/NetBufferExtensions.cs +++ b/Subsurface/Source/Networking/NetBufferExtensions.cs @@ -5,14 +5,14 @@ namespace Barotrauma.Networking { static class NetBufferExtensions { - public static void WriteEnum(this NetBuffer buffer, Enum value) - { - buffer.WriteRangedInteger(0, Enum.GetValues(value.GetType()).Length - 1, Convert.ToInt32(value)); - } + //public static void WriteEnum(this NetBuffer buffer, Enum value) + //{ + // buffer.WriteRangedInteger(0, Enum.GetValues(value.GetType()).Length - 1, Convert.ToInt32(value)); + //} - public static TEnum ReadEnum(this NetBuffer buffer) - { - return (TEnum)(object)buffer.ReadRangedInteger(0, Enum.GetValues(typeof(TEnum)).Length - 1); - } + //public static TEnum ReadEnum(this NetBuffer buffer) + //{ + // return (TEnum)(object)buffer.ReadRangedInteger(0, Enum.GetValues(typeof(TEnum)).Length - 1); + //} } } diff --git a/Subsurface/Source/Networking/NetworkEvent.cs b/Subsurface/Source/Networking/NetworkEvent.cs index 9f98d3c68..563b7ffd8 100644 --- a/Subsurface/Source/Networking/NetworkEvent.cs +++ b/Subsurface/Source/Networking/NetworkEvent.cs @@ -132,7 +132,7 @@ namespace Barotrauma.Networking public bool FillData(NetBuffer message) { - message.WriteEnum(eventType); + message.Write((byte)eventType); Entity e = Entity.FindEntityByID(id); if (e == null) return false; @@ -189,7 +189,7 @@ namespace Barotrauma.Networking try { - eventType = message.ReadEnum(); + eventType = (NetworkEventType)message.ReadByte(); id = message.ReadUInt16(); } catch (Exception exception) diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index 72c83b042..7f75d07ed 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -7,7 +7,7 @@ using Lidgren.Network; namespace Barotrauma.Networking { - enum PacketTypes : int + enum PacketTypes : byte { Unknown, @@ -32,6 +32,8 @@ namespace Barotrauma.Networking Vote, VoteStatus, ResendRequest, ReliableMessage, LatestMessageID, + + RequestFile, FileStream, SpectateRequest } @@ -163,7 +165,7 @@ namespace Barotrauma.Networking if (msgBytes.Count == 0) return null; NetOutgoingMessage message = netPeer.CreateMessage(); - message.WriteEnum(PacketTypes.NetworkEvent); + message.Write((byte)PacketTypes.NetworkEvent); message.Write((float)NetTime.Now); @@ -295,25 +297,6 @@ namespace Barotrauma.Networking } public virtual void Disconnect() { } - - protected byte PlayerCountToByte(int playerCount, int maxPlayers) - { - byte byteVal = (byte)playerCount; - - byteVal |= (byte)((maxPlayers - 1) << 4); - - return byteVal; - } - - public static int ByteToPlayerCount(byte byteVal, out int maxPlayers) - { - maxPlayers = (byteVal >> 4)+1; - - int playerCount = byteVal & (byte)((1 << 4) - 1); - - return playerCount; - } - } } diff --git a/Subsurface/Source/Networking/ReliableSender.cs b/Subsurface/Source/Networking/ReliableSender.cs index b90244522..27059b237 100644 --- a/Subsurface/Source/Networking/ReliableSender.cs +++ b/Subsurface/Source/Networking/ReliableSender.cs @@ -94,7 +94,7 @@ namespace Barotrauma.Networking.ReliableMessages var reliableMessage = new ReliableMessage(message, messageID); - message.WriteEnum(PacketTypes.ReliableMessage); + message.Write((byte)PacketTypes.ReliableMessage); message.Write(messageID); @@ -184,7 +184,7 @@ namespace Barotrauma.Networking.ReliableMessages //Debug.WriteLine("Sending ack message: "+messageCount); NetOutgoingMessage message = sender.CreateMessage(); - message.WriteEnum(PacketTypes.LatestMessageID); + message.Write((byte)PacketTypes.LatestMessageID); message.Write(messageCount); @@ -244,7 +244,7 @@ namespace Barotrauma.Networking.ReliableMessages Debug.WriteLine("rerequest "+missingMessage.ID+" (try #"+missingMessage.ResendRequestsSent+")"); NetOutgoingMessage resendRequest = receiver.CreateMessage(); - resendRequest.WriteEnum(PacketTypes.ResendRequest); + resendRequest.Write((byte)PacketTypes.ResendRequest); resendRequest.Write(missingMessage.ID); @@ -443,6 +443,7 @@ namespace Barotrauma.Networking.ReliableMessages public void SaveInnerMessage() { + innerMessage.WritePadBits(); innerMessageBytes = innerMessage.PeekBytes(innerMessage.LengthBytes); //innerMessage = null; } diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs index c88ea34af..1cd4d37fe 100644 --- a/Subsurface/Source/Screens/NetLobbyScreen.cs +++ b/Subsurface/Source/Screens/NetLobbyScreen.cs @@ -37,6 +37,10 @@ namespace Barotrauma public bool IsServer; public string ServerName, ServerMessage; + const float NetworkUpdateInterval = 1.0f; + private float networkUpdateTimer; + private bool valueChanged; + private Sprite backgroundSprite; private GUITextBox serverMessage; @@ -327,7 +331,7 @@ namespace Barotrauma modeList.OnSelected = VotableClicked; modeList.OnSelected = SelectMode; subList.OnSelected = VotableClicked; - subList.OnSelected = SelectMap; + subList.OnSelected = SelectSub; traitorProbabilityButtons[0].OnClicked = ToggleTraitorsEnabled; traitorProbabilityButtons[1].OnClicked = ToggleTraitorsEnabled; @@ -484,8 +488,8 @@ namespace Barotrauma if (GameMain.Server == null) return false; GameMain.Server.AutoRestart = tickBox.Selected; - - GameMain.Server.UpdateNetLobby(tickBox); + + valueChanged = true; return true; } @@ -501,8 +505,8 @@ namespace Barotrauma if (index > 2) index = 0; SetTraitorsEnabled((YesNoMaybe)index); - - if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(null); + + valueChanged = true; return true; } @@ -515,9 +519,9 @@ namespace Barotrauma } - private bool SelectMap(GUIComponent component, object obj) + private bool SelectSub(GUIComponent component, object obj) { - if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(obj); + valueChanged = true; //Submarine sub = (Submarine)obj; @@ -558,7 +562,7 @@ namespace Barotrauma { if (GameMain.Server == null) return false; ServerName = text; - GameMain.Server.UpdateNetLobby(null, null); + valueChanged = true; return true; } @@ -567,7 +571,7 @@ namespace Barotrauma { if (GameMain.Server == null) return false; ServerMessage = text; - GameMain.Server.UpdateNetLobby(null, null); + valueChanged = true; return true; } @@ -692,6 +696,18 @@ namespace Barotrauma { if (GameMain.Server.BanList.BanFrame != null) GameMain.Server.BanList.BanFrame.Update((float)deltaTime); } + + if (valueChanged && GameMain.Server != null) + { + networkUpdateTimer -= (float)deltaTime; + if (networkUpdateTimer <= 0.0f) + { + GameMain.Server.UpdateNetLobby(null); + + valueChanged = false; + networkUpdateTimer = NetworkUpdateInterval; + } + } //durationBar.BarScroll = Math.Max(durationBar.BarScroll, 1.0f / 60.0f); } @@ -803,7 +819,7 @@ namespace Barotrauma GameModePreset modePreset = obj as GameModePreset; if (modePreset == null) return false; - if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(obj); + valueChanged = true; return true; } @@ -818,8 +834,8 @@ namespace Barotrauma //textBox.Text = LevelSeed; //textBox.Selected = false; - - if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(null); + + valueChanged = true; return true; } @@ -904,7 +920,18 @@ namespace Barotrauma Submarine sub = Submarine.SavedSubmarines.Find(m => m.Name == subName); if (sub == null) { - new GUIMessageBox("Submarine not found!","The submarine ''" + subName + "'' has been selected by the server. Matching file not found in your map folder."); + var requestFileBox = new GUIMessageBox("Submarine not found!", "The submarine ''" + subName + "'' has been selected by the server. " + +"Matching file not found in your map folder. Do you want to download the file from the server host?", new string[] { "Yes", "No" }); + requestFileBox.Buttons[0].UserData = subName; + requestFileBox.Buttons[0].OnClicked += requestFileBox.Close; + requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) => + { + GameMain.Client.RequestFile(userdata.ToString(), FileTransferType.Submarine); + return true; + }; + requestFileBox.Buttons[1].OnClicked += requestFileBox.Close; + + return false; } else @@ -949,7 +976,7 @@ namespace Barotrauma //msg.Write(AllowSubVoting); //msg.Write(AllowModeVoting); - msg.Write(modeList.SelectedIndex); + msg.Write((byte)modeList.SelectedIndex); //msg.Write(durationBar.BarScroll); msg.Write(LevelSeed); @@ -991,7 +1018,7 @@ namespace Barotrauma //AllowSubVoting = msg.ReadBoolean(); //AllowModeVoting = msg.ReadBoolean(); - modeIndex = msg.ReadInt32(); + modeIndex = msg.ReadByte(); //durationScroll = msg.ReadFloat(); @@ -1001,9 +1028,9 @@ namespace Barotrauma restartTimer = msg.ReadFloat(); int playerCount = msg.ReadByte(); - + playerList.ClearChildren(); - for (int i = 0; i 3) ? arguments[3] : ""; - string playerCountStr = (arguments.Length > 4) ? arguments[4] : ""; + string currPlayersStr = (arguments.Length > 4) ? arguments[4] : ""; + string maxPlayersStr = (arguments.Length > 5) ? arguments[5] : ""; + string hasPassWordStr = (arguments.Length > 5) ? arguments[5] : ""; - var serverFrame = new GUIFrame(new Rectangle(0,0,0,20), (i%2 == 0) ? Color.Transparent : Color.White*0.2f, null, serverList); - serverFrame.UserData = IP+":"+port; + var serverFrame = new GUIFrame(new Rectangle(0, 0, 0, 20), (i % 2 == 0) ? Color.Transparent : Color.White * 0.2f, null, serverList); + serverFrame.UserData = IP + ":" + port; serverFrame.HoverColor = Color.Gold * 0.2f; serverFrame.SelectedColor = Color.Gold * 0.5f; - var passwordBox = new GUITickBox(new Rectangle(columnX[0]/2, 0, 20, 20), "", Alignment.TopLeft, serverFrame); + var passwordBox = new GUITickBox(new Rectangle(columnX[0] / 2, 0, 20, 20), "", Alignment.TopLeft, serverFrame); passwordBox.Selected = hasPassWordStr == "1"; passwordBox.Enabled = false; passwordBox.UserData = "password"; var nameText = new GUITextBlock(new Rectangle(columnX[0], 0, 0, 0), serverName, GUI.Style, serverFrame); - int playerCount, maxPlayers; - playerCount = GameClient.ByteToPlayerCount((byte)int.Parse(playerCountStr), out maxPlayers); + int playerCount = 0, maxPlayers = 1; + int.TryParse(currPlayersStr, out playerCount); + int.TryParse(maxPlayersStr, out maxPlayers); var playerCountText = new GUITextBlock(new Rectangle(columnX[1], 0, 0, 0), playerCount + "/" + maxPlayers, GUI.Style, serverFrame); @@ -208,7 +211,7 @@ namespace Barotrauma if (client == null) yield return CoroutineStatus.Success; - var request = new RestRequest("masterserver.php", Method.GET); + var request = new RestRequest("masterserver2.php", Method.GET); request.AddParameter("gamename", "barotrauma"); // adds to POST or URL querystring based on Method request.AddParameter("action", "listservers"); // adds to POST or URL querystring based on Method diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index c08510be1..a02bd522a 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ