Unstable 0.17.0.0

This commit is contained in:
Markus Isberg
2022-02-26 02:43:01 +09:00
parent a83f375681
commit 3974067915
913 changed files with 32472 additions and 32364 deletions
@@ -56,9 +56,9 @@ namespace Barotrauma.Networking
{
if (Type.HasFlag(ChatMessageType.Server) || Type.HasFlag(ChatMessageType.Error) || Type.HasFlag(ChatMessageType.ServerLog))
{
if (translatedText == null || translatedText.Length == 0)
if (translatedText.IsNullOrEmpty())
{
translatedText = TextManager.GetServerMessage(Text);
translatedText = TextManager.GetServerMessage(Text).Value;
}
return translatedText;
@@ -15,11 +15,11 @@ namespace Barotrauma.Networking
public UInt64 SteamID;
public UInt64 OwnerSteamID;
public string Language;
public LanguageIdentifier Language;
public UInt16 Ping;
public string PreferredJob;
public Identifier PreferredJob;
public CharacterTeamType TeamID;
@@ -148,7 +148,7 @@ namespace Barotrauma.Networking
private List<Client> kickVoters;
public HashSet<string> GivenAchievements = new HashSet<string>();
public HashSet<Identifier> GivenAchievements = new HashSet<Identifier>();
public ClientPermissions Permissions = ClientPermissions.None;
public List<DebugConsole.Command> PermittedConsoleCommands
@@ -33,16 +33,16 @@ namespace Barotrauma.Networking
{
public static List<PermissionPreset> List = new List<PermissionPreset>();
public readonly string Name;
public readonly string Description;
public readonly LocalizedString Name;
public readonly LocalizedString Description;
public readonly ClientPermissions Permissions;
public readonly List<DebugConsole.Command> PermittedCommands;
public PermissionPreset(XElement element)
{
string name = element.GetAttributeString("name", "");
Name = TextManager.Get("permissionpresetname." + name, true) ?? name;
Description = TextManager.Get("permissionpresetdescription." + name, true) ?? element.GetAttributeString("description", "");
Name = TextManager.Get("permissionpresetname." + name).Fallback(name);
Description = TextManager.Get("permissionpresetdescription." + name) .Fallback(element.GetAttributeString("description", ""));
string permissionsStr = element.GetAttributeString("permissions", "");
if (!Enum.TryParse(permissionsStr, out Permissions))
@@ -53,7 +53,7 @@ namespace Barotrauma.Networking
PermittedCommands = new List<DebugConsole.Command>();
if (Permissions.HasFlag(ClientPermissions.ConsoleCommands))
{
foreach (XElement subElement in element.Elements())
foreach (var subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("command", StringComparison.OrdinalIgnoreCase)) { continue; }
string commandName = subElement.GetAttributeString("name", "");
@@ -117,7 +117,7 @@ namespace Barotrauma
class CharacterSpawnInfo : IEntitySpawnInfo
{
public readonly string identifier;
public readonly Identifier Identifier;
public readonly CharacterInfo CharacterInfo;
public readonly Vector2 Position;
@@ -125,30 +125,32 @@ namespace Barotrauma
private readonly Action<Character> onSpawned;
public CharacterSpawnInfo(string identifier, Vector2 worldPosition, Action<Character> onSpawn = null)
public CharacterSpawnInfo(Identifier identifier, Vector2 worldPosition, Action<Character> onSpawn = null)
{
this.identifier = identifier ?? throw new ArgumentException("ItemSpawnInfo prefab cannot be null.");
this.Identifier = identifier;
if (identifier.IsEmpty) { throw new ArgumentException($"{nameof(CharacterSpawnInfo)} identifier cannot be null."); }
Position = worldPosition;
this.onSpawned = onSpawn;
}
public CharacterSpawnInfo(string identifier, Vector2 position, Submarine sub, Action<Character> onSpawn = null)
public CharacterSpawnInfo(Identifier identifier, Vector2 position, Submarine sub, Action<Character> onSpawn = null)
{
this.identifier = identifier ?? throw new ArgumentException("ItemSpawnInfo prefab cannot be null.");
this.Identifier = identifier;
if (identifier.IsEmpty) { throw new ArgumentException($"{nameof(CharacterSpawnInfo)} identifier cannot be null."); }
Position = position;
Submarine = sub;
this.onSpawned = onSpawn;
}
public CharacterSpawnInfo(string identifier, Vector2 position, CharacterInfo characterInfo, Action<Character> onSpawn = null) : this (identifier, position, onSpawn)
public CharacterSpawnInfo(Identifier identifier, Vector2 position, CharacterInfo characterInfo, Action<Character> onSpawn = null) : this (identifier, position, onSpawn)
{
CharacterInfo = characterInfo;
}
public Entity Spawn()
{
var character = string.IsNullOrEmpty(identifier) ? null :
Character.Create(identifier,
var character = Identifier.IsEmpty ? null :
Character.Create(Identifier,
Submarine == null ? Position : Submarine.Position + Position,
ToolBox.RandomSeed(8), CharacterInfo, createNetworkEvent: false);
return character;
@@ -199,6 +201,7 @@ namespace Barotrauma
public readonly Entity Entity;
public readonly UInt16 OriginalID, OriginalInventoryID;
public readonly int OriginalSlotIndex;
public readonly byte OriginalItemContainerIndex;
@@ -219,6 +222,7 @@ namespace Barotrauma
if (entity is Item item && item.ParentInventory?.Owner != null)
{
OriginalInventoryID = item.ParentInventory.Owner.ID;
OriginalSlotIndex = item.ParentInventory.FindIndex(item);
//find the index of the ItemContainer this item is inside to get the item to
//spawn in the correct inventory in multi-inventory items like fabricators
if (item.Container != null)
@@ -250,7 +254,7 @@ namespace Barotrauma
return "EntitySpawner";
}
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition = null, int? quality = null, Action<Item> onSpawned = null)
public void AddItemToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition = null, int? quality = null, Action<Item> onSpawned = null)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (itemPrefab == null)
@@ -263,7 +267,7 @@ namespace Barotrauma
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, onSpawned, condition, quality));
}
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null, int? quality = null, Action<Item> onSpawned = null)
public void AddItemToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null, int? quality = null, Action<Item> onSpawned = null)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (itemPrefab == null)
@@ -276,7 +280,7 @@ namespace Barotrauma
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, onSpawned, condition, quality));
}
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null, int? quality = null, Action<Item> onSpawned = null, bool spawnIfInventoryFull = true, bool ignoreLimbSlots = false, InvSlotType slot = InvSlotType.None)
public void AddItemToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null, int? quality = null, Action<Item> onSpawned = null, bool spawnIfInventoryFull = true, bool ignoreLimbSlots = false, InvSlotType slot = InvSlotType.None)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (itemPrefab == null)
@@ -294,10 +298,10 @@ namespace Barotrauma
});
}
public void AddToSpawnQueue(string speciesName, Vector2 worldPosition, Action<Character> onSpawn = null)
public void AddCharacterToSpawnQueue(Identifier speciesName, Vector2 worldPosition, Action<Character> onSpawn = null)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (string.IsNullOrEmpty(speciesName))
if (speciesName.IsEmpty)
{
string errorMsg = "Attempted to add an empty/null species name to entity spawn queue.\n" + Environment.StackTrace.CleanupStackTrace();
DebugConsole.ThrowError(errorMsg);
@@ -307,10 +311,10 @@ namespace Barotrauma
spawnQueue.Enqueue(new CharacterSpawnInfo(speciesName, worldPosition, onSpawn));
}
public void AddToSpawnQueue(string speciesName, Vector2 position, Submarine sub, Action<Character> onSpawn = null)
public void AddCharacterToSpawnQueue(Identifier speciesName, Vector2 position, Submarine sub, Action<Character> onSpawn = null)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (string.IsNullOrEmpty(speciesName))
if (speciesName.IsEmpty)
{
string errorMsg = "Attempted to add an empty/null species name to entity spawn queue.\n" + Environment.StackTrace.CleanupStackTrace();
DebugConsole.ThrowError(errorMsg);
@@ -320,10 +324,10 @@ namespace Barotrauma
spawnQueue.Enqueue(new CharacterSpawnInfo(speciesName, position, sub, onSpawn));
}
public void AddToSpawnQueue(string speciesName, Vector2 worldPosition, CharacterInfo characterInfo, Action<Character> onSpawn = null)
public void AddCharacterToSpawnQueue(Identifier speciesName, Vector2 worldPosition, CharacterInfo characterInfo, Action<Character> onSpawn = null)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (string.IsNullOrEmpty(speciesName))
if (speciesName.IsEmpty)
{
string errorMsg = "Attempted to add an empty/null species name to entity spawn queue.\n" + Environment.StackTrace.CleanupStackTrace();
DebugConsole.ThrowError(errorMsg);
@@ -333,10 +337,11 @@ namespace Barotrauma
spawnQueue.Enqueue(new CharacterSpawnInfo(speciesName, worldPosition, characterInfo, onSpawn));
}
public void AddToRemoveQueue(Entity entity)
public void AddEntityToRemoveQueue(Entity entity)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (removeQueue.Contains(entity) || entity.Removed || entity == null || entity.IdFreed) { return; }
if (entity is Item item) { AddItemToRemoveQueue(item); return; }
if (entity is Character)
{
Character character = entity as Character;
@@ -352,7 +357,7 @@ namespace Barotrauma
removeQueue.Enqueue(entity);
}
public void AddToRemoveQueue(Item item)
public void AddItemToRemoveQueue(Item item)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (removeQueue.Contains(item) || item.Removed) { return; }
@@ -364,7 +369,7 @@ namespace Barotrauma
{
if (containedItem != null)
{
AddToRemoveQueue(containedItem);
AddItemToRemoveQueue(containedItem);
}
}
}
@@ -12,6 +12,6 @@
enum FileTransferType
{
Submarine, CampaignSave
Submarine, CampaignSave, Mod
}
}
@@ -77,6 +77,7 @@ namespace Barotrauma
{ typeof(Single), new ReadWriteBehavior(ReadSingle, WriteSingle) },
{ typeof(Double), new ReadWriteBehavior(ReadDouble, WriteDynamic) },
{ typeof(String), new ReadWriteBehavior(ReadString, WriteDynamic) },
{ typeof(Identifier), new ReadWriteBehavior(ReadIdentifier, WriteDynamic) },
{ typeof(Color), new ReadWriteBehavior(ReadColor, WriteColor) },
{ typeof(Vector2), new ReadWriteBehavior(ReadVector2, WriteVector2) }
}.ToImmutableDictionary();
@@ -86,7 +87,7 @@ namespace Barotrauma
private static readonly ImmutableDictionary<Predicate<Type>, ReadWriteBehavior> TypePredicates = new Dictionary<Predicate<Type>, ReadWriteBehavior>
{
// Arrays
{ type => type.BaseType?.IsAssignableFrom(typeof(Array)) ?? false, new ReadWriteBehavior(ReadArray, WriteArray) },
{ type => typeof(Array).IsAssignableFrom(type.BaseType), new ReadWriteBehavior(ReadArray, WriteArray) },
// Nested INetSerializableStructs
{ type => typeof(INetSerializableStruct).IsAssignableFrom(type), new ReadWriteBehavior(ReadINetSerializableStruct, WriteINetSerializableStruct) },
@@ -94,14 +95,77 @@ namespace Barotrauma
// Enums
{ type => type.IsEnum, new ReadWriteBehavior(ReadEnum, WriteEnum) },
// Nullable / Optional types
{ type => Nullable.GetUnderlyingType(type) != null, new ReadWriteBehavior(ReadNullable, WriteNullable) }
// Nullable
{ type => Nullable.GetUnderlyingType(type) != null, new ReadWriteBehavior(ReadNullable, WriteNullable) },
// Option
{ type => type.GetGenericTypeDefinition() == typeof(Option<>), new ReadWriteBehavior(ReadOption, WriteOption) }
}.ToImmutableDictionary();
private static readonly Dictionary<Type, MethodInfo> cachedSomeCreateMethods = new Dictionary<Type, MethodInfo>();
private static readonly Dictionary<Type, MethodInfo> cachedNoneCreateMethod = new Dictionary<Type, MethodInfo>();
private static void WriteInvalid(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg) => throw new InvalidOperationException($"Type {obj?.GetType()} cannot be serialized. Did you forget to implement INetSerializableStruct?");
private static dynamic ReadInvalid(IReadMessage inc, Type type, NetworkSerialize attribute) => throw new InvalidOperationException($"Type {type} cannot be deserialized. Did you forget to implement INetSerializableStruct?");
private static void WriteOption(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg)
{
if (obj is null) { throw new ArgumentNullException(nameof(obj), "Tried to write 'null' into a non-nullable type"); }
Type type = obj.GetType();
Type optionType = type.GetGenericTypeDefinition();
Type underlyingType = type.GetGenericArguments()[0];
if (optionType == typeof(None<>))
{
msg.Write(false);
}
else if (optionType == typeof(Some<>))
{
msg.Write(true);
if (TryFindBehavior(underlyingType, out ReadWriteBehavior behavior))
{
behavior.WriteAction(obj.Value, attribute, msg);
}
}
else
{
throw new InvalidOperationException("Option type was neither None<> or Some<>");
}
}
private static dynamic? ReadOption(IReadMessage inc, Type type, NetworkSerialize attribute)
{
Type underlyingType = type.GetGenericArguments()[0];
bool hasValue = inc.ReadBoolean();
if (!hasValue)
{
return GetCreateMethod(typeof(None<>), underlyingType, cachedNoneCreateMethod).Invoke(null, null);
}
if (TryFindBehavior(underlyingType, out ReadWriteBehavior behavior))
{
dynamic? value = behavior.ReadAction(inc, underlyingType, attribute);
return GetCreateMethod(typeof(Some<>), underlyingType, cachedSomeCreateMethods).Invoke(null, new []{ value });
}
throw new InvalidOperationException($"Could not find suitable behavior for type {underlyingType} in {nameof(ReadOption)}");
static MethodInfo GetCreateMethod(Type optionType, Type type, Dictionary<Type, MethodInfo> cache)
{
if (cache.TryGetValue(type, out MethodInfo? foundInfo))
{
return foundInfo;
}
Type genericType = optionType.MakeGenericType(type);
MethodInfo info = genericType.GetMethod("Create", BindingFlags.Static | BindingFlags.Public)!;
cache.Add(type, info);
return info;
}
}
private static void WriteNullable(dynamic? obj, NetworkSerialize attribute, IWriteMessage msg)
{
if (obj is { } notNull)
@@ -152,9 +216,9 @@ namespace Barotrauma
Range<int> range = GetEnumRange(type);
int enumIndex = inc.ReadRangedInteger(range.Start, range.End);
foreach (dynamic e in Enum.GetValues(type))
foreach (dynamic? e in Enum.GetValues(type))
{
if (Convert.ChangeType(e, e.GetTypeCode()) == enumIndex) { return e; }
if (Convert.ChangeType(e, e!.GetTypeCode()) == enumIndex) { return e; }
}
throw new InvalidOperationException($"An enum {type} with value {enumIndex} could not be found in {nameof(ReadEnum)}");
@@ -213,9 +277,9 @@ namespace Barotrauma
msg.WriteRangedInteger(array.Length, 0, attribute.ArrayMaxSize);
foreach (dynamic o in array)
foreach (dynamic? o in array)
{
if (TryFindBehavior(o.GetType(), out ReadWriteBehavior behavior))
if (TryFindBehavior(o!.GetType(), out ReadWriteBehavior behavior))
{
behavior.WriteAction(o, attribute, msg);
}
@@ -285,6 +349,8 @@ namespace Barotrauma
private static dynamic ReadDouble(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadDouble();
private static dynamic ReadString(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadString();
private static dynamic ReadIdentifier(IReadMessage inc, Type type, NetworkSerialize attribute) => inc.ReadIdentifier();
private static dynamic ReadColor(IReadMessage inc, Type type, NetworkSerialize attribute) => attribute.IncludeColorAlpha ? inc.ReadColorR8G8B8A8() : inc.ReadColorR8G8B8();
@@ -408,8 +474,8 @@ namespace Barotrauma
/// <see cref="String">string</see><br/>
/// <see cref="Microsoft.Xna.Framework.Color"/><br/>
/// <see cref="Microsoft.Xna.Framework.Vector2"/><br/>
/// In addition arrays, enums and <see cref="Nullable{T}"/> are supported.<br/>
/// Using <see cref="Nullable{T}"/> will make the field or property optional
/// In addition arrays, enums, <see cref="Nullable{T}"/> and <see cref="Option{T}"/> are supported.<br/>
/// Using <see cref="Nullable{T}"/> or <see cref="Option{T}"/> will make the field or property optional.
/// </remarks>
/// <seealso cref="NetworkSerialize"/>
public interface INetSerializableStruct
@@ -13,105 +13,105 @@ namespace Barotrauma
public string Name => "KarmaManager";
public Dictionary<string, SerializableProperty> SerializableProperties { get; private set; }
public Dictionary<Identifier, SerializableProperty> SerializableProperties { get; private set; }
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool ResetKarmaBetweenRounds { get; set; }
[Serialize(0.1f, true)]
[Serialize(0.1f, IsPropertySaveable.Yes)]
public float KarmaDecay { get; set; }
[Serialize(50.0f, true)]
[Serialize(50.0f, IsPropertySaveable.Yes)]
public float KarmaDecayThreshold { get; set; }
[Serialize(0.15f, true)]
[Serialize(0.15f, IsPropertySaveable.Yes)]
public float KarmaIncrease { get; set; }
[Serialize(50.0f, true)]
[Serialize(50.0f, IsPropertySaveable.Yes)]
public float KarmaIncreaseThreshold { get; set; }
[Serialize(0.05f, true)]
[Serialize(0.05f, IsPropertySaveable.Yes)]
public float StructureRepairKarmaIncrease { get; set; }
[Serialize(0.1f, true)]
[Serialize(0.1f, IsPropertySaveable.Yes)]
public float StructureDamageKarmaDecrease { get; set; }
[Serialize(15.0f, true)]
[Serialize(15.0f, IsPropertySaveable.Yes)]
public float MaxStructureDamageKarmaDecreasePerSecond { get; set; }
[Serialize(0.03f, true)]
[Serialize(0.03f, IsPropertySaveable.Yes)]
public float ItemRepairKarmaIncrease { get; set; }
[Serialize(0.5f, true)]
[Serialize(0.5f, IsPropertySaveable.Yes)]
public float ReactorOverheatKarmaDecrease { get; set; }
[Serialize(30.0f, true)]
[Serialize(30.0f, IsPropertySaveable.Yes)]
public float ReactorMeltdownKarmaDecrease { get; set; }
[Serialize(0.1f, true)]
[Serialize(0.1f, IsPropertySaveable.Yes)]
public float DamageEnemyKarmaIncrease { get; set; }
[Serialize(0.2f, true)]
[Serialize(0.2f, IsPropertySaveable.Yes)]
public float HealFriendlyKarmaIncrease { get; set; }
[Serialize(0.25f, true)]
[Serialize(0.25f, IsPropertySaveable.Yes)]
public float DamageFriendlyKarmaDecrease { get; set; }
[Serialize(0.25f, true)]
[Serialize(0.25f, IsPropertySaveable.Yes)]
public float StunFriendlyKarmaDecrease { get; set; }
[Serialize(0.3f, true)]
[Serialize(0.3f, IsPropertySaveable.Yes)]
public float StunFriendlyKarmaDecreaseThreshold { get; set; }
[Serialize(1.0f, true)]
[Serialize(1.0f, IsPropertySaveable.Yes)]
public float ExtinguishFireKarmaIncrease { get; set; }
[Serialize(defaultValue: 15.0f, true)]
[Serialize(defaultValue: 15.0f, IsPropertySaveable.Yes)]
public float DangerousItemStealKarmaDecrease { get; set; }
[Serialize(defaultValue: false, true)]
[Serialize(defaultValue: false, IsPropertySaveable.Yes)]
public bool DangerousItemStealBots { get; set; }
[Serialize(defaultValue: 0.05f, true)]
[Serialize(defaultValue: 0.05f, IsPropertySaveable.Yes)]
public float BallastFloraKarmaIncrease { get; set; }
private int allowedWireDisconnectionsPerMinute;
[Serialize(5, true)]
[Serialize(5, IsPropertySaveable.Yes)]
public int AllowedWireDisconnectionsPerMinute
{
get { return allowedWireDisconnectionsPerMinute; }
set { allowedWireDisconnectionsPerMinute = Math.Max(0, value); }
}
[Serialize(6.0f, true)]
[Serialize(6.0f, IsPropertySaveable.Yes)]
public float WireDisconnectionKarmaDecrease { get; set; }
[Serialize(0.15f, true)]
[Serialize(0.15f, IsPropertySaveable.Yes)]
public float SteerSubKarmaIncrease { get; set; }
[Serialize(15.0f, true)]
[Serialize(15.0f, IsPropertySaveable.Yes)]
public float SpamFilterKarmaDecrease { get; set; }
[Serialize(40.0f, true)]
[Serialize(40.0f, IsPropertySaveable.Yes)]
public float HerpesThreshold { get; set; }
[Serialize(1.0f, true)]
[Serialize(1.0f, IsPropertySaveable.Yes)]
public float KickBanThreshold { get; set; }
[Serialize(0, true)]
[Serialize(0, IsPropertySaveable.Yes)]
public int KicksBeforeBan { get; set; }
[Serialize(10.0f, true)]
[Serialize(10.0f, IsPropertySaveable.Yes)]
public float KarmaNotificationInterval { get; set; }
[Serialize(120.0f, true)]
[Serialize(120.0f, IsPropertySaveable.Yes)]
public float AllowedRetaliationTime { get; set; }
[Serialize(5.0f, true)]
[Serialize(5.0f, IsPropertySaveable.Yes)]
public float DangerousItemContainKarmaDecrease { get; set; }
[Serialize(defaultValue: true, true)]
[Serialize(defaultValue: true, IsPropertySaveable.Yes)]
public bool IsDangerousItemContainKarmaDecreaseIncremental { get; set; }
[Serialize(30.0f, true)]
[Serialize(30.0f, IsPropertySaveable.Yes)]
public float MaxDangerousItemContainKarmaDecrease { get; set; }
private readonly AfflictionPrefab herpesAffliction;
@@ -141,7 +141,7 @@ namespace Barotrauma
if (doc?.Root != null)
{
Presets["custom"] = doc.Root;
foreach (XElement subElement in doc.Root.Elements())
foreach (var subElement in doc.Root.Elements())
{
string presetName = subElement.GetAttributeString("name", "");
Presets[presetName.ToLowerInvariant()] = subElement;
@@ -13,8 +13,6 @@ namespace Barotrauma.Networking
public const int ServerNameMaxLength = 60;
public const int ServerMessageMaxLength = 2000;
public static string MasterServerUrl = GameMain.Config.MasterServerUrl;
public const float MaxPhysicsBodyVelocity = 64.0f;
public const float MaxPhysicsBodyAngularVelocity = 16.0f;
@@ -11,17 +11,17 @@ namespace Barotrauma.Networking
public readonly Character TargetCharacter;
//which entity is this order referring to (hull, reactor, railgun controller, etc)
public readonly ISpatialEntity TargetEntity;
public ISpatialEntity TargetEntity => Order.TargetSpatialEntity;
//additional instructions (power up, fire at will, etc)
public readonly string OrderOption;
public Identifier OrderOption => Order.Option;
public readonly int OrderPriority;
public int OrderPriority => Order.ManualPriority;
/// <summary>
/// Used when the order targets a wall
/// </summary>
public int? WallSectionIndex { get; set; }
public int? WallSectionIndex => Order.WallSectionIndex;
public bool IsNewOrder { get; }
@@ -29,55 +29,50 @@ namespace Barotrauma.Networking
/// Same as calling <see cref="OrderChatMessage.OrderChatMessage(Order, string, int, string, ISpatialEntity, Character, Character)"/>,
/// but the text parameter is set using <see cref="Order.GetChatMessage(string, string, bool, string)"/>
/// </summary>
public OrderChatMessage(Order order, string orderOption, int priority, ISpatialEntity targetEntity, Character targetCharacter, Character sender, bool isNewOrder = true)
: this(order, orderOption, priority,
order?.GetChatMessage(targetCharacter?.Name, sender?.CurrentHull?.DisplayName, targetCharacter == sender, orderOption, isNewOrder),
targetEntity, targetCharacter, sender, isNewOrder)
public OrderChatMessage(Order order, Character targetCharacter, Character sender, bool isNewOrder = true)
: this(order,
order?.GetChatMessage(targetCharacter?.Name, sender?.CurrentHull?.DisplayName?.Value, givingOrderToSelf: targetCharacter == sender, orderOption: order.Option, isNewOrder: isNewOrder),
targetCharacter, sender, isNewOrder)
{
}
public OrderChatMessage(Order order, string orderOption, int priority, string text, ISpatialEntity targetEntity,
Character targetCharacter, Character sender, bool isNewOrder = true)
public OrderChatMessage(Order order, string text, Character targetCharacter, Character sender, bool isNewOrder = true)
: 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;
IsNewOrder = isNewOrder;
}
public static void WriteOrder(IWriteMessage msg, Order order, Character targetCharacter, ISpatialEntity targetEntity,
string orderOption, int orderPriority, int? wallSectionIndex, bool isNewOrder)
public static void WriteOrder(IWriteMessage msg, Order order, Character targetCharacter, bool isNewOrder)
{
msg.Write((byte)Order.PrefabList.IndexOf(order.Prefab));
msg.Write(order.Prefab.Identifier);
msg.Write(targetCharacter == null ? (UInt16)0 : targetCharacter.ID);
msg.Write(targetEntity is Entity ? (targetEntity as Entity).ID : (UInt16)0);
msg.Write(order.TargetSpatialEntity is Entity ? (order.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")
if (!order.IsDismissal)
{
msg.Write((byte)Array.IndexOf(order.Prefab.Options, orderOption));
msg.Write((byte)order.Options.IndexOf(order.Option));
}
else
{
if (!string.IsNullOrEmpty(orderOption))
if (order.Option != Identifier.Empty)
{
msg.Write(true);
string[] dismissedOrder = orderOption.Split('.');
string[] dismissedOrder = order.Option.Value.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));
Identifier dismissedOrderIdentifier = dismissedOrder[0].ToIdentifier();
var orderPrefab = OrderPrefab.Prefabs[dismissedOrderIdentifier];
msg.Write(dismissedOrderIdentifier);
if (dismissedOrder.Length > 1)
{
string dismissedOrderOption = dismissedOrder[1];
msg.Write((byte)Array.IndexOf(orderPrefab.Options, dismissedOrderOption));
Identifier dismissedOrderOption = dismissedOrder[1].ToIdentifier();
msg.Write((byte)orderPrefab.Options.IndexOf(dismissedOrderOption));
}
}
}
@@ -89,9 +84,9 @@ namespace Barotrauma.Networking
}
}
msg.Write((byte)orderPriority);
msg.Write((byte)order.ManualPriority);
msg.Write((byte)order.TargetType);
if (order.TargetType == Order.OrderTargetType.Position && targetEntity is OrderTarget orderTarget)
if (order.TargetType == Order.OrderTargetType.Position && order.TargetSpatialEntity is OrderTarget orderTarget)
{
msg.Write(true);
msg.Write(orderTarget.Position.X);
@@ -103,7 +98,7 @@ namespace Barotrauma.Networking
msg.Write(false);
if (order.TargetType == Order.OrderTargetType.WallSection)
{
msg.Write((byte)(wallSectionIndex ?? order.WallSectionIndex ?? 0));
msg.Write((byte)(order.WallSectionIndex ?? 0));
}
}
@@ -112,14 +107,14 @@ namespace Barotrauma.Networking
private void WriteOrder(IWriteMessage msg)
{
WriteOrder(msg, Order, TargetCharacter, TargetEntity, OrderOption, OrderPriority, WallSectionIndex, IsNewOrder);
WriteOrder(msg, Order, TargetCharacter, IsNewOrder);
}
public struct OrderMessageInfo
{
public int OrderIndex { get; }
public Order OrderPrefab { get; }
public string OrderOption { get; }
public Identifier OrderIdentifier { get; }
public OrderPrefab OrderPrefab => OrderPrefab.Prefabs[OrderIdentifier];
public Identifier OrderOption { get; }
public int? OrderOptionIndex { get; }
public Character TargetCharacter { get; }
public Order.OrderTargetType TargetType { get; }
@@ -129,11 +124,10 @@ namespace Barotrauma.Networking
public int Priority { get; }
public bool IsNewOrder { get; }
public OrderMessageInfo(int orderIndex, Order orderPrefab, string orderOption, int? orderOptionIndex, Character targetCharacter,
public OrderMessageInfo(Identifier orderIdentifier, Identifier orderOption, int? orderOptionIndex, Character targetCharacter,
Order.OrderTargetType targetType, Entity targetEntity, OrderTarget targetPosition, int? wallSectionIndex, int orderPriority, bool isNewOrder)
{
OrderIndex = orderIndex;
OrderPrefab = orderPrefab;
OrderIdentifier = orderIdentifier;
OrderOption = orderOption;
OrderOptionIndex = orderOptionIndex;
TargetCharacter = targetCharacter;
@@ -148,21 +142,20 @@ namespace Barotrauma.Networking
public static OrderMessageInfo ReadOrder(IReadMessage msg)
{
int orderIndex = msg.ReadByte();
Identifier orderIdentifier = msg.ReadIdentifier();
ushort targetCharacterId = msg.ReadUInt16();
Character targetCharacter = targetCharacterId != Entity.NullEntityID ? Entity.FindEntityByID(targetCharacterId) as Character : null;
ushort targetEntityId = msg.ReadUInt16();
Entity targetEntity = targetEntityId != Entity.NullEntityID ? Entity.FindEntityByID(targetEntityId) : null;
Order orderPrefab = null;
int? optionIndex = null;
string orderOption = null;
Identifier orderOption = Identifier.Empty;
// 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 (orderIndex >= 0 && orderIndex < Order.PrefabList.Count)
if (orderIdentifier != Identifier.Empty)
{
orderPrefab = Order.PrefabList[orderIndex];
if (orderPrefab.Identifier != "dismissed")
var orderPrefab = OrderPrefab.Prefabs[orderIdentifier];
if (!orderPrefab.IsDismissal)
{
optionIndex = msg.ReadByte();
}
@@ -172,11 +165,11 @@ namespace Barotrauma.Networking
int identifierCount = msg.ReadByte();
if (identifierCount > 0)
{
int dismissedOrderIndex = msg.ReadByte();
Order dismissedOrderPrefab = null;
if (dismissedOrderIndex >= 0 && dismissedOrderIndex < Order.PrefabList.Count)
Identifier dismissedOrderIdentifier = msg.ReadIdentifier();
OrderPrefab dismissedOrderPrefab = null;
if (dismissedOrderIdentifier != Identifier.Empty)
{
dismissedOrderPrefab = Order.PrefabList[dismissedOrderIndex];
dismissedOrderPrefab = OrderPrefab.Prefabs[dismissedOrderIdentifier];
orderOption = dismissedOrderPrefab.Identifier;
}
if (identifierCount > 1)
@@ -187,7 +180,7 @@ namespace Barotrauma.Networking
var options = dismissedOrderPrefab.Options;
if (options != null && dismissedOrderOptionIndex >= 0 && dismissedOrderOptionIndex < options.Length)
{
orderOption += $".{options[dismissedOrderOptionIndex]}";
orderOption = $"{orderOption.Value}.{options[dismissedOrderOptionIndex]}".ToIdentifier();
}
}
}
@@ -217,9 +210,8 @@ namespace Barotrauma.Networking
}
bool isNewOrder = msg.ReadBoolean();
return new OrderMessageInfo(orderIndex, orderPrefab, orderOption, optionIndex, targetCharacter,
orderTargetType, targetEntity, orderTargetPosition, wallSectionIndex, orderPriority, isNewOrder);
return new OrderMessageInfo(orderIdentifier, orderOption, optionIndex, targetCharacter,
orderTargetType, targetEntity, orderTargetPosition, wallSectionIndex, orderPriority, isNewOrder);
}
}
}
@@ -19,6 +19,7 @@ namespace Barotrauma.Networking
Double ReadDouble();
UInt32 ReadVariableUInt32();
String ReadString();
Identifier ReadIdentifier();
Microsoft.Xna.Framework.Color ReadColorR8G8B8();
Microsoft.Xna.Framework.Color ReadColorR8G8B8A8();
int ReadRangedInteger(int min, int max);
@@ -19,11 +19,12 @@ namespace Barotrauma.Networking
void WriteColorR8G8B8A8(Microsoft.Xna.Framework.Color val);
void WriteVariableUInt32(UInt32 val);
void Write(string val);
void Write(Identifier val);
void WriteRangedInteger(int val, int min, int max);
void WriteRangedSingle(Single val, Single min, Single max, int bitCount);
void Write(byte[] val, int startIndex, int length);
void PrepareForSending(ref byte[] outBuf, out bool isCompressed, out int outLength);
void PrepareForSending(ref byte[] outBuf, bool compressPastThreshold, out bool isCompressed, out int outLength);
int BitPosition { get; set; }
int BytePosition { get; }
@@ -454,6 +454,7 @@ namespace Barotrauma.Networking
{
lengthBits = value;
seekPos = seekPos > lengthBits ? lengthBits : seekPos;
MsgWriter.EnsureBufferSize(ref buf, lengthBits);
}
}
@@ -540,6 +541,11 @@ namespace Barotrauma.Networking
MsgWriter.Write(ref buf, ref seekPos, val);
}
public void Write(Identifier val)
{
Write(val.Value);
}
public void WriteRangedInteger(int val, int min, int max)
{
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, val, min, max);
@@ -555,9 +561,9 @@ namespace Barotrauma.Networking
MsgWriter.WriteBytes(ref buf, ref seekPos, val, startPos, length);
}
public void PrepareForSending(ref byte[] outBuf, out bool isCompressed, out int length)
public void PrepareForSending(ref byte[] outBuf, bool compressPastThreshold, out bool isCompressed, out int length)
{
if (LengthBytes <= MsgConstants.CompressionThreshold)
if (LengthBytes <= MsgConstants.CompressionThreshold || !compressPastThreshold)
{
isCompressed = false;
if (LengthBytes > outBuf.Length) { Array.Resize(ref outBuf, LengthBytes); }
@@ -764,6 +770,11 @@ namespace Barotrauma.Networking
return MsgReader.ReadString(buf, ref seekPos);
}
public Identifier ReadIdentifier()
{
return ReadString().ToIdentifier();
}
public Color ReadColorR8G8B8()
{
return MsgReader.ReadColorR8G8B8(buf, ref seekPos);
@@ -773,7 +784,6 @@ namespace Barotrauma.Networking
{
return MsgReader.ReadColorR8G8B8A8(buf, ref seekPos);
}
public int ReadRangedInteger(int min, int max)
{
@@ -938,6 +948,10 @@ namespace Barotrauma.Networking
MsgWriter.Write(ref buf, ref seekPos, val);
}
public void Write(Identifier val)
{
Write(val.Value);
}
public void WriteRangedInteger(int val, int min, int max)
{
@@ -1019,6 +1033,11 @@ namespace Barotrauma.Networking
return MsgReader.ReadString(buf, ref seekPos);
}
public Identifier ReadIdentifier()
{
return ReadString().ToIdentifier();
}
public Color ReadColorR8G8B8()
{
return MsgReader.ReadColorR8G8B8(buf, ref seekPos);
@@ -1044,7 +1063,7 @@ namespace Barotrauma.Networking
return MsgReader.ReadBytes(buf, ref seekPos, numberOfBytes);
}
public void PrepareForSending(ref byte[] outBuf, out bool isCompressed, out int outLength)
public void PrepareForSending(ref byte[] outBuf, bool compressPastThreshold, out bool isCompressed, out int outLength)
{
throw new InvalidOperationException("ReadWriteMessages are not to be sent");
}
@@ -33,7 +33,7 @@ namespace Barotrauma.Networking
protected set;
}
public string Language
public LanguageIdentifier Language
{
get; set;
}
@@ -236,7 +236,7 @@ namespace Barotrauma.Networking
//remove respawn items that have been left in the shuttle
if (respawnItems.Contains(item))
{
Spawner.AddToRemoveQueue(item);
Spawner.AddItemToRemoveQueue(item);
continue;
}
@@ -272,7 +272,7 @@ namespace Barotrauma.Networking
}
}
foreach (Hull hull in Hull.hullList)
foreach (Hull hull in Hull.HullList)
{
if (hull.Submarine != RespawnShuttle) { continue; }
hull.OxygenPercentage = 100.0f;
@@ -295,12 +295,12 @@ namespace Barotrauma.Networking
c.Kill(CauseOfDeathType.Unknown, null, true);
c.Enabled = false;
Spawner.AddToRemoveQueue(c);
Spawner.AddEntityToRemoveQueue(c);
if (c.Inventory != null)
{
foreach (Item item in c.Inventory.AllItems)
{
Spawner.AddToRemoveQueue(item);
Spawner.AddItemToRemoveQueue(item);
}
}
}
@@ -322,7 +322,7 @@ namespace Barotrauma.Networking
public static Affliction GetRespawnPenaltyAffliction()
{
var respawnPenaltyAffliction = AfflictionPrefab.List.FirstOrDefault(a => a.AfflictionType.Equals("respawnpenalty", StringComparison.OrdinalIgnoreCase));
var respawnPenaltyAffliction = AfflictionPrefab.Prefabs.First(a => a.AfflictionType == "respawnpenalty");
return respawnPenaltyAffliction?.Instantiate(10.0f);
}
@@ -10,23 +10,20 @@ namespace Barotrauma.Networking
{
private struct LogMessage
{
public readonly string Text;
public readonly string SanitizedText;
public readonly RichString Text;
public readonly MessageType Type;
public readonly List<RichTextData> RichData;
public LogMessage(string text, MessageType type)
{
if (type.HasFlag(MessageType.Chat))
{
Text = $"[{DateTime.Now}]\n {text}";
text = $"[{DateTime.Now}]\n {text}";
}
else
{
Text = $"[{DateTime.Now}]\n {TextManager.GetServerMessage(text)}";
text = $"[{DateTime.Now}]\n {TextManager.GetServerMessage(text)}";
}
RichData = RichTextData.GetRichTextData(Text, out SanitizedText);
Text = RichString.Rich(text);
Type = type;
}
}
@@ -113,7 +110,7 @@ namespace Barotrauma.Networking
var newText = new LogMessage(line, messageType);
#if SERVER
DebugConsole.NewMessage(newText.SanitizedText, messageColor[messageType]); //TODO: REMOVE
DebugConsole.NewMessage(newText.Text.SanitizedValue, messageColor[messageType]); //TODO: REMOVE
#endif
lines.Enqueue(newText);
@@ -173,7 +170,7 @@ namespace Barotrauma.Networking
try
{
File.WriteAllLines(filePath, unsavedLines.Select(l => l.SanitizedText));
File.WriteAllLines(filePath, unsavedLines.Select(l => l.Text.SanitizedValue));
}
catch (Exception e)
{
@@ -97,11 +97,8 @@ namespace Barotrauma.Networking
private readonly SerializableProperty property;
private readonly string typeString;
private readonly object parentObject;
public string Name
{
get { return property.Name; }
}
public Identifier Name => property.Name.ToIdentifier();
public object Value
{
@@ -266,7 +263,7 @@ namespace Barotrauma.Networking
}
};
public Dictionary<string, SerializableProperty> SerializableProperties
public Dictionary<Identifier, SerializableProperty> SerializableProperties
{
get;
private set;
@@ -313,7 +310,7 @@ namespace Barotrauma.Networking
if (typeName != null || property.PropertyType.IsEnum)
{
NetPropertyData netPropertyData = new NetPropertyData(this, property, typeName);
UInt32 key = ToolBox.StringToUInt32Hash(property.Name, md5);
UInt32 key = ToolBox.IdentifierToUint32Hash(netPropertyData.Name, md5);
if (key == 0) { key++; } //0 is reserved to indicate the end of the netproperties section of a message
if (netProperties.ContainsKey(key)){ throw new Exception("Hashing collision in ServerSettings.netProperties: " + netProperties[key] + " has same key as " + property.Name + " (" + key.ToString() + ")"); }
netProperties.Add(key, netPropertyData);
@@ -330,7 +327,7 @@ namespace Barotrauma.Networking
if (typeName != null || property.PropertyType.IsEnum)
{
NetPropertyData netPropertyData = new NetPropertyData(networkMember.KarmaManager, property, typeName);
UInt32 key = ToolBox.StringToUInt32Hash(property.Name, md5);
UInt32 key = ToolBox.IdentifierToUint32Hash(netPropertyData.Name, md5);
if (netProperties.ContainsKey(key)) { throw new Exception("Hashing collision in ServerSettings.netProperties: " + netProperties[key] + " has same key as " + property.Name + " (" + key.ToString() + ")"); }
netProperties.Add(key, netPropertyData);
}
@@ -382,7 +379,7 @@ namespace Barotrauma.Networking
public Voting Voting;
public Dictionary<string, bool> MonsterEnabled { get; private set; }
public Dictionary<Identifier, bool> MonsterEnabled { get; private set; }
public const int MaxExtraCargoItemsOfType = 10;
public const int MaxExtraCargoItemTypes = 20;
@@ -405,63 +402,63 @@ namespace Barotrauma.Networking
public WhiteList Whitelist { get; private set; }
[Serialize(20, true)]
[Serialize(20, IsPropertySaveable.Yes)]
public int TickRate
{
get;
set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool RandomizeSeed
{
get;
set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool UseRespawnShuttle
{
get;
private set;
}
[Serialize(300.0f, true)]
[Serialize(300.0f, IsPropertySaveable.Yes)]
public float RespawnInterval
{
get;
private set;
}
[Serialize(180.0f, true)]
[Serialize(180.0f, IsPropertySaveable.Yes)]
public float MaxTransportTime
{
get;
private set;
}
[Serialize(0.2f, true)]
[Serialize(0.2f, IsPropertySaveable.Yes)]
public float MinRespawnRatio
{
get;
private set;
}
[Serialize(60.0f, true)]
[Serialize(60.0f, IsPropertySaveable.Yes)]
public float AutoRestartInterval
{
get;
set;
}
[Serialize(false, true)]
[Serialize(false, IsPropertySaveable.Yes)]
public bool StartWhenClientsReady
{
get;
set;
}
[Serialize(0.8f, true)]
[Serialize(0.8f, IsPropertySaveable.Yes)]
public float StartWhenClientsReadyRatio
{
get;
@@ -469,7 +466,7 @@ namespace Barotrauma.Networking
}
private bool allowSpectating;
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowSpectating
{
get { return allowSpectating; }
@@ -481,21 +478,28 @@ namespace Barotrauma.Networking
}
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool SaveServerLogs
{
get;
private set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowModDownloads
{
get;
private set;
} = true;
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowRagdollButton
{
get;
set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowFileTransfers
{
get;
@@ -503,7 +507,7 @@ namespace Barotrauma.Networking
}
private bool voiceChatEnabled;
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool VoiceChatEnabled
{
get { return voiceChatEnabled; }
@@ -516,7 +520,7 @@ namespace Barotrauma.Networking
}
private PlayStyle playstyleSelection;
[Serialize(PlayStyle.Casual, true)]
[Serialize(PlayStyle.Casual, IsPropertySaveable.Yes)]
public PlayStyle PlayStyle
{
get { return playstyleSelection; }
@@ -527,14 +531,14 @@ namespace Barotrauma.Networking
}
}
[Serialize(Barotrauma.LosMode.Opaque, true)]
[Serialize(Barotrauma.LosMode.Opaque, IsPropertySaveable.Yes)]
public LosMode LosMode
{
get;
set;
}
[Serialize(800, true)]
[Serialize(800, IsPropertySaveable.Yes)]
public int LinesPerLogFile
{
get
@@ -569,7 +573,7 @@ namespace Barotrauma.Networking
#endif
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowVoteKick
{
get
@@ -582,7 +586,7 @@ namespace Barotrauma.Networking
}
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowEndVoting
{
get
@@ -596,7 +600,7 @@ namespace Barotrauma.Networking
}
private bool allowRespawn;
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowRespawn
{
get { return allowRespawn; ; }
@@ -608,28 +612,28 @@ namespace Barotrauma.Networking
}
}
[Serialize(0, true)]
[Serialize(0, IsPropertySaveable.Yes)]
public int BotCount
{
get;
set;
}
[Serialize(16, true)]
[Serialize(16, IsPropertySaveable.Yes)]
public int MaxBotCount
{
get;
set;
}
[Serialize(BotSpawnMode.Normal, true)]
[Serialize(BotSpawnMode.Normal, IsPropertySaveable.Yes)]
public BotSpawnMode BotSpawnMode
{
get;
set;
}
[Serialize(false, true)]
[Serialize(false, IsPropertySaveable.Yes)]
public bool DisableBotConversations
{
get;
@@ -642,76 +646,76 @@ namespace Barotrauma.Networking
set { selectedLevelDifficulty = MathHelper.Clamp(value, 0.0f, 100.0f); }
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowDisguises
{
get;
set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowRewiring
{
get;
set;
}
[Serialize(false, true)]
[Serialize(false, IsPropertySaveable.Yes)]
public bool LockAllDefaultWires
{
get;
set;
}
[Serialize(false, true)]
[Serialize(false, IsPropertySaveable.Yes)]
public bool AllowLinkingWifiToChat
{
get;
set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool AllowFriendlyFire
{
get;
set;
}
[Serialize(false, true)]
[Serialize(false, IsPropertySaveable.Yes)]
public bool DestructibleOutposts
{
get;
set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool KillableNPCs
{
get;
set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool BanAfterWrongPassword
{
get;
set;
}
[Serialize(3, true)]
[Serialize(3, IsPropertySaveable.Yes)]
public int MaxPasswordRetriesBeforeBan
{
get;
private set;
}
[Serialize("", true)]
[Serialize("", IsPropertySaveable.Yes)]
public string SelectedSubmarine
{
get;
set;
}
[Serialize("", true)]
[Serialize("", IsPropertySaveable.Yes)]
public string SelectedShuttle
{
get;
@@ -719,7 +723,7 @@ namespace Barotrauma.Networking
}
private YesNoMaybe traitorsEnabled;
[Serialize(YesNoMaybe.No, true)]
[Serialize(YesNoMaybe.No, IsPropertySaveable.Yes)]
public YesNoMaybe TraitorsEnabled
{
get { return traitorsEnabled; }
@@ -731,35 +735,35 @@ namespace Barotrauma.Networking
}
}
[Serialize(defaultValue: 1, isSaveable: true)]
[Serialize(defaultValue: 1, isSaveable: IsPropertySaveable.Yes)]
public int TraitorsMinPlayerCount
{
get;
set;
}
[Serialize(defaultValue: 90.0f, isSaveable: true)]
[Serialize(defaultValue: 90.0f, isSaveable: IsPropertySaveable.Yes)]
public float TraitorsMinStartDelay
{
get;
set;
}
[Serialize(defaultValue: 180.0f, isSaveable: true)]
[Serialize(defaultValue: 180.0f, isSaveable: IsPropertySaveable.Yes)]
public float TraitorsMaxStartDelay
{
get;
set;
}
[Serialize(defaultValue: 30.0f, isSaveable: true)]
[Serialize(defaultValue: 30.0f, isSaveable: IsPropertySaveable.Yes)]
public float TraitorsMinRestartDelay
{
get;
set;
}
[Serialize(defaultValue: 90.0f, isSaveable: true)]
[Serialize(defaultValue: 90.0f, isSaveable: IsPropertySaveable.Yes)]
public float TraitorsMaxRestartDelay
{
get;
@@ -767,7 +771,7 @@ namespace Barotrauma.Networking
}
private SelectionMode subSelectionMode;
[Serialize(SelectionMode.Manual, true)]
[Serialize(SelectionMode.Manual, IsPropertySaveable.Yes)]
public SelectionMode SubSelectionMode
{
get { return subSelectionMode; }
@@ -780,7 +784,7 @@ namespace Barotrauma.Networking
}
private SelectionMode modeSelectionMode;
[Serialize(SelectionMode.Manual, true)]
[Serialize(SelectionMode.Manual, IsPropertySaveable.Yes)]
public SelectionMode ModeSelectionMode
{
get { return modeSelectionMode; }
@@ -794,42 +798,42 @@ namespace Barotrauma.Networking
public BanList BanList { get; private set; }
[Serialize(0.6f, true)]
[Serialize(0.6f, IsPropertySaveable.Yes)]
public float EndVoteRequiredRatio
{
get;
private set;
}
[Serialize(0.6f, true)]
[Serialize(0.6f, IsPropertySaveable.Yes)]
public float SubmarineVoteRequiredRatio
{
get;
private set;
}
[Serialize(30f, true)]
[Serialize(30f, IsPropertySaveable.Yes)]
public float SubmarineVoteTimeout
{
get;
private set;
}
[Serialize(0.6f, true)]
[Serialize(0.6f, IsPropertySaveable.Yes)]
public float KickVoteRequiredRatio
{
get;
private set;
}
[Serialize(300.0f, true)]
[Serialize(300.0f, IsPropertySaveable.Yes)]
public float KillDisconnectedTime
{
get;
private set;
}
[Serialize(600.0f, true)]
[Serialize(600.0f, IsPropertySaveable.Yes)]
public float KickAFKTime
{
get;
@@ -837,7 +841,7 @@ namespace Barotrauma.Networking
}
private bool karmaEnabled;
[Serialize(false, true)]
[Serialize(false, IsPropertySaveable.Yes)]
public bool KarmaEnabled
{
get { return karmaEnabled; }
@@ -851,7 +855,7 @@ namespace Barotrauma.Networking
}
private string karmaPreset = "default";
[Serialize("default", true)]
[Serialize("default", IsPropertySaveable.Yes)]
public string KarmaPreset
{
get { return karmaPreset; }
@@ -866,21 +870,21 @@ namespace Barotrauma.Networking
}
}
[Serialize("sandbox", true)]
public string GameModeIdentifier
[Serialize("sandbox", IsPropertySaveable.Yes)]
public Identifier GameModeIdentifier
{
get;
set;
}
[Serialize("All", true)]
[Serialize("All", IsPropertySaveable.Yes)]
public string MissionType
{
get;
set;
}
[Serialize(8, true)]
[Serialize(8, IsPropertySaveable.Yes)]
public int MaxPlayers
{
get { return maxPlayers; }
@@ -893,21 +897,21 @@ namespace Barotrauma.Networking
set;
}
[Serialize(60f * 60.0f, true)]
[Serialize(60f * 60.0f, IsPropertySaveable.Yes)]
public float AutoBanTime
{
get;
private set;
}
[Serialize(60.0f * 60.0f * 24.0f, true)]
[Serialize(60.0f * 60.0f * 24.0f, IsPropertySaveable.Yes)]
public float MaxAutoBanTime
{
get;
private set;
}
[Serialize(true, true)]
[Serialize(true, IsPropertySaveable.Yes)]
public bool RadiationEnabled
{
get;
@@ -916,7 +920,7 @@ namespace Barotrauma.Networking
private int maxMissionCount = CampaignSettings.DefaultMaxMissionCount;
[Serialize(CampaignSettings.DefaultMaxMissionCount, true)]
[Serialize(CampaignSettings.DefaultMaxMissionCount, IsPropertySaveable.Yes)]
public int MaxMissionCount
{
get { return maxMissionCount; }
@@ -962,45 +966,40 @@ namespace Barotrauma.Networking
/// <summary>
/// A list of int pairs that represent the ranges of UTF-16 codes allowed in client names
/// </summary>
public List<Pair<int, int>> AllowedClientNameChars
public List<Range<int>> AllowedClientNameChars
{
get;
private set;
} = new List<Pair<int, int>>();
} = new List<Range<int>>();
private void InitMonstersEnabled()
{
//monster spawn settings
if (MonsterEnabled == null)
{
List<string> monsterNames1 = CharacterPrefab.Prefabs.Select(p => p.Identifier).ToList();
MonsterEnabled = new Dictionary<string, bool>();
foreach (string s in monsterNames1)
{
if (!MonsterEnabled.ContainsKey(s)) MonsterEnabled.Add(s, true);
}
}
MonsterEnabled ??= CharacterPrefab.Prefabs.Select(p => (p.Identifier, true)).ToDictionary();
}
public void ReadMonsterEnabled(IReadMessage inc)
{
InitMonstersEnabled();
List<string> monsterNames = MonsterEnabled.Keys.ToList();
foreach (string s in monsterNames)
List<Identifier> monsterNames = MonsterEnabled.Keys
.OrderBy(k => CharacterPrefab.Prefabs[k].UintIdentifier)
.ToList();
foreach (Identifier s in monsterNames)
{
MonsterEnabled[s] = inc.ReadBoolean();
}
inc.ReadPadBits();
}
public void WriteMonsterEnabled(IWriteMessage msg, Dictionary<string, bool> monsterEnabled = null)
public void WriteMonsterEnabled(IWriteMessage msg, Dictionary<Identifier, bool> monsterEnabled = null)
{
//monster spawn settings
if (monsterEnabled == null) monsterEnabled = MonsterEnabled;
if (monsterEnabled == null) { monsterEnabled = MonsterEnabled; }
List<string> monsterNames = monsterEnabled.Keys.ToList();
foreach (string s in monsterNames)
List<Identifier> monsterNames = monsterEnabled.Keys
.OrderBy(k => CharacterPrefab.Prefabs[k].UintIdentifier)
.ToList();
foreach (Identifier s in monsterNames)
{
msg.Write(monsterEnabled[s]);
}
@@ -1015,7 +1014,7 @@ namespace Barotrauma.Networking
Dictionary<ItemPrefab, int> extraCargo = new Dictionary<ItemPrefab, int>();
for (int i = 0; i < count; i++)
{
string prefabIdentifier = msg.ReadString();
Identifier prefabIdentifier = msg.ReadIdentifier();
byte amount = msg.ReadByte();
if (MapEntityPrefab.Find(null, prefabIdentifier, showErrorMessages: false) is ItemPrefab itemPrefab && amount > 0)
@@ -1041,7 +1040,7 @@ namespace Barotrauma.Networking
msg.Write((UInt32)ExtraCargo.Count);
foreach (KeyValuePair<ItemPrefab, int> kvp in ExtraCargo)
{
msg.Write(kvp.Key.Identifier ?? "");
msg.Write(kvp.Key.Identifier);
msg.Write((byte)kvp.Value);
}
}
@@ -1,296 +0,0 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
#if USE_STEAM
namespace Barotrauma.Steam
{
static partial class SteamManager
{
public const int STEAMP2P_OWNER_PORT = 30000;
public const uint AppID = 602960;
private static readonly List<string> initializationErrors = new List<string>();
public static IEnumerable<string> InitializationErrors
{
get { return initializationErrors; }
}
public const string MetadataFileName = "filelist.xml";
public const string CopyIndicatorFileName = ".copying";
private static readonly Dictionary<string, int> tagCommonness = new Dictionary<string, int>()
{
{ "submarine", 10 },
{ "item", 10 },
{ "monster", 8 },
{ "art", 8 },
{ "mission", 8 },
{ "event set", 8 },
{ "total conversion", 5 },
{ "environment", 5 },
{ "item assembly", 5 },
{ "language", 5 }
};
private static readonly List<string> popularTags = new List<string>();
public static IEnumerable<string> PopularTags
{
get
{
if (!isInitialized) { return Enumerable.Empty<string>(); }
return popularTags;
}
}
private static bool isInitialized;
public static bool IsInitialized => isInitialized;
public static void Initialize()
{
InitializeProjectSpecific();
}
public static ulong GetSteamID()
{
if (!isInitialized || !Steamworks.SteamClient.IsValid)
{
return 0;
}
return Steamworks.SteamClient.SteamId;
}
public static string GetUsername()
{
if (!isInitialized || !Steamworks.SteamClient.IsValid)
{
return "";
}
return Steamworks.SteamClient.Name;
}
private static Steamworks.AuthTicket currentTicket = null;
public static Steamworks.AuthTicket GetAuthSessionTicket()
{
if (!isInitialized)
{
return null;
}
currentTicket?.Cancel();
currentTicket = Steamworks.SteamUser.GetAuthSessionTicket();
return currentTicket;
}
public static bool OverlayCustomURL(string url)
{
if (!isInitialized || !Steamworks.SteamClient.IsValid)
{
return false;
}
Steamworks.SteamFriends.OpenWebOverlay(url);
return true;
}
public static bool UnlockAchievement(string achievementIdentifier)
{
if (!isInitialized || !Steamworks.SteamClient.IsValid)
{
return false;
}
DebugConsole.Log("Unlocked achievement \"" + achievementIdentifier + "\"");
var achievements = Steamworks.SteamUserStats.Achievements.ToList();
int achIndex = achievements.FindIndex(ach => ach.Identifier == achievementIdentifier);
bool unlocked = achIndex >= 0 ? achievements[achIndex].Trigger() : false;
if (!unlocked)
{
//can be caused by an incorrect identifier, but also happens during normal gameplay:
//SteamAchievementManager tries to unlock achievements that may or may not exist
//(discovered[whateverbiomewasentered], kill[withwhateveritem], kill[somemonster] etc) so that we can add
//some types of new achievements without the need for client-side changes.
#if DEBUG
DebugConsole.NewMessage("Failed to unlock achievement \"" + achievementIdentifier + "\".");
#endif
}
return unlocked;
}
public static bool IncrementStat(string statName, int increment)
{
if (!isInitialized || !Steamworks.SteamClient.IsValid) { return false; }
DebugConsole.Log("Incremented stat \"" + statName + "\" by " + increment);
bool success = Steamworks.SteamUserStats.AddStat(statName, increment);
if (!success)
{
#if DEBUG
DebugConsole.NewMessage("Failed to increment stat \"" + statName + "\".");
#endif
}
else
{
StoreStats();
}
return success;
}
public static bool IncrementStat(string statName, float increment)
{
if (!isInitialized || !Steamworks.SteamClient.IsValid) { return false; }
DebugConsole.Log("Incremented stat \"" + statName + "\" by " + increment);
bool success = Steamworks.SteamUserStats.AddStat(statName, increment);
if (!success)
{
#if DEBUG
DebugConsole.NewMessage("Failed to increment stat \"" + statName + "\".");
#endif
}
else
{
StoreStats();
}
return success;
}
public static int GetStatInt(string statName)
{
if (!isInitialized || !Steamworks.SteamClient.IsValid) { return 0; }
return Steamworks.SteamUserStats.GetStatInt(statName);
}
public static bool StoreStats()
{
if (!isInitialized || !Steamworks.SteamClient.IsValid) { return false; }
DebugConsole.Log("Storing Steam stats...");
bool success = Steamworks.SteamUserStats.StoreStats();
if (!success)
{
#if DEBUG
DebugConsole.NewMessage("Failed to store Steam stats.");
#endif
}
return success;
}
public static bool TryGetUnlockedAchievements(out List<Steamworks.Data.Achievement> achievements)
{
if (!isInitialized || !Steamworks.SteamClient.IsValid)
{
achievements = null;
return false;
}
achievements = Steamworks.SteamUserStats.Achievements.Where(a => a.State).ToList();
return true;
}
public static void Update(float deltaTime)
{
if (!isInitialized) { return; }
if (Steamworks.SteamClient.IsValid) { Steamworks.SteamClient.RunCallbacks(); }
if (Steamworks.SteamServer.IsValid) { Steamworks.SteamServer.RunCallbacks(); }
SteamAchievementManager.Update(deltaTime);
}
public static void ShutDown()
{
if (!isInitialized) { return; }
if (Steamworks.SteamClient.IsValid) { Steamworks.SteamClient.Shutdown(); }
if (Steamworks.SteamServer.IsValid) { Steamworks.SteamServer.Shutdown(); }
isInitialized = false;
}
public static IEnumerable<ulong> ParseWorkshopIds(string workshopIdData)
{
string[] workshopIds = workshopIdData.Split(',');
foreach (string id in workshopIds)
{
if (ulong.TryParse(id, out ulong idCast))
{
yield return idCast;
}
else
{
yield return 0;
}
}
}
public static IEnumerable<ulong> WorkshopUrlsToIds(IEnumerable<string> urls)
{
return urls.Select((u) =>
{
if (string.IsNullOrEmpty(u))
{
return (ulong)0;
}
else
{
return GetWorkshopItemIDFromUrl(u);
}
});
}
public static ulong GetWorkshopItemIDFromUrl(string url)
{
try
{
Uri uri = new Uri(url);
string idStr = HttpUtility.ParseQueryString(uri.Query)["id"];
if (ulong.TryParse(idStr, out ulong id))
{
return id;
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to get Workshop item ID from the url \"" + url + "\"!", e);
}
return 0;
}
public static UInt64 SteamIDStringToUInt64(string str)
{
if (string.IsNullOrWhiteSpace(str)) { return 0; }
UInt64 retVal;
if (str.StartsWith("STEAM64_", StringComparison.InvariantCultureIgnoreCase)) { str = str.Substring(8); }
if (UInt64.TryParse(str, out retVal) && retVal >(1<<52)) { return retVal; }
if (!str.StartsWith("STEAM_", StringComparison.InvariantCultureIgnoreCase)) { return 0; }
string[] split = str.Substring(6).Split(':');
if (split.Length != 3) { return 0; }
if (!UInt64.TryParse(split[0], out UInt64 universe)) { return 0; }
if (!UInt64.TryParse(split[1], out UInt64 y)) { return 0; }
if (!UInt64.TryParse(split[2], out UInt64 accountNumber)) { return 0; }
UInt64 accountInstance = 1; UInt64 accountType = 1;
return (universe << 56) | (accountType << 52) | (accountInstance << 32) | (accountNumber << 1) | y;
}
public static string SteamIDUInt64ToString(UInt64 uint64)
{
UInt64 y = uint64 & 0x1;
UInt64 accountNumber = (uint64 >> 1) & 0x7fffffff;
UInt64 universe = (uint64 >> 56) & 0xff;
string retVal = "STEAM_" + universe.ToString() + ":" + y.ToString() + ":" + accountNumber.ToString();
if (SteamIDStringToUInt64(retVal) != uint64) { return "STEAM64_" + uint64.ToString(); }
return retVal;
}
}
}
#endif