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:
juanjp600
2016-08-30 19:59:14 -03:00
parent 37ffd64490
commit 9416eb64d7
31 changed files with 72 additions and 1437 deletions

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}
}
}