Merge branch 'master' of https://github.com/Regalis11/Barotrauma into develop
This commit is contained in:
@@ -120,7 +120,7 @@ namespace Barotrauma.Networking
|
||||
if (radioNoiseChannel == null || !radioNoiseChannel.IsPlaying)
|
||||
{
|
||||
radioNoiseChannel = SoundPlayer.PlaySound("radiostatic");
|
||||
radioNoiseChannel.Category = "voip";
|
||||
radioNoiseChannel.Category = SoundManager.SoundCategoryVoip;
|
||||
radioNoiseChannel.Looping = true;
|
||||
}
|
||||
radioNoiseChannel.Near = VoipSound.Near;
|
||||
|
||||
@@ -50,25 +50,29 @@ readonly record struct ConnectCommand(
|
||||
NameAndLidgrenEndpointOption: endpoint is LidgrenEndpoint lidgrenEndpoint
|
||||
? Option.Some(new NameAndLidgrenEndpoint(ServerName: serverName, lidgrenEndpoint))
|
||||
: Option.None,
|
||||
SteamLobbyIdOption: Option.None) { }
|
||||
SteamLobbyIdOption: Option.None)
|
||||
{ }
|
||||
|
||||
public ConnectCommand(string serverName, ImmutableArray<P2PEndpoint> endpoints)
|
||||
: this(
|
||||
NameAndP2PEndpointsOption: Option.Some(new NameAndP2PEndpoints(ServerName: serverName, Endpoints: endpoints)),
|
||||
NameAndLidgrenEndpointOption: Option.None,
|
||||
SteamLobbyIdOption: Option.None) { }
|
||||
SteamLobbyIdOption: Option.None)
|
||||
{ }
|
||||
|
||||
public ConnectCommand(string serverName, LidgrenEndpoint endpoint)
|
||||
: this(
|
||||
NameAndP2PEndpointsOption: Option.None,
|
||||
NameAndLidgrenEndpointOption: Option.Some(new NameAndLidgrenEndpoint(ServerName: serverName, Endpoint: endpoint)),
|
||||
SteamLobbyIdOption: Option.None) { }
|
||||
SteamLobbyIdOption: Option.None)
|
||||
{ }
|
||||
|
||||
public ConnectCommand(SteamLobbyId lobbyId)
|
||||
: this(
|
||||
NameAndP2PEndpointsOption: Option.None,
|
||||
NameAndLidgrenEndpointOption: Option.None,
|
||||
SteamLobbyIdOption: Option.Some(lobbyId)) { }
|
||||
SteamLobbyIdOption: Option.Some(lobbyId))
|
||||
{ }
|
||||
|
||||
public static Option<ConnectCommand> Parse(string str)
|
||||
=> Parse(ToolBox.SplitCommand(str));
|
||||
|
||||
@@ -40,12 +40,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) { return; }
|
||||
Name = value;
|
||||
nameId++;
|
||||
ForceNameJobTeamUpdate();
|
||||
}
|
||||
|
||||
public void ForceNameJobTeamUpdate()
|
||||
{
|
||||
// Triggers SendLobbyUpdate() which causes the server to call GameServer.ClientReadLobby()
|
||||
// Deviously triggers SendLobbyUpdate() which causes the server to call GameServer.ClientReadLobby()
|
||||
nameId++;
|
||||
}
|
||||
|
||||
@@ -584,6 +584,9 @@ namespace Barotrauma.Networking
|
||||
private readonly List<IReadMessage> pendingIncomingMessages = new List<IReadMessage>();
|
||||
private readonly List<IReadMessage> incomingMessagesToProcess = new List<IReadMessage>();
|
||||
|
||||
private CoroutineHandle startGameCoroutine;
|
||||
private bool requestNewRoundStart;
|
||||
|
||||
private void ReadDataMessage(IReadMessage inc)
|
||||
{
|
||||
ServerPacketHeader header = (ServerPacketHeader)inc.ReadByte();
|
||||
@@ -718,9 +721,6 @@ namespace Barotrauma.Networking
|
||||
campaignUpdateIDs[flag] = inc.ReadUInt16();
|
||||
}
|
||||
|
||||
IWriteMessage readyToStartMsg = new WriteOnlyMessage();
|
||||
readyToStartMsg.WriteByte((byte)ClientPacketHeader.RESPONSE_STARTGAME);
|
||||
|
||||
if (campaign != null) { campaign.PendingSubmarineSwitch = null; }
|
||||
GameMain.NetLobbyScreen.UsingShuttle = usingShuttle;
|
||||
bool readyToStart;
|
||||
@@ -742,13 +742,9 @@ namespace Barotrauma.Networking
|
||||
campaign.LastSaveID == campaignSaveID &&
|
||||
campaignUpdateIDs.All(kvp => campaign.GetLastUpdateIdForFlag(kvp.Key) == kvp.Value);
|
||||
}
|
||||
readyToStartMsg.WriteBoolean(readyToStart);
|
||||
|
||||
DebugConsole.Log(readyToStart ? "Ready to start." : "Not ready to start.");
|
||||
|
||||
WriteCharacterInfo(readyToStartMsg);
|
||||
|
||||
ClientPeer.Send(readyToStartMsg, DeliveryMethod.Reliable);
|
||||
SendStartGameResponse(readyToStart: readyToStart);
|
||||
|
||||
if (readyToStart && !CoroutineManager.IsCoroutineRunning("WaitForStartRound"))
|
||||
{
|
||||
@@ -775,15 +771,34 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
case ServerPacketHeader.STARTGAME:
|
||||
DebugConsole.Log("Received STARTGAME packet.");
|
||||
if (Screen.Selected == GameMain.GameScreen && GameMain.GameSession?.GameMode is CampaignMode)
|
||||
if (GameMain.NetLobbyScreen is not { AFKSelected: true } || !ServerSettings.AllowAFK)
|
||||
{
|
||||
//start without a loading screen if playing a campaign round
|
||||
CoroutineManager.StartCoroutine(StartGame(inc));
|
||||
if (startGameCoroutine != null && CoroutineManager.IsCoroutineRunning(startGameCoroutine))
|
||||
{
|
||||
DebugConsole.Log("New round started before the previous one had finished loading. Starting a new round once loading the round finishes...");
|
||||
requestNewRoundStart = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Screen.Selected == GameMain.GameScreen && GameMain.GameSession?.GameMode is CampaignMode)
|
||||
{
|
||||
//start without a loading screen if playing a campaign round
|
||||
DebugConsole.Log($"Starting {nameof(StartGame)} coroutine...");
|
||||
startGameCoroutine = CoroutineManager.StartCoroutine(StartGame(inc));
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIMessageBox.CloseAll();
|
||||
DebugConsole.Log($"Starting {nameof(StartGame)} coroutine with a loading screen...");
|
||||
startGameCoroutine = GameMain.Instance.ShowLoading(StartGame(inc), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIMessageBox.CloseAll();
|
||||
GameMain.Instance.ShowLoading(StartGame(inc), false);
|
||||
//reselect to refresh the state of the screen (to indicate the round is running)
|
||||
GameStarted = true;
|
||||
GameMain.NetLobbyScreen?.Select();
|
||||
}
|
||||
break;
|
||||
case ServerPacketHeader.STARTGAMEFINALIZE:
|
||||
@@ -930,10 +945,19 @@ namespace Barotrauma.Networking
|
||||
contentToPreload.AddIfNotNull(file);
|
||||
}
|
||||
|
||||
byte roundId = inc.ReadByte();
|
||||
|
||||
string campaignErrorInfo = string.Empty;
|
||||
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign)
|
||||
{
|
||||
if (roundId != campaign.RoundID)
|
||||
{
|
||||
DebugConsole.AddWarning($"Received a StartGameFinalize message for an incorrect round (client: {campaign.RoundID}, server: {roundId}). The server might have started a new round before the client finished loading the previous one.");
|
||||
requestNewRoundStart = true;
|
||||
return;
|
||||
}
|
||||
campaignErrorInfo = $" Round start save ID: {debugStartGameCampaignSaveID}, last save id: {campaign.LastSaveID}, pending save id: {campaign.PendingSaveID}.";
|
||||
|
||||
}
|
||||
|
||||
GameMain.GameSession.EventManager.PreloadContent(contentToPreload);
|
||||
@@ -1409,6 +1433,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
private IEnumerable<CoroutineStatus> StartGame(IReadMessage inc)
|
||||
{
|
||||
DebugConsole.Log($"Running {nameof(StartGame)} coroutine");
|
||||
|
||||
Character?.Remove();
|
||||
Character = null;
|
||||
HasSpawned = false;
|
||||
@@ -1444,6 +1470,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
DebugConsole.ThrowError("Game mode \"" + modeIdentifier + "\" not found!");
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1461,7 +1488,11 @@ namespace Barotrauma.Networking
|
||||
GameMain.LightManager.LosMode = (LosMode)inc.ReadByte();
|
||||
ServerSettings.ShowEnemyHealthBars = (EnemyHealthBarMode)inc.ReadByte();
|
||||
bool includesFinalize = inc.ReadBoolean(); inc.ReadPadBits();
|
||||
|
||||
GameMain.LightManager.LightingEnabled = true;
|
||||
#if DEBUG
|
||||
GameMain.LightManager.LightingEnabled = !GameMain.DevMode;
|
||||
#endif
|
||||
|
||||
ServerSettings.ReadMonsterEnabled(inc);
|
||||
|
||||
@@ -1500,6 +1531,7 @@ namespace Barotrauma.Networking
|
||||
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, SelectedSubType.Sub, GameMain.NetLobbyScreen.SubList))
|
||||
{
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
@@ -1515,6 +1547,7 @@ namespace Barotrauma.Networking
|
||||
if (!GameMain.NetLobbyScreen.TrySelectSub(shuttleName, shuttleHash, SelectedSubType.Shuttle, GameMain.NetLobbyScreen.ShuttleList.ListBox))
|
||||
{
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
@@ -1544,6 +1577,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectSub" + subName, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
if (GameMain.NetLobbyScreen.SelectedShuttle == null ||
|
||||
@@ -1556,6 +1590,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectShuttle" + shuttleName, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1568,14 +1603,15 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign))
|
||||
if (GameMain.GameSession?.GameMode is not MultiPlayerCampaign campaign)
|
||||
{
|
||||
throw new InvalidOperationException("Attempted to start a campaign round when a campaign was not active.");
|
||||
}
|
||||
|
||||
if (GameMain.GameSession?.CrewManager != null) { GameMain.GameSession.CrewManager.Reset(); }
|
||||
GameMain.GameSession?.CrewManager?.Reset();
|
||||
|
||||
byte campaignID = inc.ReadByte();
|
||||
byte roundID = inc.ReadByte();
|
||||
UInt16 campaignSaveID = inc.ReadUInt16();
|
||||
int nextLocationIndex = inc.ReadInt32();
|
||||
int nextConnectionIndex = inc.ReadInt32();
|
||||
@@ -1588,6 +1624,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.ThrowError("Failed to start campaign round (campaign ID does not match).");
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1604,6 +1641,7 @@ namespace Barotrauma.Networking
|
||||
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("campaignsavetransfer.timeout"));
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
//use success status, even though this is a failure (no need to show a console error because we show it in the message box)
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
@@ -1617,6 +1655,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.ThrowError("Failed to start campaign round (campaign map not loaded yet).");
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1630,12 +1669,18 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (roundSummary != null)
|
||||
{
|
||||
loadTask = campaign.SelectSummaryScreen(roundSummary, levelData, mirrorLevel, null);
|
||||
loadTask = campaign.SelectSummaryScreen(roundSummary, levelData, mirrorLevel, () =>
|
||||
{
|
||||
DebugConsole.Log($"Set round ID from {campaign.RoundID} to {roundID}.");
|
||||
campaign.RoundID = roundID;
|
||||
});
|
||||
roundSummary.ContinueButton.Visible = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.GameSession.StartRound(levelData, mirrorLevel, startOutpost: campaign?.GetPredefinedStartOutpost());
|
||||
DebugConsole.Log($"Set round ID from {campaign.RoundID} to {roundID}.");
|
||||
campaign.RoundID = roundID;
|
||||
}
|
||||
isOutpost = levelData.Type == LevelData.LevelType.Outpost;
|
||||
}
|
||||
@@ -1654,9 +1699,16 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
DebugConsole.ThrowError("There was an error initializing the round (disconnected during the StartGame coroutine.)");
|
||||
roundInitStatus = RoundInitStatus.Error;
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
if (requestNewRoundStart)
|
||||
{
|
||||
RequestNewRoundStart();
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
roundInitStatus = RoundInitStatus.WaitingForStartGameFinalize;
|
||||
|
||||
//wait for up to 30 seconds for the server to send the STARTGAMEFINALIZE message
|
||||
@@ -1678,6 +1730,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (requestNewRoundStart)
|
||||
{
|
||||
RequestNewRoundStart();
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (DateTime.Now > requestFinalizeTime)
|
||||
@@ -1742,10 +1800,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
DebugConsole.ThrowError(roundInitStatus.ToString());
|
||||
CoroutineManager.StartCoroutine(EndGame(""));
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
else
|
||||
{
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
}
|
||||
@@ -1754,6 +1814,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.GameSession.Submarine.Info.IsFileCorrupted)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to start a round. Could not load the submarine \"{GameMain.GameSession.Submarine.Info.Name}\".");
|
||||
startGameCoroutine = null;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1801,6 +1862,17 @@ namespace Barotrauma.Networking
|
||||
AddChatMessage(message, ChatMessageType.Server);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
|
||||
void RequestNewRoundStart()
|
||||
{
|
||||
GameMain.GameSession?.EndRound("");
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
CoroutineManager.StopCoroutines("LevelTransition");
|
||||
roundInitStatus = RoundInitStatus.Error;
|
||||
startGameCoroutine = null;
|
||||
SendJoinOngoingRequest(joinButton: null);
|
||||
requestNewRoundStart = false;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<CoroutineStatus> EndGame(string endMessage, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None, TraitorManager.TraitorResults? traitorResults = null)
|
||||
@@ -1910,6 +1982,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
GameStarted = inc.ReadBoolean();
|
||||
bool allowSpectating = inc.ReadBoolean();
|
||||
bool allowAFK = inc.ReadBoolean();
|
||||
bool permadeathMode = inc.ReadBoolean();
|
||||
bool ironmanMode = inc.ReadBoolean();
|
||||
|
||||
@@ -1929,7 +2002,7 @@ namespace Barotrauma.Networking
|
||||
message = TextManager.Get(allowSpectating ? "RoundRunningSpectateEnabled" : "RoundRunningSpectateDisabled");
|
||||
}
|
||||
new GUIMessageBox(TextManager.Get("PleaseWait"), message);
|
||||
if (!(Screen.Selected is ModDownloadScreen)) { GameMain.NetLobbyScreen.Select(); }
|
||||
if (Screen.Selected is not ModDownloadScreen) { GameMain.NetLobbyScreen.Select(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2002,8 +2075,7 @@ namespace Barotrauma.Networking
|
||||
Name = tc.Name;
|
||||
nameId = tc.NameId;
|
||||
}
|
||||
if (GameMain.NetLobbyScreen.CharacterNameBox != null &&
|
||||
!GameMain.NetLobbyScreen.CharacterNameBox.Selected)
|
||||
if (GameMain.NetLobbyScreen.CharacterNameBox is { Selected: false, Enabled: true })
|
||||
{
|
||||
GameMain.NetLobbyScreen.CharacterNameBox.Text = Name;
|
||||
}
|
||||
@@ -2117,6 +2189,7 @@ namespace Barotrauma.Networking
|
||||
bool voiceChatEnabled = inc.ReadBoolean();
|
||||
|
||||
bool allowSpectating = inc.ReadBoolean();
|
||||
bool allowAFK = inc.ReadBoolean();
|
||||
|
||||
float traitorProbability = inc.ReadSingle();
|
||||
int traitorDangerLevel = inc.ReadRangedInteger(TraitorEventPrefab.MinDangerLevel, TraitorEventPrefab.MaxDangerLevel);
|
||||
@@ -2194,6 +2267,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen.SetAllowSpectating(allowSpectating);
|
||||
GameMain.NetLobbyScreen.SetAllowAFK(allowAFK);
|
||||
GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty);
|
||||
GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode);
|
||||
GameMain.NetLobbyScreen.SetBotCount(botCount);
|
||||
@@ -2386,6 +2460,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.WriteUInt16(GameMain.NetLobbyScreen.LastUpdateID);
|
||||
outmsg.WriteUInt16(ChatMessage.LastID);
|
||||
outmsg.WriteUInt16(LastClientListUpdateID);
|
||||
outmsg.WriteBoolean(GameMain.NetLobbyScreen.AFKSelected);
|
||||
outmsg.WriteUInt16(nameId);
|
||||
outmsg.WriteString(Name);
|
||||
var jobPreferences = GameMain.NetLobbyScreen.JobPreferences;
|
||||
@@ -2532,6 +2607,15 @@ namespace Barotrauma.Networking
|
||||
msg.WriteUInt16(bot.ID);
|
||||
ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void ToggleReserveBench(CharacterInfo bot, bool pendingHire = false)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ClientPacketHeader.TOGGLE_RESERVE_BENCH);
|
||||
msg.WriteUInt16(bot.ID);
|
||||
msg.WriteBoolean(pendingHire);
|
||||
ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void RequestFile(FileTransferType fileType, string file, string fileHash)
|
||||
{
|
||||
@@ -2796,8 +2880,12 @@ namespace Barotrauma.Networking
|
||||
public void WriteCharacterInfo(IWriteMessage msg, string newName = null)
|
||||
{
|
||||
msg.WriteBoolean(GameMain.NetLobbyScreen.Spectating);
|
||||
msg.WriteBoolean(GameMain.NetLobbyScreen.CampaignCharacterDiscarded);
|
||||
bool writeInfo = characterInfo != null;
|
||||
msg.WriteBoolean(writeInfo);
|
||||
msg.WritePadBits();
|
||||
if (characterInfo == null) { return; }
|
||||
|
||||
if (!writeInfo) { return; }
|
||||
|
||||
var head = characterInfo.Head;
|
||||
|
||||
@@ -3080,9 +3168,9 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tell the server to end the round (permission required)
|
||||
/// Tell the server to end the round (permission required).
|
||||
/// </summary>
|
||||
public void RequestRoundEnd(bool save, bool quitCampaign = false)
|
||||
public void RequestEndRound(bool save, bool quitCampaign = false)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ClientPacketHeader.SERVER_COMMAND);
|
||||
@@ -3094,7 +3182,31 @@ namespace Barotrauma.Networking
|
||||
ClientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public bool JoinOnGoingClicked(GUIButton button, object _)
|
||||
/// <summary>
|
||||
/// End the round locally (just returning to the lobby without ending the round for everyone).
|
||||
/// </summary>
|
||||
public void EndRoundForSelf()
|
||||
{
|
||||
GameMain.GameSession?.EndRound(endMessage: string.Empty, createRoundSummary: false);
|
||||
Submarine.Unload();
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
Character.Controlled = null;
|
||||
WaitForNextRoundRespawn = null;
|
||||
RespawnManager = null;
|
||||
|
||||
EntityEventManager?.Clear();
|
||||
LastSentEntityEventID = 0;
|
||||
|
||||
MyClient.CharacterID = Entity.NullEntityID;
|
||||
|
||||
roundInitStatus = RoundInitStatus.NotStarted;
|
||||
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ClientPacketHeader.ENDROUND_SELF);
|
||||
ClientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public bool SendJoinOngoingRequest(GUIButton joinButton)
|
||||
{
|
||||
MultiPlayerCampaign campaign =
|
||||
GameMain.NetLobbyScreen.SelectedMode == GameMain.GameSession?.GameMode.Preset ?
|
||||
@@ -3106,23 +3218,32 @@ namespace Barotrauma.Networking
|
||||
new GUIMessageBox("", TextManager.Get("campaignfiletransferinprogress"));
|
||||
return false;
|
||||
}
|
||||
if (button != null) { button.Enabled = false; }
|
||||
if (joinButton != null) { joinButton.Enabled = false; }
|
||||
if (campaign != null) { LateCampaignJoin = true; }
|
||||
|
||||
if (ClientPeer == null) { return false; }
|
||||
|
||||
//assume we have the required sub files to start the round
|
||||
//(if not, we'll find out when the server sends the STARTGAME message and can initiate a file transfer)
|
||||
SendStartGameResponse(readyToStart: true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SendStartGameResponse(bool readyToStart)
|
||||
{
|
||||
IWriteMessage readyToStartMsg = new WriteOnlyMessage();
|
||||
readyToStartMsg.WriteByte((byte)ClientPacketHeader.RESPONSE_STARTGAME);
|
||||
|
||||
//assume we have the required sub files to start the round
|
||||
//(if not, we'll find out when the server sends the STARTGAME message and can initiate a file transfer)
|
||||
readyToStartMsg.WriteBoolean(true);
|
||||
readyToStartMsg.WriteBoolean(readyToStart);
|
||||
readyToStartMsg.WriteBoolean(GameMain.NetLobbyScreen.AFKSelected && ServerSettings.AllowAFK);
|
||||
|
||||
WriteCharacterInfo(readyToStartMsg);
|
||||
|
||||
ClientPeer.Send(readyToStartMsg, DeliveryMethod.Reliable);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool SetReadyToStart(GUITickBox tickBox)
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace Barotrauma.Networking
|
||||
protected bool IsOwner => ownerKey.IsSome();
|
||||
protected readonly Option<int> ownerKey;
|
||||
|
||||
/// <summary>
|
||||
/// Has the ClientPeer been started? Set to true in <see cref="Start"/>, set to false when shutting the client down <see cref="Close(PeerDisconnectPacket)"/>.
|
||||
/// </summary>
|
||||
public bool IsActive => isActive;
|
||||
|
||||
protected bool isActive;
|
||||
@@ -104,8 +107,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
TaskPool.Add($"{GetType().Name}.{nameof(GetAccountId)}", GetAccountId(), t =>
|
||||
{
|
||||
// FIXME what to do with this?
|
||||
//if (GameMain.Client?.ClientPeer is null) { return; }
|
||||
if (!IsActive)
|
||||
{
|
||||
//client has become inactive (cancelled/disconnected while waiting for initialization)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!t.TryGetResult(out Option<AccountId> accountId))
|
||||
{
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace Barotrauma.Networking
|
||||
var teamId = (CharacterTeamType)msg.ReadByte();
|
||||
|
||||
bool respawnPromptPending = false;
|
||||
bool clientHasChosenNewBotViaShuttle = false;
|
||||
var newState = (State)msg.ReadRangedInteger(0, Enum.GetNames(typeof(State)).Length);
|
||||
switch (newState)
|
||||
{
|
||||
@@ -70,18 +71,20 @@ namespace Barotrauma.Networking
|
||||
teamSpecificState.ReturnCountdownStarted = msg.ReadBoolean();
|
||||
maxTransportTime = msg.ReadSingle();
|
||||
float transportTimeLeft = msg.ReadSingle();
|
||||
|
||||
teamSpecificState.ReturnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: (int)(transportTimeLeft * 1000.0f));
|
||||
teamSpecificState.RespawnCountdownStarted = false;
|
||||
SetShuttleBodyType(teamSpecificState.TeamID, FarseerPhysics.BodyType.Dynamic);
|
||||
break;
|
||||
case State.Waiting:
|
||||
teamSpecificState.PendingRespawnCount = msg.ReadUInt16();
|
||||
teamSpecificState.RequiredRespawnCount = msg.ReadUInt16();
|
||||
respawnPromptPending = msg.ReadBoolean();
|
||||
clientHasChosenNewBotViaShuttle = msg.ReadBoolean();
|
||||
teamSpecificState.RespawnCountdownStarted = msg.ReadBoolean();
|
||||
ResetShuttle(teamSpecificState);
|
||||
float newRespawnTime = msg.ReadSingle();
|
||||
teamSpecificState.RespawnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: (int)(newRespawnTime * 1000.0f));
|
||||
SetShuttleBodyType(teamSpecificState.TeamID, FarseerPhysics.BodyType.Static);
|
||||
break;
|
||||
case State.Returning:
|
||||
teamSpecificState.RespawnCountdownStarted = false;
|
||||
@@ -89,7 +92,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
teamSpecificState.CurrentState = newState;
|
||||
|
||||
if (respawnPromptPending)
|
||||
if (respawnPromptPending && !clientHasChosenNewBotViaShuttle)
|
||||
{
|
||||
GameMain.Client.HasSpawned = true;
|
||||
DeathPrompt.Create(delay: 1.0f);
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
float playStyleBannerAspectRatio = (float)playStyleBannerSprite.SourceRect.Width / (float)playStyleBannerSprite.SourceRect.Height;
|
||||
playStyleBanner = new GUIImage(new RectTransform(new Vector2(1.0f, 1.0f / playStyleBannerAspectRatio), frame.RectTransform, scaleBasis: ScaleBasis.BothWidth),
|
||||
playStyleBannerSprite, null, true);
|
||||
playStyleBannerSprite, scaleToFit: true);
|
||||
playStyleBannerColor = playStyleBannerSprite.SourceElement.GetAttributeColor("bannercolor", Color.Black);
|
||||
}
|
||||
else
|
||||
@@ -385,14 +385,24 @@ namespace Barotrauma.Networking
|
||||
{ MinSize = new Point(0, 15) },
|
||||
package.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
Enabled = false
|
||||
};
|
||||
packageText.Box.DisabledColor = packageText.Box.Color;
|
||||
packageText.TextBlock.DisabledTextColor = packageText.TextBlock.TextColor;
|
||||
if (!string.IsNullOrEmpty(package.Hash))
|
||||
{
|
||||
if (ContentPackageManager.AllPackages.Any(contentPackage => contentPackage.Hash.StringRepresentation == package.Hash))
|
||||
if (ContentPackageManager.AllPackages.FirstOrDefault(contentPackage => contentPackage.Hash.StringRepresentation == package.Hash) is { } matchingPackage)
|
||||
{
|
||||
packageText.TextColor = GUIStyle.Green;
|
||||
packageText.Selected = true;
|
||||
matchingPackage.TryFetchUgcDescription(onFinished: (string? description) =>
|
||||
{
|
||||
if (packageText.ToolTip.IsNullOrEmpty() &&
|
||||
!string.IsNullOrEmpty(description))
|
||||
{
|
||||
packageText.ToolTip = description + "...";
|
||||
}
|
||||
});
|
||||
}
|
||||
//workshop download link found
|
||||
else if (package.Id.TryUnwrap(out var ugcId) && ugcId is SteamWorkshopId)
|
||||
@@ -437,7 +447,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void UpdateInfo(Func<string, string?> valueGetter)
|
||||
{
|
||||
ServerMessage = valueGetter("message") ?? "";
|
||||
ServerMessage = ExtractServerMessage(valueGetter);
|
||||
if (Version.TryParse(valueGetter("version"), out var version))
|
||||
{
|
||||
GameVersion = version;
|
||||
@@ -477,6 +487,22 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private static string ExtractServerMessage(Func<string, string?> valueGetter)
|
||||
{
|
||||
string msg = valueGetter("message") ?? string.Empty;
|
||||
if (!msg.IsNullOrEmpty()) { return msg; }
|
||||
|
||||
int messageIndex = 0;
|
||||
string splitMessage;
|
||||
do
|
||||
{
|
||||
splitMessage = valueGetter($"message{messageIndex}") ?? string.Empty;
|
||||
msg += splitMessage;
|
||||
messageIndex++;
|
||||
} while (!splitMessage.IsNullOrEmpty());
|
||||
return msg;
|
||||
}
|
||||
|
||||
private static ServerListContentPackageInfo[] ExtractContentPackageInfo(string serverName, Func<string, string?> valueGetter)
|
||||
{
|
||||
//workaround to ServerRules queries truncating the values to 255 bytes
|
||||
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -67,6 +67,7 @@ namespace Barotrauma
|
||||
return null;
|
||||
});
|
||||
serverInfo.Checked = true;
|
||||
serverInfo.HasPassword |= entry.Passworded;
|
||||
|
||||
onServerDataReceived(serverInfo, this);
|
||||
});
|
||||
|
||||
@@ -465,6 +465,12 @@ namespace Barotrauma.Networking
|
||||
var allowSpecBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsAllowSpectating"));
|
||||
AssignGUIComponent(nameof(AllowSpectating), allowSpecBox);
|
||||
|
||||
var allowAfkBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsAllowAFK"))
|
||||
{
|
||||
ToolTip = TextManager.Get("ServerSettingsAllowAFK.tooltip")
|
||||
};
|
||||
AssignGUIComponent(nameof(AllowAFK), allowAfkBox);
|
||||
|
||||
var losModeLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
|
||||
TextManager.Get("LosEffect"));
|
||||
var losModeSelection = new GUISelectionCarousel<LosMode>(new RectTransform(new Vector2(0.5f, 0.6f), losModeLabel.RectTransform, Anchor.CenterRight));
|
||||
|
||||
@@ -116,12 +116,12 @@ namespace Barotrauma.Networking
|
||||
bool spectating = Character.Controlled == null;
|
||||
float rangeMultiplier = spectating ? 2.0f : 1.0f;
|
||||
WifiComponent senderRadio = null;
|
||||
|
||||
var messageType =
|
||||
!client.VoipQueue.ForceLocal &&
|
||||
ChatMessage.CanUseRadio(client.Character, out senderRadio) &&
|
||||
ChatMessage.CanUseRadio(Character.Controlled, out var recipientRadio) &&
|
||||
senderRadio.CanReceive(recipientRadio) ?
|
||||
ChatMessageType.Radio : ChatMessageType.Default;
|
||||
(spectating || (ChatMessage.CanUseRadio(Character.Controlled, out var recipientRadio) && senderRadio.CanReceive(recipientRadio)))
|
||||
? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
client.Character.ShowTextlessSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
||||
|
||||
client.VoipSound.UseRadioFilter = messageType == ChatMessageType.Radio && !GameSettings.CurrentConfig.Audio.DisableVoiceChatFilters;
|
||||
@@ -149,7 +149,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetLobbyScreen?.SetPlayerSpeaking(client);
|
||||
GameMain.GameSession?.CrewManager?.SetClientSpeaking(client);
|
||||
|
||||
if ((client.VoipSound.CurrentAmplitude * client.VoipSound.Gain * GameMain.SoundManager.GetCategoryGainMultiplier("voip")) > 0.1f) //TODO: might need to tweak
|
||||
if ((client.VoipSound.CurrentAmplitude * client.VoipSound.Gain * GameMain.SoundManager.GetCategoryGainMultiplier(SoundManager.SoundCategoryVoip)) > 0.1f) //TODO: might need to tweak
|
||||
{
|
||||
if (client.Character != null && !client.Character.Removed && !client.Character.IsDead)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user