From cc9ae260a33fb69bda40a06612aae4f037a62768 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Thu, 21 Mar 2019 14:52:00 +0200 Subject: [PATCH] 58005a8...01f115d commit 01f115d32d768c76d01bc5fad5cfe2e3f88333cc Author: Joonas Rikkonen Date: Thu Mar 21 13:09:32 2019 +0200 MidRoundSyncing changes (could potentially fix #1281 and #1323): - Don't mark events as "sent to all" if there's a midround syncing client who'll need those events once the midround sync is done. - Don't keep updating midround syncing clients' unreceived event count as new unique events are created during midround sync, but instead just send the clients the unique events they were missing at the time of joining. Because the new events created during the midround syncing aren't removed anymore, the joining client will be able to receive them when they switch to normal sync. The old behaviour might've lead to cases where the client can't "catch up" with the new events while midround syncing, causing them to time out. commit 915aeb4e322ad04968556484aea74cf8b0070c3e Author: Joonas Rikkonen Date: Thu Mar 21 12:16:57 2019 +0200 Fixed end round vote count overlapping with the server log button, display the votes as votes/max instead of y/n. commit 62e3b272bb0235553562578493bf638a047235ab Author: Joonas Rikkonen Date: Wed Mar 20 23:36:03 2019 +0200 Updated handheld sonar UI graphics & moved it to the bottom left corner of the screen commit b93c7312c6bf4b560c8259e79650dbf1444072c9 Author: Joonas Rikkonen Date: Wed Mar 20 23:10:08 2019 +0200 Hide the start button from the campaign UI if the client doesn't have the permission to manage the campaign or rounds. --- .../Source/Networking/GameClient.cs | 30 +++++++++++----- .../Source/Screens/CampaignUI.cs | 13 +++++-- .../Source/Screens/NetLobbyScreen.cs | 7 ++++ .../ServerEntityEventManager.cs | 35 ++++++++++--------- .../Source/Networking/Voting.cs | 4 +-- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index 1deac6e29..e8a7fc784 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -132,6 +132,7 @@ namespace Barotrauma.Networking var buttonContainer = new GUILayoutGroup(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ButtonAreaTop, inGameHUD.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight) { + AbsoluteSpacing = 5, CanBeFocused = false }; @@ -147,9 +148,10 @@ namespace Barotrauma.Networking Visible = false }; - EndVoteTickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.6f), buttonContainer.RectTransform) { MinSize = new Point(150, 0) }, + EndVoteTickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.4f), buttonContainer.RectTransform) { MinSize = new Point(150, 0) }, TextManager.Get("EndRound")) { + UserData = TextManager.Get("EndRound"), OnSelected = ToggleEndRoundVote, Visible = false }; @@ -2209,13 +2211,25 @@ namespace Barotrauma.Networking if (EndVoteCount > 0) { - string endVoteText = TextManager.Get("EndRoundVotes") - .Replace("[y]", EndVoteCount.ToString()) - .Replace("[n]", (EndVoteMax - EndVoteCount).ToString()); - GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 10.0f - GUI.SmallFont.MeasureString(endVoteText).X, 40), - endVoteText, - Color.White, - font: GUI.SmallFont); + if (EndVoteTickBox.Visible) + { + EndVoteTickBox.Text = + (EndVoteTickBox.UserData as string) + " " + EndVoteCount + "/" + EndVoteMax; + } + else + { + string endVoteText = TextManager.Get("EndRoundVotes") + .Replace("[votes]", EndVoteCount.ToString()) + .Replace("[max]", EndVoteMax.ToString()); + GUI.DrawString(spriteBatch, EndVoteTickBox.Rect.Center.ToVector2() - GUI.SmallFont.MeasureString(endVoteText) / 2, + endVoteText, + Color.White, + font: GUI.SmallFont); + } + } + else + { + EndVoteTickBox.Text = EndVoteTickBox.UserData as string; } if (respawnManager != null) diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs index 12d87cf51..827b8af57 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs @@ -457,7 +457,10 @@ namespace Barotrauma { IgnoreLayoutGroups = true, OnClicked = (GUIButton btn, object obj) => { StartRound?.Invoke(); return true; }, - Enabled = true + Enabled = true, + Visible = GameMain.Client == null || + GameMain.Client.HasPermission(Networking.ClientPermissions.ManageRound) || + GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign) }; } @@ -502,7 +505,13 @@ namespace Barotrauma CanBeFocused = false }; - if (startButton != null) { startButton.Enabled = true; } + if (startButton != null) + { + startButton.Enabled = true; + startButton.Visible = GameMain.Client == null || + GameMain.Client.HasPermission(Networking.ClientPermissions.ManageRound) || + GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign); + } } private void CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, int width) diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs index 5651d6695..e249c088f 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs @@ -844,6 +844,13 @@ namespace Barotrauma GameMain.Client.ShowLogButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ServerLog); GameMain.Client.EndRoundButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound); + + if (campaignUI?.StartButton != null) + { + campaignUI.StartButton.Visible = + GameMain.Client.HasPermission(ClientPermissions.ManageRound) || + GameMain.Client.HasPermission(ClientPermissions.ManageCampaign); + } } public void ShowSpectateButton() diff --git a/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index 08a5f7a2e..275f94e51 100644 --- a/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -1,4 +1,5 @@ -using Lidgren.Network; +using Barotrauma.Extensions; +using Lidgren.Network; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; @@ -206,15 +207,19 @@ namespace Barotrauma.Networking lastSentToAll = owner.LastRecvEntityEventID; } } - inGameClients.ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.LastRecvEntityEventID)) lastSentToAll = c.LastRecvEntityEventID; }); + clients.Where(c => c.NeedsMidRoundSync).ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.FirstNewEventID)) lastSentToAll = (ushort)(c.FirstNewEventID - 1); }); + ServerEntityEvent firstEventToResend = events.Find(e => e.ID == (ushort)(lastSentToAll + 1)); if (firstEventToResend != null && (Timing.TotalTime - firstEventToResend.CreateTime) > 10.0f) { - //it's been 10 seconds since this event was created - //kick everyone that hasn't received it yet, this is way too old - List toKick = inGameClients.FindAll(c => NetIdUtils.IdMoreRecent((UInt16)(lastSentToAll + 1), c.LastRecvEntityEventID)); + //it's been 10 seconds since this event was created, kick everyone that hasn't received it yet, this is way too old + // UNLESS the event was created when the client was still midround syncing, in which case we'll wait until the timeout + // runs out before kicking the client + List toKick = inGameClients.FindAll(c => + NetIdUtils.IdMoreRecent((UInt16)(lastSentToAll + 1), c.LastRecvEntityEventID) && + (firstEventToResend.CreateTime > c.MidRoundSyncTimeOut || Timing.TotalTime > c.MidRoundSyncTimeOut)); toKick.ForEach(c => { DebugConsole.NewMessage(c.Name + " was kicked due to excessive desync (expected old event " + (c.LastRecvEntityEventID + 1).ToString() + ")", Color.Red); @@ -235,7 +240,7 @@ namespace Barotrauma.Networking toKick.ForEach(c => { DebugConsole.NewMessage(c.Name + " was kicked due to excessive desync (expected removed event " + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", Color.Red); - GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected removed event" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.ServerMessage); + GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected removed event " + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.ServerMessage); server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesyncRemovedEvent"); }); } @@ -318,15 +323,7 @@ namespace Barotrauma.Networking if (client.NeedsMidRoundSync) { - msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL); - - //how many (unique) events the clients had missed before joining - client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count; - //ID of the first event sent after the client joined - //(after the client has been synced they'll switch their lastReceivedID - //to the one before this, and the eventmanagers will start to function "normally") - client.FirstNewEventID = events.Count == 0 ? (UInt16)0 : events[events.Count - 1].ID; - + msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL); msg.Write(client.UnreceivedEntityEventCount); msg.Write(client.FirstNewEventID); @@ -394,9 +391,15 @@ namespace Barotrauma.Networking midRoundSyncTimeOut = Math.Max(10.0f, midRoundSyncTimeOut * 10.0f); client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count; - client.FirstNewEventID = 0; client.NeedsMidRoundSync = true; client.MidRoundSyncTimeOut = Timing.TotalTime + midRoundSyncTimeOut; + + //how many (unique) events the clients had missed before joining + client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count; + //ID of the first event sent after the client joined + //(after the client has been synced they'll switch their lastReceivedID + //to the one before this, and the eventmanagers will start to function "normally") + client.FirstNewEventID = events.Count == 0 ? (UInt16)0 : events[events.Count - 1].ID; } } diff --git a/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs b/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs index 6aa489dc4..67f5012ba 100644 --- a/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs +++ b/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs @@ -116,8 +116,8 @@ namespace Barotrauma msg.Write(AllowEndVoting); if (AllowEndVoting) { - msg.Write((byte)GameMain.Server.ConnectedClients.Count(v => v.GetVote(VoteType.EndRound))); - msg.Write((byte)GameMain.Server.ConnectedClients.Count); + msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote(VoteType.EndRound))); + msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned)); } msg.Write(AllowVoteKick);