Unstable v0.1300.0.0 (February 19th 2021)

This commit is contained in:
Joonas Rikkonen
2021-02-25 13:44:23 +02:00
parent b772654326
commit 24cbef485a
441 changed files with 21343 additions and 8562 deletions
@@ -209,11 +209,11 @@ namespace Barotrauma.Networking
case ChatMessageType.Order:
if (receiver != null && !receiver.IsDead)
{
var receiverItem = receiver.Inventory?.Items.FirstOrDefault(i => i?.GetComponent<WifiComponent>() != null);
var receiverItem = receiver.Inventory?.AllItems.FirstOrDefault(i => i.GetComponent<WifiComponent>() != null);
//character doesn't have a radio -> don't send
if (receiverItem == null || !receiver.HasEquippedItem(receiverItem)) { return spokenMsg; }
var senderItem = sender.Inventory?.Items.FirstOrDefault(i => i?.GetComponent<WifiComponent>() != null);
var senderItem = sender.Inventory?.AllItems.FirstOrDefault(i => i.GetComponent<WifiComponent>() != null);
if (senderItem == null || !sender.HasEquippedItem(senderItem)) { return spokenMsg; }
var receiverRadio = receiverItem.GetComponent<WifiComponent>();
@@ -253,7 +253,7 @@ namespace Barotrauma.Networking
{
radio = null;
if (sender?.Inventory == null || sender.Removed) { return false; }
radio = sender.Inventory.Items.FirstOrDefault(i => i?.GetComponent<WifiComponent>() != null)?.GetComponent<WifiComponent>();
radio = sender.Inventory.AllItems.FirstOrDefault(i => i.GetComponent<WifiComponent>() != null)?.GetComponent<WifiComponent>();
if (radio?.Item == null) { return false; }
return sender.HasEquippedItem(radio.Item) && radio.CanTransmit();
}
@@ -20,7 +20,9 @@ namespace Barotrauma.Networking
public string PreferredJob;
public Character.TeamType TeamID;
public CharacterTeamType TeamID;
public CharacterTeamType PreferredTeam;
private Character character;
public Character Character
@@ -26,6 +26,9 @@ namespace Barotrauma
public readonly Submarine Submarine;
public readonly float Condition;
public bool SpawnIfInventoryFull = true;
public bool IgnoreLimbSlots = false;
private readonly Action<Item> onSpawned;
public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition, Action<Item> onSpawned, float? condition = null)
@@ -62,9 +65,27 @@ namespace Barotrauma
Item spawnedItem;
if (Inventory?.Owner != null)
{
spawnedItem = new Item(Prefab, Vector2.Zero, null);
if (!SpawnIfInventoryFull && !Inventory.CanBePut(Prefab))
{
return null;
}
spawnedItem = new Item(Prefab, Vector2.Zero, null)
{
Condition = Condition
};
if (!Inventory.Owner.Removed && !Inventory.TryPutItem(spawnedItem, null, spawnedItem.AllowedSlots))
{
if (IgnoreLimbSlots)
{
for (int i = 0; i < Inventory.Capacity; i++)
{
if (Inventory.GetItemAt(i) == null)
{
Inventory.ForceToSlot(spawnedItem, i);
break;
}
}
}
spawnedItem.SetTransform(FarseerPhysics.ConvertUnits.ToSimUnits(Inventory.Owner?.WorldPosition ?? Vector2.Zero), spawnedItem.body?.Rotation ?? 0.0f, findNewHull: false);
}
}
@@ -238,7 +259,7 @@ namespace Barotrauma
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, onSpawned, condition));
}
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null, Action<Item> onSpawned = null)
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null, Action<Item> onSpawned = null, bool spawnIfInventoryFull = true, bool ignoreLimbSlots = false)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (itemPrefab == null)
@@ -248,7 +269,11 @@ namespace Barotrauma
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return;
}
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, onSpawned, condition));
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, onSpawned, condition)
{
SpawnIfInventoryFull = spawnIfInventoryFull,
IgnoreLimbSlots = ignoreLimbSlots
});
}
public void AddToSpawnQueue(string speciesName, Vector2 worldPosition, Action<Character> onSpawn = null)
@@ -302,7 +327,7 @@ namespace Barotrauma
if (removeQueue.Contains(item) || item.Removed) { return; }
removeQueue.Enqueue(item);
var containedItems = item.OwnInventory?.Items;
var containedItems = item.OwnInventory?.AllItems;
if (containedItems == null) { return; }
foreach (Item containedItem in containedItems)
{
@@ -329,6 +354,11 @@ namespace Barotrauma
return spawnQueue.Count(s => predicate(s));
}
public bool IsInRemoveQueue(Entity entity)
{
return removeQueue.Contains(entity);
}
public void Update()
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
@@ -36,7 +36,7 @@ namespace Barotrauma
[Serialize(0.1f, true)]
public float StructureDamageKarmaDecrease { get; set; }
[Serialize(30.0f, true)]
[Serialize(15.0f, true)]
public float MaxStructureDamageKarmaDecreasePerSecond { get; set; }
[Serialize(0.03f, true)]
@@ -14,15 +14,6 @@ namespace Barotrauma.Networking
public static string MasterServerUrl = GameMain.Config.MasterServerUrl;
//if a Character is further than this from the sub and the players, the server will disable it
//(in display units)
public const float DisableCharacterDist = 22000.0f;
public const float DisableCharacterDistSqr = DisableCharacterDist * DisableCharacterDist;
//the character needs to get this close to be re-enabled
public const float EnableCharacterDist = 20000.0f;
public const float EnableCharacterDistSqr = EnableCharacterDist * EnableCharacterDist;
public const float MaxPhysicsBodyVelocity = 64.0f;
public const float MaxPhysicsBodyAngularVelocity = 16.0f;
@@ -18,7 +18,8 @@ namespace Barotrauma.Networking
Combine,
ExecuteAttack,
Upgrade,
AssignCampaignInteraction
AssignCampaignInteraction,
ObjectiveManagerOrderState,
}
public readonly Entity Entity;
@@ -43,30 +43,16 @@ namespace Barotrauma.Networking
eventCount++;
continue;
}
//the length of the data is written as a byte, so the data needs to be less than 255 bytes long
if (tempEventBuffer.LengthBytes > 255)
{
DebugConsole.ThrowError("Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes, event ID " + e.ID + $", {string.Join(' ',e.Data.Select(d => d.ToString()))})");
GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:TooLong" + e.Entity.ToString(),
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes, event ID " + e.ID + ")");
//write an empty event to prevent breaking the event syncing
tempBuffer.Write(Entity.NullEntityID);
tempBuffer.WritePadBits();
eventCount++;
continue;
}
if (msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > MaxEventBufferLength)
if (eventCount > 0 &&
msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > MaxEventBufferLength)
{
//no more room in this packet
break;
}
tempBuffer.Write(e.EntityID);
tempBuffer.Write((byte)tempEventBuffer.LengthBytes);
tempBuffer.WriteVariableUInt32((uint)tempEventBuffer.LengthBytes);
tempBuffer.Write(tempEventBuffer.Buffer, 0, tempEventBuffer.LengthBytes);
tempBuffer.WritePadBits();
sentEvents.Add(e);
@@ -226,13 +226,13 @@ namespace Barotrauma.Networking
public bool CanUseRadio(Character sender)
{
if (sender == null) return false;
if (sender == null) { return false; }
var radio = sender.Inventory.Items.FirstOrDefault(i => i != null && i.GetComponent<WifiComponent>() != null);
if (radio == null || !sender.HasEquippedItem(radio)) return false;
var radio = sender.Inventory.AllItems.FirstOrDefault(i => i.GetComponent<WifiComponent>() != null);
if (radio == null || !sender.HasEquippedItem(radio)) { return false; }
var radioComponent = radio.GetComponent<WifiComponent>();
if (radioComponent == null) return false;
if (radioComponent == null) { return false; }
return radioComponent.HasRequiredContainedItems(sender, addMessage: false);
}
@@ -1,4 +1,6 @@
namespace Barotrauma.Networking
using System;
namespace Barotrauma.Networking
{
partial class OrderChatMessage : ChatMessage
{
@@ -13,26 +15,87 @@
//additional instructions (power up, fire at will, etc)
public readonly string OrderOption;
public readonly int OrderPriority;
/// <summary>
/// Used when the order targets a wall
/// </summary>
public int? WallSectionIndex { get; set; }
public OrderChatMessage(Order order, string orderOption, ISpatialEntity targetEntity, Character targetCharacter, Character sender)
: this(order, orderOption,
public OrderChatMessage(Order order, string orderOption, int priority, ISpatialEntity targetEntity, Character targetCharacter, Character sender)
: this(order, orderOption, priority,
order?.GetChatMessage(targetCharacter?.Name, sender?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == sender, orderOption: orderOption),
targetEntity, targetCharacter, sender)
{
}
public OrderChatMessage(Order order, string orderOption, string text, ISpatialEntity targetEntity, Character targetCharacter, Character sender)
public OrderChatMessage(Order order, string orderOption, int priority, string text, ISpatialEntity targetEntity, Character targetCharacter, Character sender)
: base(sender?.Name, text, ChatMessageType.Order, sender, GameMain.NetworkMember.ConnectedClients.Find(c => c.Character == sender))
{
Order = order;
OrderOption = orderOption;
OrderPriority = priority;
TargetCharacter = targetCharacter;
TargetEntity = targetEntity;
}
private void WriteOrder(IWriteMessage msg)
{
msg.Write((byte)Order.PrefabList.IndexOf(Order.Prefab));
msg.Write(TargetCharacter == null ? (UInt16)0 : TargetCharacter.ID);
msg.Write(TargetEntity is Entity ? (TargetEntity as Entity).ID : (UInt16)0);
// The option of a Dismiss order is written differently so we know what order we target
// now that the game supports multiple current orders simultaneously
if (Order.Prefab.Identifier != "dismissed")
{
msg.Write((byte)Array.IndexOf(Order.Prefab.Options, OrderOption));
}
else
{
if (!string.IsNullOrEmpty(OrderOption))
{
msg.Write(true);
string[] dismissedOrder = OrderOption.Split('.');
msg.Write((byte)dismissedOrder.Length);
if (dismissedOrder.Length > 0)
{
string dismissedOrderIdentifier = dismissedOrder[0];
var orderPrefab = Order.GetPrefab(dismissedOrderIdentifier);
msg.Write((byte)Order.PrefabList.IndexOf(orderPrefab));
if (dismissedOrder.Length > 1)
{
string dismissedOrderOption = dismissedOrder[1];
msg.Write((byte)Array.IndexOf(orderPrefab.Options, dismissedOrderOption));
}
}
}
else
{
// If the order option is not specified for a Dismiss order,
// we dismiss all current orders for the character
msg.Write(false);
}
}
msg.Write((byte)OrderPriority);
msg.Write((byte)Order.TargetType);
if (Order.TargetType == Order.OrderTargetType.Position && TargetEntity is OrderTarget orderTarget)
{
msg.Write(true);
msg.Write(orderTarget.Position.X);
msg.Write(orderTarget.Position.Y);
msg.Write(orderTarget.Hull == null ? (UInt16)0 : orderTarget.Hull.ID);
}
else
{
msg.Write(false);
if (Order.TargetType == Order.OrderTargetType.WallSection)
{
msg.Write((byte)(WallSectionIndex ?? Order.WallSectionIndex ?? 0));
}
}
}
}
}
@@ -136,8 +136,7 @@ namespace Barotrauma.Networking
EnsureBufferSize(ref buf, bitPos + 64);
byte[] bytes = BitConverter.GetBytes(val);
WriteBytes(ref buf, ref bitPos, bytes, 0, bytes.Length);
bitPos += 64;
WriteBytes(ref buf, ref bitPos, bytes, 0, 8);
}
internal static void Write(ref byte[] buf, ref int bitPos, string val)
{
@@ -155,14 +154,14 @@ namespace Barotrauma.Networking
internal static int WriteVariableUInt32(ref byte[] buf, ref int bitPos, uint value)
{
int retval = 1;
uint num1 = (uint)value;
while (num1 >= 0x80)
uint remainingValue = (uint)value;
while (remainingValue >= 0x80)
{
Write(ref buf, ref bitPos, (byte)(num1 | 0x80));
num1 = num1 >> 7;
Write(ref buf, ref bitPos, (byte)(remainingValue | 0x80));
remainingValue = remainingValue >> 7;
retval++;
}
Write(ref buf, ref bitPos, (byte)num1);
Write(ref buf, ref bitPos, (byte)remainingValue);
return retval;
}
@@ -304,19 +303,19 @@ namespace Barotrauma.Networking
{
int bitLength = buf.Length * 8;
int num1 = 0;
int num2 = 0;
int result = 0;
int shift = 0;
while (bitLength - bitPos >= 8)
{
byte num3 = ReadByte(buf, ref bitPos);
num1 |= (num3 & 0x7f) << num2;
num2 += 7;
if ((num3 & 0x80) == 0)
return (uint)num1;
byte chunk = ReadByte(buf, ref bitPos);
result |= (chunk & 0x7f) << shift;
shift += 7;
if ((chunk & 0x80) == 0)
return (uint)result;
}
// ouch; failed to find enough bytes; malformed variable length number?
return (uint)num1;
return (uint)result;
}
internal static String ReadString(byte[] buf, ref int bitPos)
@@ -329,7 +328,7 @@ namespace Barotrauma.Networking
if ((ulong)(bitLength - bitPos) < ((ulong)byteLen * 8))
{
// not enough data
return null;
return null;
}
if ((bitPos & 7) == 0)
@@ -34,6 +34,13 @@ namespace Barotrauma.Networking
EndPointString = IPString;
}
public override bool SetSteamIDIfUnknown(UInt64 id)
{
if (SteamID != 0) { return false; } //do not allow the SteamID to be set multiple times
SteamID = id;
return true;
}
public override bool EndpointMatches(string endPoint)
{
if (IPEndPoint?.Address == null) { return false; }
@@ -35,5 +35,14 @@ namespace Barotrauma.Networking
public abstract bool EndpointMatches(string endPoint);
public NetworkConnectionStatus Status = NetworkConnectionStatus.Disconnected;
public virtual bool SetSteamIDIfUnknown(UInt64 id)
{
//by default, don't allow setting the ID, this is only done
//with Lidgren connections since those are initialized before
//the SteamID can be known; it's set once the Steam auth ticket
//is received by the server.
return false;
}
}
}
@@ -79,7 +79,7 @@ namespace Barotrauma.Networking
}
foreach (WifiComponent wifiComponent in wifiComponents)
{
wifiComponent.TeamID = Character.TeamType.FriendlyNPC;
wifiComponent.TeamID = CharacterTeamType.FriendlyNPC;
}
ResetShuttle();
@@ -222,7 +222,7 @@ namespace Barotrauma.Networking
foreach (Item item in Item.ItemList)
{
if (item.Submarine != RespawnShuttle) continue;
if (item.Submarine != RespawnShuttle) { continue; }
//remove respawn items that have been left in the shuttle
if (respawnItems.Contains(item))
@@ -239,6 +239,19 @@ namespace Barotrauma.Networking
{
powerContainer.Charge = powerContainer.Capacity;
}
var door = item.GetComponent<Door>();
if (door != null) { door.Stuck = 0.0f; }
var steering = item.GetComponent<Steering>();
if (steering != null)
{
steering.MaintainPos = true;
steering.AutoPilot = true;
#if SERVER
steering.UnsentChanges = true;
#endif
}
}
foreach (Structure wall in Structure.WallList)
@@ -269,9 +282,8 @@ namespace Barotrauma.Networking
Spawner.AddToRemoveQueue(c);
if (c.Inventory != null)
{
foreach (Item item in c.Inventory.Items)
foreach (Item item in c.Inventory.AllItems)
{
if (item == null) continue;
Spawner.AddToRemoveQueue(item);
}
}
@@ -787,7 +787,7 @@ namespace Barotrauma.Networking
private set;
}
[Serialize(120.0f, true)]
[Serialize(300.0f, true)]
public float KillDisconnectedTime
{
get;
@@ -6,8 +6,8 @@ namespace Barotrauma.Networking
{
static partial class VoipConfig
{
public const int MAX_COMPRESSED_SIZE = 120; //amount of bytes we expect each 60ms of audio to fit in
public const int MAX_COMPRESSED_SIZE = 40; //amount of bytes we expect each 20ms of audio to fit in
public static readonly TimeSpan SEND_INTERVAL = new TimeSpan(0,0,0,0,120);
public static readonly TimeSpan SEND_INTERVAL = new TimeSpan(0,0,0,0,20);
}
}