diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index be04a7891..6471bc32d 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -793,8 +793,7 @@ namespace Barotrauma.Networking } GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, submarines); - GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, submarines); - + GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, submarines); gameStarted = inc.ReadBoolean(); bool allowSpectating = inc.ReadBoolean(); @@ -847,6 +846,8 @@ namespace Barotrauma.Networking bool allowSubVoting = inc.ReadBoolean(); bool allowModeVoting = inc.ReadBoolean(); + bool allowSpectating = inc.ReadBoolean(); + YesNoMaybe traitorsEnabled = (YesNoMaybe)inc.ReadRangedInteger(0, 2); int missionTypeIndex = inc.ReadRangedInteger(0, Mission.MissionTypes.Count - 1); int modeIndex = inc.ReadByte(); @@ -888,6 +889,8 @@ namespace Barotrauma.Networking { GameMain.NetLobbyScreen.SelectMode(modeIndex); } + + GameMain.NetLobbyScreen.SetAllowSpectating(allowSpectating); GameMain.NetLobbyScreen.LevelSeed = levelSeed; @@ -1213,6 +1216,7 @@ namespace Barotrauma.Networking public void WriteCharacterInfo(NetOutgoingMessage msg) { + msg.Write(characterInfo == null); if (characterInfo == null) return; msg.Write(characterInfo.Gender == Gender.Male); diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs index 72fe0a72b..689f49989 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs @@ -314,6 +314,7 @@ namespace Barotrauma.Networking allowSpecBox.OnSelected = (GUITickBox) => { AllowSpectating = GUITickBox.Selected; + GameMain.NetLobbyScreen.LastUpdateID++; return true; }; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs index 75b8afefa..e8af9e986 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs @@ -415,6 +415,19 @@ namespace Barotrauma campaignViewButton.OnClicked = (btn, obj) => { ToggleCampaignView(true); return true; }; campaignViewButton.Visible = false; + if (myPlayerFrame.children.Find(c => c.UserData as string == "playyourself") == null) + { + var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); + playYourself.Selected = GameMain.NetworkMember.CharacterInfo != null; + playYourself.OnSelected = TogglePlayYourself; + playYourself.UserData = "playyourself"; + + if (GameMain.NetworkMember.CharacterInfo != null) + { + TogglePlayYourself(playYourself); + } + } + if (IsServer && GameMain.Server != null) { List subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)).ToList(); @@ -441,7 +454,6 @@ namespace Barotrauma StartButton = new GUIButton(new Rectangle(0, 0, 80, 30), "Start", Alignment.BottomRight, "", defaultModeContainer); StartButton.OnClicked = GameMain.Server.StartGameClicked; - GUIButton settingsButton = new GUIButton(new Rectangle(-110, 0, 80, 20), "Settings", Alignment.TopRight, "", infoFrame); settingsButton.OnClicked = GameMain.Server.ToggleSettingsFrame; settingsButton.UserData = "settingsButton"; @@ -462,14 +474,6 @@ namespace Barotrauma if (GameModePreset.list.Count > 0 && modeList.Selected == null) modeList.Select(0); - if (myPlayerFrame.children.Find(c => c.UserData as string == "playyourself") == null) - { - var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); - playYourself.Selected = GameMain.Server.CharacterInfo != null; - playYourself.OnSelected = TogglePlayYourself; - playYourself.UserData = "playyourself"; - } - GameMain.Server.Voting.ResetVotes(GameMain.Server.ConnectedClients); if (GameMain.Server.RandomizeSeed) LevelSeed = ToolBox.RandomSeed(8); @@ -490,8 +494,6 @@ namespace Barotrauma } GameMain.Client.Voting.ResetVotes(GameMain.Client.ConnectedClients); - - UpdatePlayerFrame(GameMain.Client.CharacterInfo); } GameMain.NetworkMember.EndVoteCount = 0; @@ -512,24 +514,15 @@ namespace Barotrauma private void UpdatePlayerFrame(CharacterInfo characterInfo) { - if (myPlayerFrame.children.Count <= 1) + if (myPlayerFrame.children.Count <= 2) { myPlayerFrame.ClearChildren(); - - if (IsServer && GameMain.Server != null) - { - var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); - playYourself.Selected = GameMain.Server.CharacterInfo != null; - playYourself.OnSelected = TogglePlayYourself; - playYourself.UserData = "playyourself"; - } - - //new GUITextBlock(new Rectangle(100, 30, 200, 30), "Name: ", "", myPlayerFrame); - - //GUITextBox playerName = new GUITextBox(new Rectangle(100, 55, 0, 20), Alignment.TopLeft, "", myPlayerFrame); - //playerName.Text = characterInfo.Name; - //playerName.OnEnterPressed += ChangeCharacterName; - + + var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); + playYourself.Selected = GameMain.NetworkMember.CharacterInfo != null; + playYourself.OnSelected = TogglePlayYourself; + playYourself.UserData = "playyourself"; + GUIButton toggleHead = new GUIButton(new Rectangle(0, 50, 15, 15), "<", "", myPlayerFrame); toggleHead.UserData = -1; toggleHead.OnClicked = ToggleHead; @@ -590,34 +583,48 @@ namespace Barotrauma UpdateJobPreferences(jobList); - UpdatePreviewPlayer(characterInfo); + UpdatePlayerHead(characterInfo); } } - - private bool TogglePlayYourself(GUITickBox tickBox) + + public bool TogglePlayYourself(GUITickBox tickBox) { if (tickBox.Selected) { - GameMain.Server.CharacterInfo = new CharacterInfo(Character.HumanConfigFile, GameMain.Server.Name,Gender.None,null); - UpdatePlayerFrame(GameMain.Server.CharacterInfo); + GameMain.NetworkMember.CharacterInfo = new CharacterInfo(Character.HumanConfigFile, GameMain.NetworkMember.Name, Gender.None, null); + UpdatePlayerFrame(GameMain.NetworkMember.CharacterInfo); } else { myPlayerFrame.ClearChildren(); + + GameMain.NetworkMember.CharacterInfo = null; + GameMain.NetworkMember.Character = null; - if (IsServer && GameMain.Server != null) - { - GameMain.Server.CharacterInfo = null; - GameMain.Server.Character = null; + new GUITextBlock(Rectangle.Empty, "Playing as a spectator", "", Alignment.Center, Alignment.Center, myPlayerFrame, true); - var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); - playYourself.OnSelected = TogglePlayYourself; - playYourself.UserData = "playyourself"; - } + var playYourself = new GUITickBox(new Rectangle(0, 0, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); + playYourself.OnSelected = TogglePlayYourself; + playYourself.UserData = "playyourself"; } return false; } + public void SetAllowSpectating(bool allowSpectating) + { + GUITickBox playYourselfTickBox = myPlayerFrame?.FindChild("playyourself") as GUITickBox; + if (playYourselfTickBox == null) return; + + //show the player config menu if spectating is not allowed + if (!playYourselfTickBox.Selected && !allowSpectating) + { + playYourselfTickBox.Selected = !playYourselfTickBox.Selected; + TogglePlayYourself(playYourselfTickBox); + } + //hide "play yourself" tickbox if spectating is not allowed + playYourselfTickBox.Visible = allowSpectating; + } + public void SetAutoRestart(bool enabled, float timer = 0.0f) { autoRestartBox.Selected = enabled; @@ -1079,7 +1086,7 @@ namespace Barotrauma if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f; } - private void UpdatePreviewPlayer(CharacterInfo characterInfo) + private void UpdatePlayerHead(CharacterInfo characterInfo) { GUIComponent existing = myPlayerFrame.FindChild("playerhead"); if (existing != null) myPlayerFrame.RemoveChild(existing); @@ -1096,7 +1103,7 @@ namespace Barotrauma GameMain.NetworkMember.CharacterInfo.HeadSpriteId += dir; - UpdatePreviewPlayer(GameMain.NetworkMember.CharacterInfo); + UpdatePlayerHead(GameMain.NetworkMember.CharacterInfo); return true; } @@ -1106,7 +1113,7 @@ namespace Barotrauma Gender gender = (Gender)obj; GameMain.NetworkMember.CharacterInfo.Gender = gender; - UpdatePreviewPlayer(GameMain.NetworkMember.CharacterInfo); + UpdatePlayerHead(GameMain.NetworkMember.CharacterInfo); return true; } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/Client.cs b/Barotrauma/BarotraumaShared/Source/Networking/Client.cs index 6be80e69f..691266248 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/Client.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/Client.cs @@ -48,7 +48,6 @@ namespace Barotrauma.Networking public List chatMsgQueue = new List(); public UInt16 lastChatMsgQueueID; - //latest chat messages sent by this client public List lastSentChatMessages = new List(); public float ChatSpamSpeed; @@ -81,6 +80,8 @@ namespace Barotrauma.Networking public ClientPermissions Permissions = ClientPermissions.None; + public bool SpectateOnly; + public Queue PendingPositionUpdates { get { return pendingPositionUpdates; } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index f09e2632e..f99cd6705 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -952,6 +952,8 @@ namespace Barotrauma.Networking outmsg.Write(Voting.AllowSubVoting); outmsg.Write(Voting.AllowModeVoting); + outmsg.Write(AllowSpectating); + outmsg.WriteRangedInteger(0, 2, (int)TraitorsEnabled); outmsg.WriteRangedInteger(0, Mission.MissionTypes.Count - 1, (GameMain.NetLobbyScreen.MissionTypeIndex)); @@ -1209,8 +1211,12 @@ namespace Barotrauma.Networking for (int teamID = 1; teamID <= teamCount; teamID++) { //find the clients in this team - List teamClients = teamCount == 1 ? connectedClients : connectedClients.FindAll(c => c.TeamID == teamID); - + List teamClients = teamCount == 1 ? new List(connectedClients) : connectedClients.FindAll(c => c.TeamID == teamID); + if (AllowSpectating) + { + teamClients.RemoveAll(c => c.SpectateOnly); + } + if (!teamClients.Any() && teamID > 1) continue; AssignJobs(teamClients, teamID == hostTeam); @@ -1949,6 +1955,12 @@ namespace Barotrauma.Networking private void UpdateCharacterInfo(NetIncomingMessage message, Client sender) { + sender.SpectateOnly = message.ReadBoolean() && AllowSpectating; + if (sender.SpectateOnly) + { + return; + } + Gender gender = Gender.Male; int headSpriteId = 0; try diff --git a/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs b/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs index d8fa87f55..32fc974b8 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs @@ -110,7 +110,10 @@ namespace Barotrauma.Networking private List GetClientsToRespawn() { - return networkMember.ConnectedClients.FindAll(c => c.inGame && (c.Character == null || c.Character.IsDead)); + return networkMember.ConnectedClients.FindAll(c => + c.inGame && + (!c.SpectateOnly || !((GameServer)networkMember).AllowSpectating) && + (c.Character == null || c.Character.IsDead)); } public void Update(float deltaTime)