Unstable 0.17.5.0

This commit is contained in:
Markus Isberg
2022-03-30 01:20:59 +09:00
parent c1b8e5a341
commit 44ded0225a
88 changed files with 2033 additions and 1430 deletions
@@ -130,6 +130,8 @@ namespace Barotrauma.Networking
KarmaManager.SelectPreset(serverSettings.KarmaPreset);
serverSettings.SetPassword(password);
Voting = new Voting();
ownerKey = ownKey;
ownerSteamId = steamId;
@@ -383,23 +385,7 @@ namespace Barotrauma.Networking
TraitorManager?.Update(deltaTime);
if (serverSettings.Voting.VoteRunning)
{
Voting.SubVote.Timer += deltaTime;
if (Voting.SubVote.Timer >= serverSettings.SubmarineVoteTimeout)
{
// Do not take unanswered into account for total
if (SubmarineVoteYesCount / (float)(SubmarineVoteYesCount + SubmarineVoteNoCount) >= serverSettings.SubmarineVoteRequiredRatio)
{
SwitchSubmarine();
}
else
{
serverSettings.Voting.StopSubmarineVote(false);
}
}
}
Voting.Update(deltaTime);
bool isCrewDead =
connectedClients.All(c => c.Character == null || c.Character.IsDead || c.Character.IsIncapacitated);
@@ -1073,7 +1059,7 @@ namespace Barotrauma.Networking
ChatMessage.ServerRead(inc, c);
break;
case ClientNetObject.VOTE:
serverSettings.Voting.ServerRead(inc, c);
Voting.ServerRead(inc, c);
break;
default:
return;
@@ -1220,7 +1206,7 @@ namespace Barotrauma.Networking
entityEventManager.Read(inc, c);
break;
case ClientNetObject.VOTE:
serverSettings.Voting.ServerRead(inc, c);
Voting.ServerRead(inc, c);
break;
case ClientNetObject.SPECTATING_POS:
c.SpectatePos = new Vector2(inc.ReadSingle(), inc.ReadSingle());
@@ -1309,17 +1295,11 @@ namespace Barotrauma.Networking
var mpCampaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
if (command == ClientPermissions.ManageRound && mpCampaign != null)
{
if (!mpCampaign.AllowedToEndRound(sender))
{
return;
}
//do nothing, ending campaign rounds is checked in more detail below
}
else if (command == ClientPermissions.ManageCampaign && mpCampaign != null)
{
if (!mpCampaign.AllowedToManageCampaign(sender))
{
return;
}
//do nothing, campaign permissions are checked in more detail in MultiplayerCampaign.ServerRead
}
else if (!sender.HasPermission(command))
{
@@ -1381,21 +1361,26 @@ namespace Barotrauma.Networking
bool end = inc.ReadBoolean();
if (end)
{
bool save = inc.ReadBoolean();
if (gameStarted)
if (mpCampaign == null ||
mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageRound) ||
mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign))
{
Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
if (mpCampaign != null && Level.IsLoadedOutpost && save)
bool save = inc.ReadBoolean();
if (gameStarted)
{
mpCampaign.SavePlayers();
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
if (mpCampaign != null && Level.IsLoadedOutpost && save)
{
mpCampaign.SavePlayers();
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
}
else
{
save = false;
}
EndGame(wasSaved: save);
}
else
{
save = false;
}
EndGame(wasSaved: save);
}
}
else
@@ -1403,14 +1388,17 @@ namespace Barotrauma.Networking
bool continueCampaign = inc.ReadBoolean();
if (mpCampaign != null && mpCampaign.GameOver || continueCampaign)
{
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
if (mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageMap))
{
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
}
}
else if (!gameStarted && !initiatedStartGame)
{
Log("Client \"" + ClientLogName(sender) + "\" started the round.", ServerLog.MessageType.ServerMessage);
StartGame();
}
else if (mpCampaign != null)
else if (mpCampaign != null && (mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageMap)))
{
var availableTransition = mpCampaign.GetAvailableTransition(out _, out _);
//don't force location if we've teleported
@@ -1473,34 +1461,20 @@ namespace Barotrauma.Networking
if (GameMain.NetLobbyScreen.GameModes[modeIndex].Identifier == "multiplayercampaign")
{
string[] saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer, includeInCompatible: false).ToArray();
for (int i = 0; i < saveFiles.Length; i++)
{
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFiles[i]);
if (doc?.Root != null)
{
saveFiles[i] =
string.Join(";",
saveFiles[i].Replace(';', ' '),
doc.Root.GetAttributeStringUnrestricted("submarine", ""),
doc.Root.GetAttributeStringUnrestricted("savetime", ""),
doc.Root.GetAttributeStringUnrestricted("selectedcontentpackages", ""));
}
}
const int MaxSaves = 255;
var saveInfos = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer, includeInCompatible: false);
IWriteMessage msg = new WriteOnlyMessage();
msg.Write((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO);
msg.Write((UInt16)saveFiles.Count());
foreach (string saveFile in saveFiles)
msg.Write((byte)Math.Min(saveInfos.Count, MaxSaves));
for (int i = 0; i < saveInfos.Count && i < MaxSaves; i++)
{
msg.Write(saveFile);
msg.Write(saveInfos[i]);
}
serverPeer.Send(msg, sender.Connection, DeliveryMethod.Reliable);
}
break;
case ClientPermissions.ManageCampaign:
(GameMain.GameSession.GameMode as MultiPlayerCampaign)?.ServerRead(inc, sender);
mpCampaign?.ServerRead(inc, sender);
break;
case ClientPermissions.ConsoleCommands:
{
@@ -1900,8 +1874,8 @@ namespace Barotrauma.Networking
outmsg.Write(selectedShuttle.Name);
outmsg.Write(selectedShuttle.MD5Hash.ToString());
outmsg.Write(serverSettings.Voting.AllowSubVoting);
outmsg.Write(serverSettings.Voting.AllowModeVoting);
outmsg.Write(serverSettings.AllowSubVoting);
outmsg.Write(serverSettings.AllowModeVoting);
outmsg.Write(serverSettings.VoiceChatEnabled);
@@ -2036,9 +2010,9 @@ namespace Barotrauma.Networking
SubmarineInfo selectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle;
SubmarineInfo selectedSub;
if (serverSettings.Voting.AllowSubVoting)
if (serverSettings.AllowSubVoting)
{
selectedSub = serverSettings.Voting.HighestVoted<SubmarineInfo>(VoteType.Sub, connectedClients);
selectedSub = Voting.HighestVoted<SubmarineInfo>(VoteType.Sub, connectedClients);
if (selectedSub == null) { selectedSub = GameMain.NetLobbyScreen.SelectedSub; }
}
else
@@ -2051,7 +2025,7 @@ namespace Barotrauma.Networking
return false;
}
GameModePreset selectedMode = serverSettings.Voting.HighestVoted<GameModePreset>(VoteType.Mode, connectedClients);
GameModePreset selectedMode = Voting.HighestVoted<GameModePreset>(VoteType.Mode, connectedClients);
if (selectedMode == null) { selectedMode = GameMain.NetLobbyScreen.SelectedMode; }
if (selectedMode == null)
@@ -2455,11 +2429,8 @@ namespace Barotrauma.Networking
yield return CoroutineStatus.Running;
if (GameMain.Server?.ServerSettings?.Voting != null)
{
GameMain.Server.ServerSettings.Voting.ResetVotes(GameMain.Server.ConnectedClients);
}
Voting?.ResetVotes(GameMain.Server.ConnectedClients);
GameMain.GameScreen.Select();
Log("Round started.", ServerLog.MessageType.ServerMessage);
@@ -3233,23 +3204,24 @@ namespace Barotrauma.Networking
serverPeer.Send(msg, transfer.Connection, DeliveryMethod.ReliableOrdered);
}
public void UpdateVoteStatus()
public void UpdateVoteStatus(bool checkActiveVote = true)
{
if (connectedClients.Count == 0) return;
if (connectedClients.Count == 0) { return; }
if (serverSettings.Voting.VoteRunning)
if (checkActiveVote && Voting.ActiveVote != null)
{
int yes = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(Voting.ActiveVote.VoteType) == 2);
int no = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(Voting.ActiveVote.VoteType) == 1);
int max = GameMain.Server.ConnectedClients.Count(c => c.InGame);
// Required ratio cannot be met
if (SubmarineVoteNoCount / (float)SubmarineVoteMax > 1f - serverSettings.SubmarineVoteRequiredRatio)
if (no / (float)max > 1f - serverSettings.VoteRequiredRatio)
{
serverSettings.Voting.StopSubmarineVote(false);
return; // Update will be re-sent via StopSubmarineVote
Voting.ActiveVote.Finish(Voting, passed: false);
}
else if (SubmarineVoteYesCount / (float)SubmarineVoteMax >= serverSettings.SubmarineVoteRequiredRatio)
else if (yes / max >= serverSettings.VoteRequiredRatio)
{
SwitchSubmarine();
return; // Update will be re-sent via StopSubmarineVote
}
Voting.ActiveVote.Finish(Voting, passed: true);
}
}
Client.UpdateKickVotes(connectedClients);
@@ -3279,10 +3251,12 @@ namespace Barotrauma.Networking
SendVoteStatus(connectedClients);
if (serverSettings.Voting.AllowEndVoting && EndVoteMax > 0 &&
((float)EndVoteCount / (float)EndVoteMax) >= serverSettings.EndVoteRequiredRatio)
int endVoteCount = ConnectedClients.Count(c => c.HasSpawned && c.GetVote<bool>(VoteType.EndRound));
int endVoteMax = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned);
if (serverSettings.AllowEndVoting && endVoteMax > 0 &&
((float)endVoteCount / (float)endVoteMax) >= serverSettings.EndVoteRequiredRatio)
{
Log("Ending round by votes (" + EndVoteCount + "/" + (EndVoteMax - EndVoteCount) + ")", ServerLog.MessageType.ServerMessage);
Log("Ending round by votes (" + endVoteCount + "/" + (endVoteMax - endVoteCount) + ")", ServerLog.MessageType.ServerMessage);
EndGame(wasSaved: false);
}
}
@@ -3294,7 +3268,7 @@ namespace Barotrauma.Networking
IWriteMessage msg = new WriteOnlyMessage();
msg.Write((byte)ServerPacketHeader.UPDATE_LOBBY);
msg.Write((byte)ServerNetObject.VOTE);
serverSettings.Voting.ServerWrite(msg);
Voting.ServerWrite(msg);
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
foreach (var c in recipients)
@@ -3303,11 +3277,13 @@ namespace Barotrauma.Networking
}
}
private void SwitchSubmarine()
public void SwitchSubmarine()
{
SubmarineInfo targetSubmarine = Voting.SubVote.Sub;
VoteType voteType = Voting.SubVote.VoteType;
Client starter = Voting.SubVote.VoteStarter;
if (!(Voting.ActiveVote is Voting.SubmarineVote subVote)) { return; }
SubmarineInfo targetSubmarine = subVote.Sub;
VoteType voteType = Voting.ActiveVote.VoteType;
Client starter = Voting.ActiveVote.VoteStarter;
int deliveryFee = 0;
switch (voteType)
@@ -3318,7 +3294,7 @@ namespace Barotrauma.Networking
GameMain.GameSession.PurchaseSubmarine(targetSubmarine, starter);
break;
case VoteType.SwitchSub:
deliveryFee = Voting.SubVote.DeliveryFee;
deliveryFee = subVote.DeliveryFee;
break;
default:
return;
@@ -3326,10 +3302,10 @@ namespace Barotrauma.Networking
if (voteType != VoteType.PurchaseSub)
{
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(targetSubmarine, deliveryFee, starter);
GameMain.GameSession.SwitchSubmarine(targetSubmarine, deliveryFee, starter);
}
serverSettings.Voting.StopSubmarineVote(true);
Voting.StopSubmarineVote(true);
}
public void UpdateClientPermissions(Client client)
@@ -312,8 +312,8 @@ namespace Barotrauma.Networking
AutoRestart = doc.Root.GetAttributeBool("autorestart", false);
Voting.AllowSubVoting = SubSelectionMode == SelectionMode.Vote;
Voting.AllowModeVoting = ModeSelectionMode == SelectionMode.Vote;
AllowSubVoting = SubSelectionMode == SelectionMode.Vote;
AllowModeVoting = ModeSelectionMode == SelectionMode.Vote;
selectedLevelDifficulty = doc.Root.GetAttributeFloat("LevelDifficulty", 20.0f);
GameMain.NetLobbyScreen.SetLevelDifficulty(selectedLevelDifficulty);
@@ -7,59 +7,161 @@ namespace Barotrauma
{
partial class Voting
{
public bool AllowSubVoting
public interface IVote
{
get { return allowSubVoting; }
set { allowSubVoting = value; }
}
public bool AllowModeVoting
{
get { return allowModeVoting; }
set { allowModeVoting = value; }
}
public Client VoteStarter { get; }
public VoteType VoteType { get; }
public float Timer { get; set; }
public struct SubmarineVote
public VoteState State { get; set; }
public void Finish(Voting voting, bool passed);
}
public class SubmarineVote : IVote
{
public Client VoteStarter;
public Client VoteStarter { get; }
public VoteType VoteType { get; }
public float Timer { get; set; }
public VoteState State { get; set; }
public SubmarineInfo Sub;
public VoteType VoteType;
public float Timer;
public int DeliveryFee;
public VoteState State;
public SubmarineVote(Client starter, SubmarineInfo subInfo, int deliveryFee, VoteType voteType)
{
Sub = subInfo;
DeliveryFee = deliveryFee;
VoteType = voteType;
State = VoteState.Started;
VoteStarter = starter;
}
public void Finish(Voting voting, bool passed)
{
if (passed)
{
GameMain.Server?.SwitchSubmarine();
}
voting.StopSubmarineVote(passed);
}
}
public static SubmarineVote SubVote;
public static IVote ActiveVote;
public class TransferVote : IVote
{
public Client VoteStarter { get; }
public VoteType VoteType { get; }
public float Timer { get; set; }
public VoteState State { get; set; }
//null = bank
public readonly Client From, To;
public readonly int TransferAmount;
public TransferVote(Client starter, Client from, int transferAmount, Client to)
{
VoteStarter = starter;
From = from;
To = to;
TransferAmount = transferAmount;
State = VoteState.Started;
VoteType = VoteType.TransferMoney;
}
public void Finish(Voting voting, bool passed)
{
if (passed)
{
Wallet fromWallet = From == null ? (GameMain.GameSession.GameMode as MultiPlayerCampaign)?.Bank : From.Character?.Wallet;
if (fromWallet.TryDeduct(TransferAmount))
{
Wallet toWallet = To == null ? (GameMain.GameSession.GameMode as MultiPlayerCampaign)?.Bank : To.Character?.Wallet;
toWallet.Give(TransferAmount);
}
}
voting.StopMoneyTransferVote(passed);
}
}
private static readonly Queue<IVote> pendingVotes = new Queue<IVote>();
private void StartSubmarineVote(SubmarineInfo subInfo, VoteType voteType, Client sender)
{
SubVote.Sub = subInfo;
SubVote.DeliveryFee = voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0;
SubVote.VoteType = voteType;
SubVote.State = VoteState.Started;
SubVote.VoteStarter = sender;
VoteRunning = true;
var subVote = new SubmarineVote(
sender,
subInfo,
voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0,
voteType);
StartOrEnqueueVote(subVote);
sender.SetVote(voteType, 2);
GameMain.Server.UpdateVoteStatus(checkActiveVote: false);
}
public void StopSubmarineVote(bool passed)
{
VoteRunning = false;
SubVote.State = passed ? VoteState.Passed : VoteState.Failed;
if (!(ActiveVote is SubmarineVote)) { return; }
StopActiveVote(passed);
}
GameMain.Server.UpdateVoteStatus();
public void StopMoneyTransferVote(bool passed)
{
if (!(ActiveVote is TransferVote)) { return; }
StopActiveVote(passed);
}
public void StopActiveVote(bool passed)
{
ActiveVote.State = passed ? VoteState.Passed : VoteState.Failed;
GameMain.Server.UpdateVoteStatus(checkActiveVote: false);
GameMain.NetworkMember.SubmarineVoteYesCount = GameMain.NetworkMember.SubmarineVoteNoCount = GameMain.NetworkMember.SubmarineVoteMax = 0;
for (int i = 0; i < GameMain.NetworkMember.ConnectedClients.Count; i++)
{
GameMain.NetworkMember.ConnectedClients[i].SetVote(SubVote.VoteType, 0);
GameMain.NetworkMember.ConnectedClients[i].SetVote(ActiveVote.VoteType, 0);
}
SubVote.Sub = null;
SubVote.DeliveryFee = 0;
SubVote.VoteType = VoteType.Unknown;
SubVote.Timer = 0.0f;
SubVote.State = VoteState.None;
SubVote.VoteStarter = null;
ActiveVote = null;
if (pendingVotes.Any())
{
ActiveVote = pendingVotes.Dequeue();
}
}
public void StartTransferVote(Client starter, Client from, int transferAmount, Client to)
{
StartOrEnqueueVote(new TransferVote(starter, from, transferAmount, to));
starter.SetVote(VoteType.TransferMoney, 2);
GameMain.Server.UpdateVoteStatus(checkActiveVote: false);
}
private void StartOrEnqueueVote(IVote vote)
{
if (ActiveVote == null)
{
ActiveVote = vote;
}
else
{
pendingVotes.Enqueue(vote);
}
}
public void Update(float deltaTime)
{
if (ActiveVote == null) { return; }
ActiveVote.Timer += deltaTime;
if (ActiveVote.Timer >= GameMain.NetworkMember.ServerSettings.VoteTimeout)
{
// Do not take unanswered into account for total
int yes = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 2);
int no = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 1);
ActiveVote.Finish(this, passed: yes / (float)(yes + no) >= GameMain.NetworkMember.ServerSettings.VoteRequiredRatio);
}
}
public void ServerRead(IReadMessage inc, Client sender)
@@ -97,10 +199,6 @@ namespace Barotrauma
case VoteType.EndRound:
if (!sender.HasSpawned) { return; }
sender.SetVote(voteType, inc.ReadBoolean());
GameMain.NetworkMember.EndVoteCount = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote<bool>(VoteType.EndRound));
GameMain.NetworkMember.EndVoteMax = GameMain.Server.ConnectedClients.Count(c => c.HasSpawned);
break;
case VoteType.Kick:
byte kickedClientID = inc.ReadByte();
@@ -126,24 +224,34 @@ namespace Barotrauma
case VoteType.PurchaseAndSwitchSub:
case VoteType.PurchaseSub:
case VoteType.SwitchSub:
case VoteType.TransferMoney:
bool startVote = inc.ReadBoolean();
if (startVote)
{
string subName = inc.ReadString();
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign && (campaign.CanPurchaseSub(subInfo, sender) || GameMain.GameSession.IsSubmarineOwned(subInfo)))
if (voteType == VoteType.TransferMoney)
{
StartSubmarineVote(subInfo, voteType, sender);
int amount = inc.ReadInt32();
int fromClientId = inc.ReadByte();
int toClientId = inc.ReadByte();
pendingVotes.Enqueue(new TransferVote(sender,
GameMain.Server.ConnectedClients.Find(c => c.ID == fromClientId),
amount,
GameMain.Server.ConnectedClients.Find(c => c.ID == toClientId)));
}
else
{
string subName = inc.ReadString();
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign && (campaign.CanPurchaseSub(subInfo, sender) || GameMain.GameSession.IsSubmarineOwned(subInfo)))
{
StartSubmarineVote(subInfo, voteType, sender);
}
}
}
else
{
sender.SetVote(voteType, (int)inc.ReadByte());
}
GameMain.Server.SubmarineVoteYesCount = GameMain.Server.ConnectedClients.Count(c => c.GetVote<int>(SubVote.VoteType) == 2);
GameMain.Server.SubmarineVoteNoCount = GameMain.Server.ConnectedClients.Count(c => c.GetVote<int>(SubVote.VoteType) == 1);
GameMain.Server.SubmarineVoteMax = GameMain.Server.ConnectedClients.Count(c => c.InGame);
break;
}
@@ -154,10 +262,10 @@ namespace Barotrauma
public void ServerWrite(IWriteMessage msg)
{
if (GameMain.Server == null) return;
if (GameMain.Server == null) { return; }
msg.Write(allowSubVoting);
if (allowSubVoting)
msg.Write(GameMain.Server.ServerSettings.AllowSubVoting);
if (GameMain.Server.ServerSettings.AllowSubVoting)
{
IReadOnlyDictionary<SubmarineInfo, int> voteList = GetVoteCounts<SubmarineInfo>(VoteType.Sub, GameMain.Server.ConnectedClients);
msg.Write((byte)voteList.Count);
@@ -167,8 +275,8 @@ namespace Barotrauma
msg.Write(vote.Key.Name);
}
}
msg.Write(AllowModeVoting);
if (allowModeVoting)
msg.Write(GameMain.Server.ServerSettings.AllowModeVoting);
if (GameMain.Server.ServerSettings.AllowModeVoting)
{
IReadOnlyDictionary<GameModePreset, int> voteList = GetVoteCounts<GameModePreset>(VoteType.Mode, GameMain.Server.ConnectedClients);
msg.Write((byte)voteList.Count);
@@ -178,60 +286,78 @@ namespace Barotrauma
msg.Write(vote.Key.Identifier);
}
}
msg.Write(AllowEndVoting);
if (AllowEndVoting)
msg.Write(GameMain.Server.ServerSettings.AllowEndVoting);
if (GameMain.Server.ServerSettings.AllowEndVoting)
{
msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote<bool>(VoteType.EndRound)));
msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned));
}
msg.Write(AllowVoteKick);
msg.Write(GameMain.Server.ServerSettings.AllowVoteKick);
msg.Write((byte)SubVote.State);
if (SubVote.State != VoteState.None)
msg.Write((byte)(ActiveVote?.State ?? VoteState.None));
if (ActiveVote != null)
{
msg.Write((byte)SubVote.VoteType);
if (SubVote.VoteType != VoteType.Unknown)
{
var yesClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote<int>(SubVote.VoteType) == 2);
msg.Write((byte)ActiveVote.VoteType);
if (ActiveVote.State != VoteState.None && ActiveVote.VoteType != VoteType.Unknown)
{
var yesClients = GameMain.Server.ConnectedClients.FindAll(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 2);
msg.Write((byte)yesClients.Count);
foreach (Client c in yesClients)
{
msg.Write(c.ID);
}
var noClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote<int>(SubVote.VoteType) == 1);
var noClients = GameMain.Server.ConnectedClients.FindAll(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 1);
msg.Write((byte)noClients.Count);
foreach (Client c in noClients)
{
msg.Write(c.ID);
}
msg.Write((byte)GameMain.Server.SubmarineVoteMax);
msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.InGame));
switch (SubVote.State)
switch (ActiveVote.State)
{
case VoteState.Started:
msg.Write(SubVote.Sub.Name);
msg.Write(SubVote.VoteStarter.ID);
msg.Write((byte)GameMain.Server.ServerSettings.SubmarineVoteTimeout);
msg.Write(ActiveVote.VoteStarter.ID);
msg.Write((byte)GameMain.Server.ServerSettings.VoteTimeout);
switch (ActiveVote.VoteType)
{
case VoteType.PurchaseSub:
case VoteType.PurchaseAndSwitchSub:
case VoteType.SwitchSub:
msg.Write((ActiveVote as SubmarineVote).Sub.Name);
break;
case VoteType.TransferMoney:
var transferVote = (ActiveVote as TransferVote);
msg.Write(transferVote.From?.ID ?? 0);
msg.Write(transferVote.To?.ID ?? 0);
msg.Write(transferVote.TransferAmount);
break;
}
break;
case VoteState.Running:
// Nothing specific
break;
case VoteState.Passed:
case VoteState.Failed:
msg.Write(SubVote.State == VoteState.Passed);
msg.Write(SubVote.Sub.Name);
if (SubVote.State == VoteState.Passed)
msg.Write(ActiveVote.State == VoteState.Passed);
switch (ActiveVote.VoteType)
{
msg.Write((short)SubVote.DeliveryFee);
case VoteType.PurchaseSub:
case VoteType.PurchaseAndSwitchSub:
case VoteType.SwitchSub:
msg.Write((ActiveVote as SubmarineVote).Sub.Name);
msg.Write((short)(ActiveVote as SubmarineVote).DeliveryFee);
break;
}
break;
}
}
}
}
}
var readyClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote<bool>(VoteType.StartRound));
msg.Write((byte)readyClients.Count);