Build 1.1.4.0

This commit is contained in:
Markus Isberg
2023-03-31 18:40:44 +03:00
parent efba17e0ff
commit 9470edead3
483 changed files with 17487 additions and 8548 deletions
@@ -140,8 +140,7 @@ namespace Barotrauma.Networking
return Option<BannedPlayer>.Some(new BannedPlayer(name, addressOrAccountId, reason, expirationTime));
}
bannedPlayers.AddRange(doc.Root.Elements().Select(loadFromElement)
.OfType<Some<BannedPlayer>>().Select(o => o.Value));
bannedPlayers.AddRange(doc.Root.Elements().Select(loadFromElement).NotNone());
}
private void RemoveExpired()
@@ -102,9 +102,9 @@ namespace Barotrauma.Networking
similarity *= 0.25f;
}
bool isOwner = GameMain.Server.OwnerConnection != null && c.Connection == GameMain.Server.OwnerConnection;
bool isSpamExempt = RateLimiter.IsExempt(c);
if (similarity + c.ChatSpamSpeed > 5.0f && !isOwner)
if (similarity + c.ChatSpamSpeed > 5.0f && !isSpamExempt)
{
GameMain.Server.KarmaManager.OnSpamFilterTriggered(c);
@@ -125,7 +125,7 @@ namespace Barotrauma.Networking
c.ChatSpamSpeed += similarity + 0.5f;
if (c.ChatSpamTimer > 0.0f && !isOwner)
if (c.ChatSpamTimer > 0.0f && !isSpamExempt)
{
ChatMessage denyMsg = Create("", TextManager.Get("SpamFilterBlocked").Value, ChatMessageType.Server, null);
c.ChatSpamTimer = 10.0f;
@@ -303,7 +303,7 @@ namespace Barotrauma.Networking
}
else
{
var defaultPerms = PermissionPreset.List.Find(p => p.Name == "None");
var defaultPerms = PermissionPreset.List.Find(p => p.Identifier == "None");
if (defaultPerms != null)
{
newClient.SetPermissions(defaultPerms.Permissions, defaultPerms.PermittedCommands);
@@ -332,9 +332,8 @@ namespace Barotrauma.Networking
public void Update(float deltaTime)
{
#if CLIENT
if (ShowNetStats) { netStats.Update(deltaTime); }
#endif
dosProtection.Update(deltaTime);
if (!started) { return; }
if (ChildServerRelay.HasShutDown)
@@ -387,10 +386,10 @@ namespace Barotrauma.Networking
Voting.Update(deltaTime);
bool isCrewDead =
connectedClients.All(c => c.Character == null || c.Character.IsDead || c.Character.IsIncapacitated);
connectedClients.All(c => !c.UsingFreeCam && (c.Character == null || c.Character.IsDead || c.Character.IsIncapacitated));
bool subAtLevelEnd = false;
if (Submarine.MainSub != null && !(GameMain.GameSession.GameMode is PvPMode))
if (Submarine.MainSub != null && GameMain.GameSession.GameMode is not PvPMode)
{
if (Level.Loaded?.EndOutpost != null)
{
@@ -692,10 +691,14 @@ namespace Barotrauma.Networking
}
}
private readonly DoSProtection dosProtection = new();
private void ReadDataMessage(NetworkConnection sender, IReadMessage inc)
{
var connectedClient = connectedClients.Find(c => c.Connection == sender);
using var _ = dosProtection.Start(connectedClient);
ClientPacketHeader header = (ClientPacketHeader)inc.ReadByte();
switch (header)
{
@@ -784,7 +787,7 @@ namespace Barotrauma.Networking
if (GameStarted)
{
SendDirectChatMessage(TextManager.Get("CampaignStartFailedRoundRunning").Value, connectedClient, ChatMessageType.MessageBox);
return;
break;
}
if (CampaignMode.AllowedToManageCampaign(connectedClient, ClientPermissions.ManageRound))
{
@@ -1085,7 +1088,7 @@ namespace Barotrauma.Networking
ChatMessage.ServerRead(inc, c);
break;
case ClientNetSegment.Vote:
Voting.ServerRead(inc, c);
Voting.ServerRead(inc, c, dosProtection);
break;
default:
return SegmentTableReader<ClientNetSegment>.BreakSegmentReading.Yes;
@@ -1116,6 +1119,7 @@ namespace Barotrauma.Networking
{
//check if midround syncing is needed due to missed unique events
if (!midroundSyncingDone) { entityEventManager.InitClientMidRoundSync(c); }
MissionAction.NotifyMissionsUnlockedThisRound(c);
c.InGame = true;
}
}
@@ -1245,7 +1249,7 @@ namespace Barotrauma.Networking
entityEventManager.Read(inc, c);
break;
case ClientNetSegment.Vote:
Voting.ServerRead(inc, c);
Voting.ServerRead(inc, c, dosProtection);
break;
case ClientNetSegment.SpectatingPos:
c.SpectatePos = new Vector2(inc.ReadSingle(), inc.ReadSingle());
@@ -1405,19 +1409,23 @@ namespace Barotrauma.Networking
bool quitCampaign = inc.ReadBoolean();
if (GameStarted)
{
Log($"Client \"{ClientLogName(sender)}\" ended the round.", ServerLog.MessageType.ServerMessage);
if (mpCampaign != null && Level.IsLoadedFriendlyOutpost && save)
using (dosProtection.Pause(sender))
{
mpCampaign.SavePlayers();
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
mpCampaign.UpdateStoreStock();
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
Log($"Client \"{ClientLogName(sender)}\" ended the round.", ServerLog.MessageType.ServerMessage);
if (mpCampaign != null && Level.IsLoadedFriendlyOutpost && save)
{
mpCampaign.SavePlayers();
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
mpCampaign.UpdateStoreStock();
GameMain.GameSession?.EventManager?.RegisterEventHistory(registerFinishedOnly: true);
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
}
else
{
save = false;
}
EndGame(wasSaved: save);
}
else
{
save = false;
}
EndGame(wasSaved: save);
}
else if (mpCampaign != null)
{
@@ -1441,45 +1449,54 @@ namespace Barotrauma.Networking
}
else if (CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageMap))
{
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
using (dosProtection.Pause(sender))
{
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
}
}
}
else if (!GameStarted && !initiatedStartGame)
{
Log("Client \"" + ClientLogName(sender) + "\" started the round.", ServerLog.MessageType.ServerMessage);
TryStartGame();
using (dosProtection.Pause(sender))
{
Log("Client \"" + ClientLogName(sender) + "\" started the round.", ServerLog.MessageType.ServerMessage);
TryStartGame();
}
}
else if (mpCampaign != null && (CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageMap)))
{
var availableTransition = mpCampaign.GetAvailableTransition(out _, out _);
//don't force location if we've teleported
bool forceLocation = !mpCampaign.Map.AllowDebugTeleport || mpCampaign.Map.CurrentLocation == Level.Loaded.StartLocation;
switch (availableTransition)
using (dosProtection.Pause(sender))
{
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
if (forceLocation)
{
mpCampaign.Map.SelectLocation(
mpCampaign.Map.CurrentLocation.Connections.Find(c => c.LevelData == Level.Loaded?.LevelData).OtherLocation(mpCampaign.Map.CurrentLocation));
}
mpCampaign.LoadNewLevel();
break;
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
if (forceLocation)
{
mpCampaign.Map.SetLocation(mpCampaign.Map.Locations.IndexOf(Level.Loaded.EndLocation));
}
mpCampaign.LoadNewLevel();
break;
case CampaignMode.TransitionType.None:
#if DEBUG || UNSTABLE
DebugConsole.ThrowError($"Client \"{sender.Name}\" attempted to trigger a level transition. No transitions available.");
#endif
return;
default:
Log("Client \"" + ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
mpCampaign.LoadNewLevel();
break;
var availableTransition = mpCampaign.GetAvailableTransition(out _, out _);
//don't force location if we've teleported
bool forceLocation = !mpCampaign.Map.AllowDebugTeleport || mpCampaign.Map.CurrentLocation == Level.Loaded.StartLocation;
switch (availableTransition)
{
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
if (forceLocation)
{
mpCampaign.Map.SelectLocation(
mpCampaign.Map.CurrentLocation.Connections.Find(c => c.LevelData == Level.Loaded?.LevelData).OtherLocation(mpCampaign.Map.CurrentLocation));
}
mpCampaign.LoadNewLevel();
break;
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
if (forceLocation)
{
mpCampaign.Map.SetLocation(mpCampaign.Map.Locations.IndexOf(Level.Loaded.EndLocation));
}
mpCampaign.LoadNewLevel();
break;
case CampaignMode.TransitionType.None:
#if DEBUG || UNSTABLE
DebugConsole.ThrowError($"Client \"{sender.Name}\" attempted to trigger a level transition. No transitions available.");
#endif
break;
default:
Log("Client \"" + ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
mpCampaign.LoadNewLevel();
break;
}
}
}
}
@@ -1519,11 +1536,7 @@ namespace Barotrauma.Networking
mpCampaign?.ServerRead(inc, sender);
break;
case ClientPermissions.ConsoleCommands:
{
string consoleCommand = inc.ReadString();
Vector2 clientCursorPos = new Vector2(inc.ReadSingle(), inc.ReadSingle());
DebugConsole.ExecuteClientCommand(sender, clientCursorPos, consoleCommand);
}
DebugConsole.ServerRead(inc, sender);
break;
case ClientPermissions.ManagePermissions:
byte targetClientID = inc.ReadByte();
@@ -2366,10 +2379,7 @@ namespace Barotrauma.Networking
List<WayPoint> spawnWaypoints = null;
List<WayPoint> mainSubWaypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSubs[n]).ToList();
if (Level.Loaded?.StartOutpost != null &&
Level.Loaded.Type == LevelData.LevelType.Outpost &&
(Level.Loaded.StartOutpost.Info.OutpostGenerationParams?.SpawnCrewInsideOutpost ?? false) &&
Level.Loaded.StartOutpost.GetConnectedSubs().Any(s => s.Info.Type == SubmarineType.Player))
if (Level.Loaded != null && Level.Loaded.ShouldSpawnCrewInsideOutpost())
{
spawnWaypoints = WayPoint.WayPointList.FindAll(wp =>
wp.SpawnType == SpawnType.Human &&
@@ -2444,7 +2454,6 @@ namespace Barotrauma.Networking
spawnedCharacter.Info.InventoryData = new XElement("inventory");
spawnedCharacter.Info.StartItemsGiven = true;
spawnedCharacter.SaveInventory();
// talents are only avilable for players in online sessions, but modders or someone else might want to have them loaded anyway
spawnedCharacter.LoadTalents();
}
}
@@ -2979,7 +2988,7 @@ namespace Barotrauma.Networking
client.WaitForNextRoundRespawn = null;
client.InGame = false;
if (client.AccountId is Some<AccountId> { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); }
if (client.AccountId.TryUnwrap<SteamId>(out var steamId)) { SteamManager.StopAuthSession(steamId); }
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(client));
if (previousPlayer == null)
@@ -3313,12 +3322,13 @@ namespace Barotrauma.Networking
if (checkActiveVote && Voting.ActiveVote != null)
{
#warning TODO: this is mostly the same as Voting.Update, deduplicate (if/when refactoring the Voting class?)
var inGameClients = GameMain.Server.ConnectedClients.Where(c => c.InGame);
if (inGameClients.Count() == 1)
if (inGameClients.Count() == 1 && inGameClients.First() == Voting.ActiveVote.VoteStarter)
{
Voting.ActiveVote.Finish(Voting, passed: true);
}
else
else if (inGameClients.Any())
{
var eligibleClients = inGameClients.Where(c => c != Voting.ActiveVote.VoteStarter);
int yes = eligibleClients.Count(c => c.GetVote<int>(Voting.ActiveVote.VoteType) == 2);
@@ -3388,12 +3398,11 @@ namespace Barotrauma.Networking
public void SwitchSubmarine()
{
if (!(Voting.ActiveVote is Voting.SubmarineVote subVote)) { return; }
if (Voting.ActiveVote is not Voting.SubmarineVote subVote) { return; }
SubmarineInfo targetSubmarine = subVote.Sub;
VoteType voteType = Voting.ActiveVote.VoteType;
Client starter = Voting.ActiveVote.VoteStarter;
int deliveryFee = 0;
switch (voteType)
{
@@ -3403,7 +3412,6 @@ namespace Barotrauma.Networking
GameMain.GameSession.PurchaseSubmarine(targetSubmarine, starter);
break;
case VoteType.SwitchSub:
deliveryFee = subVote.DeliveryFee;
break;
default:
return;
@@ -3411,7 +3419,7 @@ namespace Barotrauma.Networking
if (voteType != VoteType.PurchaseSub)
{
GameMain.GameSession.SwitchSubmarine(targetSubmarine, subVote.TransferItems, deliveryFee, starter);
GameMain.GameSession.SwitchSubmarine(targetSubmarine, subVote.TransferItems, starter);
}
Voting.StopSubmarineVote(true);
@@ -3592,15 +3600,28 @@ namespace Barotrauma.Networking
}
}
private readonly RateLimiter charInfoRateLimiter = new(
maxRequests: 5,
expiryInSeconds: 10,
punishmentRules: new[]
{
(RateLimitAction.OnLimitReached, RateLimitPunishment.Announce),
(RateLimitAction.OnLimitDoubled, RateLimitPunishment.Kick)
});
private void UpdateCharacterInfo(IReadMessage message, Client sender)
{
sender.SpectateOnly = message.ReadBoolean() && (ServerSettings.AllowSpectating || sender.Connection == OwnerConnection);
if (sender.SpectateOnly)
{
return;
}
bool spectateOnly = message.ReadBoolean();
message.ReadPadBits();
string newName = message.ReadString();
sender.SpectateOnly = spectateOnly && (ServerSettings.AllowSpectating || sender.Connection == OwnerConnection);
if (sender.SpectateOnly) { return; }
var netInfo = INetSerializableStruct.Read<NetCharacterInfo>(message);
if (charInfoRateLimiter.IsLimitReached(sender)) { return; }
string newName = netInfo.NewName;
if (string.IsNullOrEmpty(newName))
{
newName = sender.Name;
@@ -3618,42 +3639,31 @@ namespace Barotrauma.Networking
}
}
int tagCount = message.ReadByte();
HashSet<Identifier> tagSet = new HashSet<Identifier>();
for (int i = 0; i < tagCount; i++)
{
tagSet.Add(message.ReadIdentifier());
}
int hairIndex = message.ReadByte();
int beardIndex = message.ReadByte();
int moustacheIndex = message.ReadByte();
int faceAttachmentIndex = message.ReadByte();
Color skinColor = message.ReadColorR8G8B8();
Color hairColor = message.ReadColorR8G8B8();
Color facialHairColor = message.ReadColorR8G8B8();
List<JobVariant> jobPreferences = new List<JobVariant>();
int count = message.ReadByte();
for (int i = 0; i < Math.Min(count, 3); i++)
{
string jobIdentifier = message.ReadString();
int variant = message.ReadByte();
if (JobPrefab.Prefabs.TryGet(jobIdentifier, out JobPrefab jobPrefab))
{
if (jobPrefab.HiddenJob) { continue; }
jobPreferences.Add(new JobVariant(jobPrefab, variant));
}
}
sender.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, newName);
sender.CharacterInfo.RecreateHead(tagSet.ToImmutableHashSet(), hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
sender.CharacterInfo.Head.SkinColor = skinColor;
sender.CharacterInfo.Head.HairColor = hairColor;
sender.CharacterInfo.Head.FacialHairColor = facialHairColor;
if (jobPreferences.Count > 0)
sender.CharacterInfo.RecreateHead(
tags: netInfo.Tags.ToImmutableHashSet(),
hairIndex: netInfo.HairIndex,
beardIndex: netInfo.BeardIndex,
moustacheIndex: netInfo.MoustacheIndex,
faceAttachmentIndex: netInfo.FaceAttachmentIndex);
sender.CharacterInfo.Head.SkinColor = netInfo.SkinColor;
sender.CharacterInfo.Head.HairColor = netInfo.HairColor;
sender.CharacterInfo.Head.FacialHairColor = netInfo.FacialHairColor;
if (netInfo.JobVariants.Length > 0)
{
sender.JobPreferences = jobPreferences;
List<JobVariant> variants = new List<JobVariant>();
foreach (NetJobVariant jv in netInfo.JobVariants)
{
if (jv.ToJobVariant() is { } variant)
{
variants.Add(variant);
}
}
sender.JobPreferences = variants;
}
}
@@ -3973,8 +3983,7 @@ namespace Barotrauma.Networking
}
public void Quit()
{
{
if (started)
{
started = false;
@@ -3986,7 +3995,7 @@ namespace Barotrauma.Networking
ServerSettings.SaveSettings();
ModSender.Dispose();
ModSender?.Dispose();
if (ServerSettings.SaveServerLogs)
{
@@ -158,7 +158,7 @@ namespace Barotrauma
else if (client.Karma < 40.0f)
herpesStrength = 30.0f;
var existingAffliction = client.Character.CharacterHealth.GetAffliction<AfflictionSpaceHerpes>("spaceherpes");
var existingAffliction = client.Character.CharacterHealth.GetAffliction<AfflictionSpaceHerpes>(AfflictionPrefab.SpaceHerpesType);
if (existingAffliction == null && herpesStrength > 0.0f)
{
client.Character.CharacterHealth.ApplyAffliction(null, new Affliction(herpesAffliction, herpesStrength));
@@ -170,7 +170,7 @@ namespace Barotrauma
existingAffliction.Strength = herpesStrength;
if (herpesStrength <= 0.0f)
{
client.Character.CharacterHealth.ReduceAfflictionOnAllLimbs("invertcontrols".ToIdentifier(), 100.0f);
client.Character.CharacterHealth.ReduceAfflictionOnAllLimbs(AfflictionPrefab.InvertControlsType, 100.0f);
}
}
@@ -358,8 +358,8 @@ namespace Barotrauma
}
}
bool targetIsHusk = target.CharacterHealth?.GetAffliction<AfflictionHusk>("huskinfection")?.State == AfflictionHusk.InfectionState.Active;
bool attackerIsHusk = attacker.CharacterHealth?.GetAffliction<AfflictionHusk>("huskinfection")?.State == AfflictionHusk.InfectionState.Active;
bool targetIsHusk = target.CharacterHealth?.GetAffliction<AfflictionHusk>(AfflictionPrefab.HuskInfectionType)?.State == AfflictionHusk.InfectionState.Active;
bool attackerIsHusk = attacker.CharacterHealth?.GetAffliction<AfflictionHusk>(AfflictionPrefab.HuskInfectionType)?.State == AfflictionHusk.InfectionState.Active;
//huskified characters count as enemies to healthy characters and vice versa
if (targetIsHusk != attackerIsHusk) { isEnemy = true; }
@@ -614,7 +614,7 @@ namespace Barotrauma
if (amount < 0.0f)
{
float? herpesStrength = client.Character?.CharacterHealth.GetAfflictionStrength("spaceherpes");
float? herpesStrength = client.Character?.CharacterHealth.GetAfflictionStrength(AfflictionPrefab.SpaceHerpesType);
var clientMemory = GetClientMemory(client);
clientMemory.KarmaDecreasesInPastMinute.RemoveAll(ta => ta.Time + 60.0f < Timing.TotalTime);
float aggregate = clientMemory.KarmaDecreasesInPastMinute.Select(ta => ta.Amount).DefaultIfEmpty().Aggregate((a, b) => a + b);
@@ -298,7 +298,7 @@ namespace Barotrauma.Networking
{
if (netServer == null) { return; }
PendingClient? pendingClient = pendingClients.Find(c => c.AccountInfo.AccountId is Some<AccountId> { Value: SteamId id } && id.Value == steamId);
PendingClient? pendingClient = pendingClients.Find(c => c.AccountInfo.AccountId.TryUnwrap<SteamId>(out var id) && id.Value == steamId);
DebugConsole.Log($"{steamId} validation: {status}, {(pendingClient != null)}");
if (pendingClient is null)
@@ -306,7 +306,7 @@ namespace Barotrauma.Networking
if (status == Steamworks.AuthResponse.OK) { return; }
if (connectedClients.Find(c
=> c.AccountInfo.AccountId is Some<AccountId> { Value: SteamId id } && id.Value == steamId)
=> c.AccountInfo.AccountId.TryUnwrap<SteamId>(out var id) && id.Value == steamId)
is LidgrenConnection connection)
{
Disconnect(connection, PeerDisconnectPacket.SteamAuthError(status));
@@ -380,7 +380,7 @@ namespace Barotrauma.Networking
lidgrenConn.Status = NetworkConnectionStatus.Disconnected;
connectedClients.Remove(lidgrenConn);
callbacks.OnDisconnect.Invoke(conn, peerDisconnectPacket);
if (conn.AccountInfo.AccountId is Some<AccountId> { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); }
if (conn.AccountInfo.AccountId.TryUnwrap<SteamId>(out var steamId)) { SteamManager.StopAuthSession(steamId); }
}
lidgrenConn.NetConnection.Disconnect(peerDisconnectPacket.ToLidgrenStringRepresentation());
@@ -71,7 +71,7 @@ namespace Barotrauma.Networking
protected List<NetworkConnection> connectedClients = null!;
protected List<PendingClient> pendingClients = null!;
protected ServerSettings serverSettings = null!;
protected Option<int> ownerKey = null!;
protected Option<int> ownerKey = Option.None;
protected NetworkConnection? OwnerConnection;
protected void ReadConnectionInitializationStep(PendingClient pendingClient, IReadMessage inc, ConnectionInitialization initializationStep)
@@ -290,7 +290,7 @@ namespace Barotrauma.Networking
pendingClients.Remove(pendingClient);
if (pendingClient.AuthSessionStarted && pendingClient.AccountInfo.AccountId is Some<AccountId> { Value: SteamId steamId })
if (pendingClient.AuthSessionStarted && pendingClient.AccountInfo.AccountId.TryUnwrap<SteamId>(out var steamId))
{
Steam.SteamManager.StopAuthSession(steamId);
pendingClient.Connection.SetAccountInfo(AccountInfo.None);
@@ -218,7 +218,10 @@ namespace Barotrauma.Networking
foreach (Door door in shuttleDoors)
{
if (door.IsOpen) door.TrySetState(false, false, true);
if (door.IsOpen)
{
door.TrySetState(open: false, isNetworkMessage: false, sendNetworkMessage: true);
}
}
var shuttleGaps = Gap.GapList.FindAll(g => g.Submarine == RespawnShuttle && g.ConnectedWall != null);
@@ -51,7 +51,7 @@ namespace Barotrauma.Networking
=> LastUpdateIdForFlag.Keys
.Where(k => IsFlagRequired(c, k))
.Aggregate(NetFlags.None, (f1, f2) => f1 | f2);
partial void InitProjSpecific()
{
LoadSettings();
@@ -176,7 +176,11 @@ namespace Barotrauma.Networking
netProperties[key].Read(incMsg);
if (!netProperties[key].PropEquals(prevValue, netProperties[key]))
{
GameServer.Log(GameServer.ClientLogName(c) + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
GameServer.Log(
NetworkMember.ClientLogName(c)
+ $" changed {netProperties[key].Name}"
+ $" to {netProperties[key].Value}",
ServerLog.MessageType.ServerMessage);
}
propertiesChanged = true;
}
@@ -330,6 +334,10 @@ namespace Barotrauma.Networking
{
LosMode = GameSettings.CurrentConfig.Graphics.LosMode;
}
if (string.IsNullOrEmpty(doc.Root.GetAttributeString("language", "")))
{
Language = ServerLanguageOptions.PickLanguage(GameSettings.CurrentConfig.Language);
}
AutoRestart = doc.Root.GetAttributeBool("autorestart", false);
@@ -512,7 +520,7 @@ namespace Barotrauma.Networking
else
{
string presetName = clientElement.GetAttributeString("preset", "");
PermissionPreset preset = PermissionPreset.List.Find(p => p.Name == presetName);
PermissionPreset preset = PermissionPreset.List.Find(p => p.DisplayName == presetName);
if (preset == null)
{
DebugConsole.ThrowError("Failed to restore saved permissions to the client \"" + clientName + "\". Permission preset \"" + presetName + "\" not found.");
@@ -577,8 +585,7 @@ namespace Barotrauma.Networking
foreach (SavedClientPermission clientPermission in ClientPermissions)
{
var matchingPreset = PermissionPreset.List.Find(p => p.MatchesPermissions(clientPermission.Permissions, clientPermission.PermittedCommands));
#warning TODO: this is broken because of localization
if (matchingPreset != null && matchingPreset.Name == "None")
if (matchingPreset != null && matchingPreset.Identifier == "None")
{
continue;
}
@@ -592,7 +599,7 @@ namespace Barotrauma.Networking
clientElement.Add(matchingPreset == null
? new XAttribute("permissions", clientPermission.Permissions.ToString())
: new XAttribute("preset", matchingPreset.Name));
: new XAttribute("preset", matchingPreset.DisplayName));
if (clientPermission.Permissions.HasFlag(Networking.ClientPermissions.ConsoleCommands))
{
@@ -28,13 +28,11 @@ namespace Barotrauma
public SubmarineInfo Sub;
public bool TransferItems;
public int DeliveryFee;
public SubmarineVote(Client starter, SubmarineInfo subInfo, bool transferItems, int deliveryFee, VoteType voteType)
public SubmarineVote(Client starter, SubmarineInfo subInfo, bool transferItems, VoteType voteType)
{
Sub = subInfo;
TransferItems = transferItems;
DeliveryFee = deliveryFee;
VoteType = voteType;
State = VoteState.Started;
VoteStarter = starter;
@@ -81,10 +79,10 @@ namespace Barotrauma
if (passed)
{
Wallet fromWallet = From == null ? (GameMain.GameSession.GameMode as MultiPlayerCampaign)?.Bank : From.Character?.Wallet;
if (fromWallet.TryDeduct(TransferAmount))
if (fromWallet != null && fromWallet.TryDeduct(TransferAmount))
{
Wallet toWallet = To == null ? (GameMain.GameSession.GameMode as MultiPlayerCampaign)?.Bank : To.Character?.Wallet;
toWallet.Give(TransferAmount);
toWallet?.Give(TransferAmount);
}
}
else
@@ -109,7 +107,6 @@ namespace Barotrauma
sender,
subInfo,
transferItems,
voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0,
voteType);
StartOrEnqueueVote(subVote);
GameMain.Server.UpdateVoteStatus(checkActiveVote: false);
@@ -206,12 +203,16 @@ namespace Barotrauma
// Do not take unanswered into account for total
int yes = eligibleClients.Count(c => c.GetVote<int>(ActiveVote.VoteType) == 2);
int no = eligibleClients.Count(c => c.GetVote<int>(ActiveVote.VoteType) == 1);
int total = Math.Max(yes + no, 1);
bool passed =
yes / (float)total >= GameMain.NetworkMember.ServerSettings.VoteRequiredRatio ||
inGameClients.Count() == 1;
int total = yes + no;
bool passed = false;
//total can be zero if the client who initiated the vote has left
if (total > 0)
{
passed =
yes / (float)total >= GameMain.NetworkMember.ServerSettings.VoteRequiredRatio ||
inGameClients.Count() == 1;
}
ActiveVote.Finish(this, passed);
}
}
@@ -224,7 +225,7 @@ namespace Barotrauma
}
}
public void ServerRead(IReadMessage inc, Client sender)
public void ServerRead(IReadMessage inc, Client sender, DoSProtection dosProtection)
{
if (GameMain.Server == null || sender == null) { return; }
@@ -336,7 +337,10 @@ namespace Barotrauma
inc.ReadPadBits();
GameMain.Server.UpdateVoteStatus();
using (dosProtection.Pause(sender))
{
GameMain.Server.UpdateVoteStatus();
}
}
public void ServerWrite(IWriteMessage msg)
@@ -436,7 +440,6 @@ namespace Barotrauma
var subVote = ActiveVote as SubmarineVote;
msg.WriteString(subVote.Sub.Name);
msg.WriteBoolean(subVote.TransferItems);
msg.WriteInt16((short)subVote.DeliveryFee);
break;
}
break;