Merge branch 'master' of https://github.com/Regalis11/Barotrauma into develop
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user