Merge remote-tracking branch 'upstream/master' into develop

This commit is contained in:
Evil Factory
2026-04-09 09:12:16 -03:00
198 changed files with 5587 additions and 3462 deletions
@@ -79,6 +79,15 @@ namespace Barotrauma
convAction.SelectedOption = selectedOption;
if (convAction.Options.Any() && !convAction.GetEndingOptions().Contains(selectedOption))
{
var option = convAction.Options[selectedOption];
if (option.ForceSay && sender.Character != null)
{
sender.Character.ForceSay(
option.ForceSayText.IsNullOrEmpty() ? TextManager.Get(option.Text).Fallback(option.Text) : TextManager.Get(option.ForceSayText).Fallback(option.ForceSayText),
option.ForceSayInRadio,
option.ForceSayRemoveQuotes);
}
foreach (Client c in convAction.TargetClients)
{
if (c == sender) { continue; }
@@ -133,7 +133,7 @@ namespace Barotrauma
switch (winCondition)
{
case WinCondition.LastManStanding:
if (crews[0].Count == 0 || crews[1].Count == 0)
if (crews[0].Count == 0 && crews[1].Count == 0)
{
//if there are no characters in either crew, end the round
teamDead[0] = teamDead[1] = true;
@@ -242,6 +242,9 @@ namespace Barotrauma
//handled in TryStartChildServerRelay
i += 2;
break;
case "-lenienthandshake":
NetConfig.UseLenientHandshake = true;
break;
}
}
@@ -7,7 +7,7 @@ namespace Barotrauma.Items.Components
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
{
msg.WriteBoolean(State);
msg.WriteUInt16(user == null ? (ushort)0 : user.ID);
msg.WriteUInt16(User == null || User.Removed ? (ushort)0 : User.ID);
}
}
}
@@ -16,8 +16,11 @@ namespace Barotrauma.Items.Components
public void ServerEventRead(IReadMessage msg, Client c)
{
if (c.Character == null) { return; }
var requestedFixAction = (FixActions)msg.ReadRangedInteger(0, 2);
var QTESuccess = msg.ReadBoolean();
FixActions requestedFixAction = (FixActions)msg.ReadRangedInteger(0, 2);
bool QTESuccess = msg.ReadBoolean();
if (!item.CanClientAccess(c) || !HasRequiredItems(c.Character, addMessage: false)) { return; }
if (requestedFixAction != FixActions.None)
{
if (!c.Character.IsTraitor && requestedFixAction == FixActions.Sabotage)
@@ -121,9 +121,9 @@ namespace Barotrauma
if (shouldBeRemoved)
{
bool itemAccessDenied = prevItems.Contains(item) && // if the item was in the inventory before
!itemAccessibility[item] && // and the sender is not allowed to access it
(item.PreviousParentInventory == null || // and either the item has no previous inventory
!sender.Character.CanAccessInventory(item.PreviousParentInventory)); // or the sender can't access the previous inventory
!itemAccessibility[item] && // and the sender is not allowed to access it
(item.PreviousParentInventory == null || // and either the item has no previous inventory
!sender.Character.CanAccessInventory(item.PreviousParentInventory)); // or the sender can't access the previous inventory
if (itemAccessDenied)
{
@@ -136,7 +136,7 @@ namespace Barotrauma
Item droppedItem = item;
Entity prevOwner = Owner;
Inventory previousInventory = droppedItem.ParentInventory;
droppedItem.Drop(null);
droppedItem.Drop(sender.Character);
droppedItem.PreviousParentInventory = previousInventory;
var previousCharacterInventory = prevOwner switch
@@ -188,9 +188,18 @@ namespace Barotrauma
if (holdable != null && !holdable.CanBeDeattached()) { continue; }
bool itemAccessDenied = !prevItems.Contains(item) && !itemAccessibility[item] &&
(sender.Character == null || item.PreviousParentInventory == null || !sender.Character.CanAccessInventory(item.PreviousParentInventory));
bool itemAccessDenied = !prevItems.Contains(item) &&
!itemAccessibility[item] &&
(item.PreviousParentInventory == null ||
!sender.Character.CanAccessInventory(item.PreviousParentInventory));
// Prevent modified clients from being able to steal items from characters by item swapping with an existing item
// due to drag and drop being enabled
if (!sender.Character.CanAccessInventory(this, CharacterInventory.AccessLevel.AllowBotsAndPets) && GetItemAt(slotIndex) != null)
{
itemAccessDenied = true;
}
//more restricted "adding" of handcuffs: we can't allow putting handcuffs on a player just because dragging and dropping is allowed
if (item.HasTag(Tags.HandLockerItem) && !itemAccessDenied)
{
@@ -12,8 +12,6 @@ namespace Barotrauma
{
private CoroutineHandle logPropertyChangeCoroutine;
public Inventory PreviousParentInventory;
public override Sprite Sprite
{
get { return base.Prefab?.Sprite; }
@@ -112,6 +112,7 @@ namespace Barotrauma
msg.WriteRangedSingle(normalizedXPos, 0.0f, 1.0f, 8);
msg.WriteRangedSingle(normalizedYPos, 0.0f, 1.0f, 8);
msg.WriteRangedSingle(decal.Scale, 0f, 2f, 12);
msg.WriteRangedSingle(decal.BaseAlpha, 0f, 1f, 8);
}
break;
case BallastFloraEventData ballastFloraEventData:
@@ -251,7 +252,7 @@ namespace Barotrauma
break;
case EventType.Decal:
byte decalIndex = msg.ReadByte();
float decalAlpha = msg.ReadRangedSingle(0.0f, 1.0f, 255);
float decalAlpha = msg.ReadRangedSingle(0f, 1f, 8);
if (decalIndex < 0 || decalIndex >= decals.Count) { return; }
if (c.Character != null && c.Character.AllowInput && c.Character.HeldItems.Any(it => it.GetComponent<Sprayer>() != null))
{
@@ -69,6 +69,9 @@ namespace Barotrauma.Networking
txt = msg.ReadString() ?? "";
}
// Sanitize incoming text message from client so they can't use RichString features
txt = txt.Replace('‖', ' ');
if (!NetIdUtils.IdMoreRecent(ID, c.LastSentChatMsgID)) { return; }
c.LastSentChatMsgID = ID;
@@ -244,6 +244,8 @@ namespace Barotrauma
Character targetCharacter = inventory.Owner as Character;
if (yoinker == null || item == null || thiefCharacter == null || targetCharacter == null || thiefCharacter == targetCharacter) { return; }
if (thiefCharacter.TeamID != targetCharacter.TeamID) { return; }
if (targetClient == null && (!DangerousItemStealBots || targetCharacter.AIController == null)) { return; }
@@ -261,7 +263,7 @@ namespace Barotrauma
}
Item foundItem = null;
if (isValid(item))
if (IsValid(item))
{
foundItem = item;
}
@@ -269,7 +271,7 @@ namespace Barotrauma
{
foreach (Item containedItem in item.ContainedItems)
{
if (isValid(containedItem))
if (IsValid(containedItem))
{
foundItem = containedItem;
break;
@@ -277,16 +279,19 @@ namespace Barotrauma
}
}
static bool isValid(Item item)
static bool IsValid(Item item)
{
return item.GetComponent<IdCard>() != null || item.GetComponent<RangedWeapon>() != null || item.GetComponent<MeleeWeapon>() != null;
return item.GetComponent<IdCard>() != null || IsWeapon(item);
}
static bool IsWeapon(Item item)
{
//a threshold of 10 excludes things like tools, all "proper weapons" seem to have a priority higher than that
return item.Components.Max(c => c.CombatPriority) > 10.0f || item.HasTag(Tags.Weapon);
}
if (foundItem == null) { return; }
bool isIdCard = foundItem.GetComponent<IdCard>() != null;
bool isWeapon = foundItem.GetComponent<RangedWeapon>() != null || foundItem.GetComponent<MeleeWeapon>() != null;
if (isIdCard)
{
string name = string.Empty;
@@ -325,7 +330,7 @@ namespace Barotrauma
JobPrefab clientJob = yoinker.CharacterInfo?.Job?.Prefab;
// security officers receive less karma penalty
if (clientJob != null && clientJob.Identifier == "securityofficer" && isWeapon)
if (clientJob != null && clientJob.Identifier == "securityofficer" && IsWeapon(foundItem))
{
karmaDecrease *= 0.5f;
}
@@ -33,6 +33,13 @@ namespace Barotrauma.Networking
DualStack = GameSettings.CurrentConfig.UseDualModeSockets,
LocalAddress = serverSettings.ListenIPAddress,
};
if (NetConfig.UseLenientHandshake)
{
// More lenient timeouts for local testing, so the server would start even without perfect conditions
netPeerConfiguration.ConnectionTimeout = 60.0f;
netPeerConfiguration.ResendHandshakeInterval = 5.0f;
netPeerConfiguration.MaximumHandshakeAttempts = 20;
}
netPeerConfiguration.DisableMessageType(
NetIncomingMessageType.DebugMessage
@@ -596,6 +596,23 @@ namespace Barotrauma.Networking
teamSpecificState.RespawnItems.AddRange(AutoItemPlacer.RegenerateLoot(respawnShuttle, respawnContainer));
}
}
else if (character.InWater)
{
if (divingSuitPrefab != null)
{
var divingSuit = new Item(divingSuitPrefab, character.Position, respawnSub);
Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(divingSuit));
character.Inventory.TryPutItem(divingSuit, user: null, allowedSlots: divingSuit.AllowedSlots);
teamSpecificState.RespawnItems.Add(divingSuit);
if (oxyPrefab != null && divingSuit.GetComponent<ItemContainer>() != null)
{
var oxyTank = new Item(oxyPrefab, character.Position, respawnSub);
Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(oxyTank));
divingSuit.Combine(oxyTank, user: null);
teamSpecificState.RespawnItems.Add(oxyTank);
}
}
}
var characterData = campaign?.GetClientCharacterData(clients[i]);
// NOTE: This was where Reaper's tax got applied
@@ -46,7 +46,7 @@ namespace Barotrauma.Networking
.Aggregate(NetFlags.None, (f1, f2) => f1 | f2);
private bool IsFlagRequired(Client c, NetFlags flag)
=> NetIdUtils.IdMoreRecent(LastUpdateIdForFlag[flag], c.LastRecvLobbyUpdate);
=> NetIdUtils.IdMoreRecent(LastUpdateIdForFlag[flag], c.LastRecvLobbyUpdate) || !c.InitialLobbyUpdateSent;
public NetFlags GetRequiredFlags(Client c)
=> LastUpdateIdForFlag.Keys