Build 1.1.4.0
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user