v1.4.4.1 (Blood in the Water Update)

This commit is contained in:
Regalis11
2024-04-24 18:09:05 +03:00
parent 89b91d1c3e
commit ff1b8951a7
397 changed files with 15250 additions and 6479 deletions
@@ -349,7 +349,7 @@ namespace Barotrauma.Networking
{
UInt32 id = incMsg.ReadUInt32();
BannedPlayer? bannedPlayer = bannedPlayers.Find(p => p.UniqueIdentifier == id);
if (bannedPlayer != null)
if (bannedPlayer != null && c.HasPermission(ClientPermissions.Unban))
{
GameServer.Log(GameServer.ClientLogName(c) + " unbanned " + bannedPlayer.Name + " (" + bannedPlayer.AddressOrAccountId + ")", ServerLog.MessageType.ConsoleUsage);
RemoveBan(bannedPlayer);
@@ -282,15 +282,19 @@ namespace Barotrauma.Networking
SendConsoleMessage("Granted all permissions to " + newClient.Name + ".", newClient);
}
SendChatMessage($"ServerMessage.JoinedServer~[client]={ClientLogName(newClient)}", ChatMessageType.Server, null, changeType: PlayerConnectionChangeType.Joined);
SendChatMessage($"ServerMessage.JoinedServer~[client]={ClientLogName(newClient)}", ChatMessageType.Server, changeType: PlayerConnectionChangeType.Joined);
ServerSettings.ServerDetailsChanged = true;
if (previousPlayer != null && previousPlayer.Name != newClient.Name)
{
string prevNameSanitized = previousPlayer.Name.Replace("‖", "");
SendChatMessage($"ServerMessage.PreviousClientName~[client]={ClientLogName(newClient)}~[previousname]={prevNameSanitized}", ChatMessageType.Server, null);
SendChatMessage($"ServerMessage.PreviousClientName~[client]={ClientLogName(newClient)}~[previousname]={prevNameSanitized}", ChatMessageType.Server);
previousPlayer.Name = newClient.Name;
}
if (!ServerSettings.ServerMessageText.IsNullOrEmpty())
{
SendDirectChatMessage((TextManager.Get("servermotd") + '\n' + ServerSettings.ServerMessageText).Value, newClient, ChatMessageType.Server);
}
var savedPermissions = ServerSettings.ClientPermissions.Find(scp =>
scp.AddressOrAccountId.TryGet(out AccountId accountId)
@@ -434,12 +438,12 @@ namespace Barotrauma.Networking
endRoundDelay = 5.0f;
endRoundTimer += deltaTime;
}
else if (subAtLevelEnd && !(GameMain.GameSession?.GameMode is CampaignMode))
else if (subAtLevelEnd && GameMain.GameSession?.GameMode is not CampaignMode)
{
endRoundDelay = 5.0f;
endRoundTimer += deltaTime;
}
else if (isCrewDead && RespawnManager == null)
else if (isCrewDead && (RespawnManager == null || !RespawnManager.CanRespawnAgain))
{
#if !DEBUG
if (endRoundTimer <= 0.0f)
@@ -1136,6 +1140,10 @@ namespace Barotrauma.Networking
//check if midround syncing is needed due to missed unique events
if (!midroundSyncingDone) { entityEventManager.InitClientMidRoundSync(c); }
MissionAction.NotifyMissionsUnlockedThisRound(c);
if (GameMain.GameSession.Campaign is MultiPlayerCampaign mpCampaign)
{
mpCampaign.SendCrewState();
}
c.InGame = true;
}
}
@@ -2322,7 +2330,7 @@ namespace Barotrauma.Networking
if (campaign != null)
{
campaign.CargoManager.CreatePurchasedItems();
campaign.SendCrewState(null, default, null);
campaign.SendCrewState();
}
Level.Loaded?.SpawnNPCs();
@@ -2792,8 +2800,6 @@ namespace Barotrauma.Networking
logMsg = message.TextWithSender;
}
Log(logMsg, ServerLog.MessageType.Chat);
base.AddChatMessage(message);
}
private bool ReadClientNameChange(Client c, IReadMessage inc)
@@ -78,6 +78,11 @@ namespace Barotrauma.Networking
public bool IsProcessed;
/// <summary>
/// Does the client need to be controlling a character for the server to consider the event valid?
/// </summary>
public bool RequireCharacter = true;
public BufferedEvent(Client sender, Character senderCharacter, UInt16 characterStateID, IClientSerializable targetEntity, ReadWriteMessage data)
{
this.Sender = sender;
@@ -157,15 +162,19 @@ namespace Barotrauma.Networking
{
if (bufferedEvent.Character == null || bufferedEvent.Character.IsDead)
{
bufferedEvent.IsProcessed = true;
continue;
if (bufferedEvent.RequireCharacter)
{
bufferedEvent.IsProcessed = true;
continue;
}
}
//delay reading the events until the inputs for the corresponding frame have been processed
//UNLESS the character is unconscious, in which case we'll read the messages immediately (because further inputs will be ignored)
//atm the "give in" command is the only thing unconscious characters can do, other types of events are ignored
if (!bufferedEvent.Character.IsIncapacitated &&
if (bufferedEvent.Character != null &&
!bufferedEvent.Character.IsIncapacitated &&
NetIdUtils.IdMoreRecent(bufferedEvent.CharacterStateID, bufferedEvent.Character.LastProcessedID))
{
DebugConsole.Log($"Delaying reading entity event sent by a client until the character state has been processed. Event's character state: {bufferedEvent.CharacterStateID}, last processed character state: {bufferedEvent.Character.LastProcessedID}");
@@ -503,7 +512,12 @@ namespace Barotrauma.Networking
byte[] temp = msg.ReadBytes(msgLength - 2);
buffer.WriteBytes(temp, 0, msgLength - 2);
buffer.BitPosition = 0;
BufferEvent(new BufferedEvent(sender, sender.Character, characterStateID, entity, buffer));
BufferEvent(
new BufferedEvent(sender, sender.Character, characterStateID, entity, buffer)
{
//hull updates can be sent without a character to allow editing water and fire in spectator mode
RequireCharacter = entity is not Hull
});
sender.LastSentEntityEventID++;
}
@@ -272,7 +272,8 @@ namespace Barotrauma.Networking
ServerName = GameMain.Server.ServerName,
ContentPackages = contentPackages
.Select(contentPackage => new ServerContentPackage(contentPackage, timeNow))
.ToImmutableArray()
.ToImmutableArray(),
AllowModDownloads = serverSettings.AllowModDownloads
};
break;
@@ -323,8 +323,8 @@ namespace Barotrauma.Networking
var clients = GetClientsToRespawn().ToList();
foreach (Client c in clients)
{
//get rid of the existing character
c.Character?.DespawnNow();
// Get rid of the existing character
if (c.Character is Character character) { character.DespawnNow(); }
c.WaitForNextRoundRespawn = null;
@@ -369,12 +369,9 @@ namespace Barotrauma.Networking
{
divingSuitPrefab = ItemPrefab.Prefabs.FirstOrDefault(it => it.Tags.Any(t => t == "respawnsuitdeep"));
}
if (divingSuitPrefab == null)
{
divingSuitPrefab =
divingSuitPrefab ??=
ItemPrefab.Prefabs.FirstOrDefault(it => it.Tags.Any(t => t == "respawnsuit")) ??
ItemPrefab.Find(null, "divingsuit".ToIdentifier());
}
ItemPrefab oxyPrefab = ItemPrefab.Find(null, "oxygentank".ToIdentifier());
ItemPrefab scooterPrefab = ItemPrefab.Find(null, "underwaterscooter".ToIdentifier());
ItemPrefab batteryPrefab = ItemPrefab.Find(null, "batterycell".ToIdentifier());
@@ -387,6 +384,7 @@ namespace Barotrauma.Networking
characterInfos[i].ClearCurrentOrders();
CharacterCampaignData characterCampaignData = null;
bool forceSpawnInMainSub = false;
if (!bot)
{
@@ -398,16 +396,16 @@ namespace Barotrauma.Networking
clients[i].PendingName = null;
}
var matchingData = campaign?.GetClientCharacterData(clients[i]);
if (matchingData != null)
characterCampaignData = campaign?.GetClientCharacterData(clients[i]);
if (characterCampaignData != null)
{
if (!matchingData.HasSpawned)
if (!characterCampaignData.HasSpawned)
{
forceSpawnInMainSub = true;
}
else
{
ReduceCharacterSkills(characterInfos[i]);
ReduceCharacterSkillsOnDeath(characterInfos[i]);
characterInfos[i].RemoveSavedStatValuesOnDeath();
characterInfos[i].CauseOfDeath = null;
}
@@ -415,6 +413,7 @@ namespace Barotrauma.Networking
}
var character = Character.Create(characterInfos[i], (forceSpawnInMainSub ? mainSubSpawnPoints[i] : shuttleSpawnPoints[i]).WorldPosition, characterInfos[i].Name, isRemotePlayer: !bot, hasAi: bot);
characterCampaignData?.ApplyWalletData(character);
character.TeamID = CharacterTeamType.Team1;
character.LoadTalents();
@@ -505,11 +504,10 @@ namespace Barotrauma.Networking
}
var characterData = campaign?.GetClientCharacterData(clients[i]);
// NOTE: This was where Reaper's tax got applied
if (characterData != null && Level.Loaded?.Type != LevelData.LevelType.Outpost && characterData.HasSpawned)
{
//we need to reapply the previous respawn penalty affliction or successive deaths won't make it stack
characterData.ApplyHealthData(character, (AfflictionPrefab ap) => ap == GetRespawnPenaltyAfflictionPrefab());
GiveRespawnPenaltyAffliction(character);
ReduceCharacterSkillsOnDeath(characterInfos[i], applyExtraSkillLoss: true);
}
if (characterData == null || characterData.HasSpawned)
{
@@ -541,14 +539,37 @@ namespace Barotrauma.Networking
}
}
public static void ReduceCharacterSkills(CharacterInfo characterInfo)
/// <summary>
/// Reduce any skill gains the character may have made over the job's default
/// skill levels by percentages defined in server settings. There are two
/// reductions, a base one that always applies, and an extra loss that only
/// applies when the player chooses to respawn ASAP rather than wait.
/// </summary>
public static void ReduceCharacterSkillsOnDeath(CharacterInfo characterInfo, bool applyExtraSkillLoss = false)
{
if (characterInfo?.Job == null) { return; }
float resistanceMultiplier;
float skillLossPercentage;
if (applyExtraSkillLoss)
{
DebugConsole.Log($"Calculating extra skill loss on respawn for {characterInfo.Name}:");
resistanceMultiplier = characterInfo.LastResistanceMultiplierSkillLossRespawn;
skillLossPercentage = SkillLossPercentageOnImmediateRespawn;
}
else
{
DebugConsole.Log($"Calculating base skill loss on death for {characterInfo.Name}:");
resistanceMultiplier = characterInfo.LastResistanceMultiplierSkillLossDeath;
skillLossPercentage = SkillLossPercentageOnDeath;
}
skillLossPercentage *= resistanceMultiplier;
foreach (Skill skill in characterInfo.Job.GetSkills())
{
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier);
if (skillPrefab == null || skill.Level < skillPrefab.LevelRange.End) { continue; }
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, SkillLossPercentageOnDeath / 100.0f);
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, skillLossPercentage / 100.0f);
}
}
@@ -95,15 +95,6 @@ namespace Barotrauma.Networking
{
NetFlags requiredFlags = GetRequiredFlags(c);
outMsg.WriteByte((byte)requiredFlags);
if (requiredFlags.HasFlag(NetFlags.Name))
{
outMsg.WriteString(ServerName);
}
if (requiredFlags.HasFlag(NetFlags.Message))
{
outMsg.WriteString(ServerMessageText);
}
outMsg.WriteByte((byte)PlayStyle);
outMsg.WriteByte((byte)MaxPlayers);
outMsg.WriteBoolean(HasPassword);
@@ -122,8 +113,7 @@ namespace Barotrauma.Networking
WriteHiddenSubs(outMsg);
}
if (c.HasPermission(Networking.ClientPermissions.ManageSettings)
&& NetIdUtils.IdMoreRecent(
if (NetIdUtils.IdMoreRecent(
newID: LastUpdateIdForFlag[NetFlags.Properties],
oldID: c.LastRecvServerSettingsUpdate))
{
@@ -147,20 +137,6 @@ namespace Barotrauma.Networking
bool changed = false;
if (flags.HasFlag(NetFlags.Name))
{
string serverName = incMsg.ReadString();
if (ServerName != serverName) { changed = true; }
ServerName = serverName;
}
if (flags.HasFlag(NetFlags.Message))
{
string serverMessageText = incMsg.ReadString();
if (ServerMessageText != serverMessageText) { changed = true; }
ServerMessageText = serverMessageText;
}
if (flags.HasFlag(NetFlags.Properties))
{
bool propertiesChanged = ReadExtraCargo(incMsg);
@@ -217,42 +193,9 @@ namespace Barotrauma.Networking
int andBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
GameMain.NetLobbyScreen.MissionType = (MissionType)(((int)GameMain.NetLobbyScreen.MissionType | orBits) & andBits);
bool changedTraitorProbability = incMsg.ReadBoolean();
float traitorProbability = incMsg.ReadSingle();
if (changedTraitorProbability)
{
TraitorProbability = traitorProbability;
}
//the byte indicates the direction we're changing the value, subtract one to get negative values from a byte
TraitorDangerLevel = TraitorDangerLevel + incMsg.ReadByte() - 1;
int botCount = BotCount + incMsg.ReadByte() - 1;
if (botCount < 0) { botCount = MaxBotCount; }
if (botCount > MaxBotCount) { botCount = 0; }
BotCount = botCount;
int botSpawnMode = (int)BotSpawnMode + incMsg.ReadByte() - 1;
if (botSpawnMode < 0) { botSpawnMode = 1; }
if (botSpawnMode > 1) { botSpawnMode = 0; }
BotSpawnMode = (BotSpawnMode)botSpawnMode;
float levelDifficulty = incMsg.ReadSingle();
if (levelDifficulty >= 0.0f) { SelectedLevelDifficulty = levelDifficulty; }
bool changedUseRespawnShuttle = incMsg.ReadBoolean();
bool useRespawnShuttle = incMsg.ReadBoolean();
if (changedUseRespawnShuttle)
{
UseRespawnShuttle = useRespawnShuttle;
}
bool changedAutoRestart = incMsg.ReadBoolean();
bool autoRestart = incMsg.ReadBoolean();
if (changedAutoRestart)
{
AutoRestart = autoRestart;
}
changed |= true;
UpdateFlag(NetFlags.Misc);
}
@@ -292,8 +235,6 @@ namespace Barotrauma.Networking
doc.Root.SetAttributeValue("enableupnp", EnableUPnP);
doc.Root.SetAttributeValue("autorestart", autoRestart);
doc.Root.SetAttributeValue("LevelDifficulty", ((int)selectedLevelDifficulty).ToString());
doc.Root.SetAttributeValue("ServerMessage", ServerMessageText);
doc.Root.SetAttributeValue("HiddenSubs", string.Join(",", HiddenSubs));
@@ -304,6 +245,8 @@ namespace Barotrauma.Networking
SerializableProperty.SerializeProperties(this, doc.Root, true);
doc.Root.Add(CampaignSettings.Save());
doc.Root.SetAttributeValue("DisabledMonsters", string.Join(",", MonsterEnabled.Where(kvp => !kvp.Value).Select(kvp => kvp.Key.Value)));
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
Indent = true,
@@ -351,9 +294,6 @@ namespace Barotrauma.Networking
AllowSubVoting = SubSelectionMode == SelectionMode.Vote;
AllowModeVoting = ModeSelectionMode == SelectionMode.Vote;
selectedLevelDifficulty = doc.Root.GetAttributeFloat("LevelDifficulty", 20.0f);
GameMain.NetLobbyScreen.SetLevelDifficulty(selectedLevelDifficulty);
GameMain.NetLobbyScreen.SetTraitorProbability(traitorProbability);
HiddenSubs.UnionWith(doc.Root.GetAttributeStringArray("HiddenSubs", Array.Empty<string>()));
@@ -448,6 +388,14 @@ namespace Barotrauma.Networking
GameMain.NetLobbyScreen.SetBotCount(BotCount);
MonsterEnabled ??= CharacterPrefab.Prefabs.Select(p => (p.Identifier, true)).ToDictionary();
var disabledMonsters = doc.Root.GetAttributeIdentifierArray("DisabledMonsters", Array.Empty<Identifier>());
foreach (var disabledMonster in disabledMonsters)
{
if (MonsterEnabled.ContainsKey(disabledMonster))
{
MonsterEnabled[disabledMonster] = false;
}
}
foreach (XElement element in doc.Root.Elements())
{
@@ -112,13 +112,13 @@ namespace Barotrauma.Networking
if (recipientSpectating)
{
if (recipient.SpectatePos == null) { return true; }
distanceFactor = MathHelper.Clamp(Vector2.Distance(sender.Character.WorldPosition, recipient.SpectatePos.Value) / ChatMessage.SpeakRange, 0.0f, 1.0f);
distanceFactor = MathHelper.Clamp(Vector2.Distance(sender.Character.WorldPosition, recipient.SpectatePos.Value) / ChatMessage.SpeakRangeVOIP, 0.0f, 1.0f);
return distanceFactor < 1.0f;
}
else
{
//otherwise do a distance check
float garbleAmount = ChatMessage.GetGarbleAmount(recipient.Character, sender.Character, ChatMessage.SpeakRange);
float garbleAmount = ChatMessage.GetGarbleAmount(recipient.Character, sender.Character, ChatMessage.SpeakRangeVOIP);
distanceFactor = garbleAmount;
return garbleAmount < 1.0f;
}