Unstable 0.17.1.0

This commit is contained in:
Markus Isberg
2022-03-17 01:25:04 +09:00
parent 3974067915
commit 6d410cc1b7
302 changed files with 5878 additions and 3317 deletions
@@ -7,6 +7,7 @@ using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using Barotrauma.Networking;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
@@ -58,7 +59,9 @@ namespace Barotrauma.MapCreatures.Behavior
public float AccumulatedDamage;
public float DamageVisualizationTimer;
#if CLIENT
public Vector2 ShakeAmount;
#endif
// Adjacent tiles, used to free up sides when this branch gets removed
public readonly Dictionary<TileSide, BallastFloraBranch> Connections = new Dictionary<TileSide, BallastFloraBranch>();
@@ -286,7 +289,7 @@ namespace Barotrauma.MapCreatures.Behavior
public float PowerConsumptionTimer;
private float defenseCooldown, toxinsCooldown, fireCheckCooldown;
private float selfDamageTimer, toxinsTimer;
private float selfDamageTimer, toxinsTimer, toxinsSpawnTimer;
private readonly List<BallastFloraBranch> branchesVulnerableToFire = new List<BallastFloraBranch>();
@@ -552,11 +555,12 @@ namespace Barotrauma.MapCreatures.Behavior
Anger -= deltaTime;
}
// This entire scope is probably very heavy for GC, need to experiment
if (toxinsTimer > 0.1f)
{
if (!AttackItemPrefab.IsEmpty)
toxinsSpawnTimer -= deltaTime;
if (!AttackItemPrefab.IsEmpty && toxinsSpawnTimer <= 0.0f)
{
toxinsSpawnTimer = 1.0f;
Dictionary<Hull, List<BallastFloraBranch>> branches = new Dictionary<Hull, List<BallastFloraBranch>>();
foreach (BallastFloraBranch branch in Branches)
{
@@ -581,7 +585,7 @@ namespace Barotrauma.MapCreatures.Behavior
randomBranch.SpawningItem = true;
ItemPrefab prefab = ItemPrefab.Find(null, AttackItemPrefab);
#warning TODO: Parent needs a nullability sanity check
#warning TODO: Parent needs a nullability sanity check
Entity.Spawner?.AddItemToSpawnQueue(prefab, Parent!.Position + Offset + randomBranch.Position, Parent.Submarine, onSpawned: item =>
{
randomBranch.AttackItem = item;
@@ -826,13 +830,13 @@ namespace Barotrauma.MapCreatures.Behavior
{
if (root != null)
{
Vector2 rootGrowthPos = Rand.Vector(rootGrowthCount * Rand.Range(3.0f, 5.0f));
Vector2 rootGrowthPos = Rand.Vector(Math.Max(rootGrowthCount, 1) * Rand.Range(3.0f, 5.0f));
TryGrowBranch(root, TileSide.None, out List<BallastFloraBranch> newRootGrowth, isRootGrowth: true, forcePosition: rootGrowthPos);
}
}
#if SERVER
SendNetworkMessage(this, NetworkHeader.BranchCreate, newBranch, parent.ID);
SendNetworkMessage(new BranchCreateEventData(newBranch, parent));
#endif
return true;
}
@@ -874,7 +878,7 @@ namespace Barotrauma.MapCreatures.Behavior
#if SERVER
if (!load)
{
SendNetworkMessage(this, NetworkHeader.Infect, target.ID, true, branch);
SendNetworkMessage(new InfectEventData(target, InfectEventData.InfectState.Yes, branch));
}
#endif
}
@@ -1002,8 +1006,10 @@ namespace Barotrauma.MapCreatures.Behavior
StateMachine.EnterState(new DefendWithPumpState(branch, ClaimedTargets, attacker));
defenseCooldown = 180f;
}
defenseCooldown = 10f;
else
{
defenseCooldown = 10f;
}
}
}
@@ -1104,7 +1110,7 @@ namespace Barotrauma.MapCreatures.Behavior
#if SERVER
if (!wasRemoved)
{
SendNetworkMessage(this, NetworkHeader.BranchRemove, branch);
SendNetworkMessage(new BranchRemoveEventData(branch));
}
#endif
}
@@ -1135,7 +1141,7 @@ namespace Barotrauma.MapCreatures.Behavior
}
});
#if SERVER
SendNetworkMessage(this, NetworkHeader.Infect, item.ID, false);
SendNetworkMessage(new InfectEventData(item, InfectEventData.InfectState.No, null));
#endif
}
@@ -1153,7 +1159,7 @@ namespace Barotrauma.MapCreatures.Behavior
StateMachine?.State?.Exit();
#if SERVER
SendNetworkMessage(this, NetworkHeader.Kill);
SendNetworkMessage(new KillEventData());
#endif
}
@@ -1175,7 +1181,7 @@ namespace Barotrauma.MapCreatures.Behavior
_entityList.Remove(this);
#if SERVER
SendNetworkMessage(this, NetworkHeader.Remove);
SendNetworkMessage(new KillEventData());
#endif
}
@@ -0,0 +1,74 @@
using Barotrauma.Networking;
namespace Barotrauma.MapCreatures.Behavior
{
internal partial class BallastFloraBehavior
{
public interface IEventData : NetEntityEvent.IData
{
public NetworkHeader NetworkHeader { get; }
}
public readonly struct SpawnEventData : IEventData
{
public NetworkHeader NetworkHeader => NetworkHeader.Spawn;
}
private readonly struct KillEventData : IEventData
{
public NetworkHeader NetworkHeader => NetworkHeader.Kill;
}
private readonly struct BranchCreateEventData : IEventData
{
public NetworkHeader NetworkHeader => NetworkHeader.BranchCreate;
public readonly BallastFloraBranch NewBranch;
public readonly BallastFloraBranch Parent;
public BranchCreateEventData(BallastFloraBranch newBranch, BallastFloraBranch parent)
{
NewBranch = newBranch;
Parent = parent;
}
}
private readonly struct BranchRemoveEventData : IEventData
{
public NetworkHeader NetworkHeader => NetworkHeader.BranchRemove;
public readonly BallastFloraBranch Branch;
public BranchRemoveEventData(BallastFloraBranch branch)
{
Branch = branch;
}
}
private readonly struct BranchDamageEventData : IEventData
{
public NetworkHeader NetworkHeader => NetworkHeader.BranchDamage;
public readonly BallastFloraBranch Branch;
public BranchDamageEventData(BallastFloraBranch branch)
{
Branch = branch;
}
}
private readonly struct InfectEventData : IEventData
{
public enum InfectState { Yes, No }
public NetworkHeader NetworkHeader => NetworkHeader.Infect;
public readonly Item Item;
public readonly InfectState Infect;
public readonly BallastFloraBranch Infector;
public InfectEventData(Item item, InfectState infect, BallastFloraBranch infector)
{
Item = item;
Infect = infect;
Infector = infector;
}
}
}
}
@@ -17,6 +17,8 @@ namespace Barotrauma.MapCreatures.Behavior
{
lastState = State;
State?.Exit();
State = null;
newState.Enter();
State = newState;
}
@@ -35,11 +37,9 @@ namespace Barotrauma.MapCreatures.Behavior
{
case ExitState.Running:
break;
case ExitState.ReturnLast when lastState != null && lastState.GetState() == ExitState.Running:
EnterState(lastState);
break;
default:
EnterState(new GrowIdleState(parent));
break;
@@ -5,6 +5,7 @@ using System.Diagnostics;
using Barotrauma.IO;
using System.Linq;
using System.Text;
using Barotrauma.Networking;
namespace Barotrauma
{
@@ -237,9 +237,9 @@ namespace Barotrauma
if (!fireProof)
{
item.ApplyStatusEffects(ActionType.OnFire, 1.0f);
if (item.Condition <= 0.0f && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
if (item.Condition <= 0.0f && GameMain.NetworkMember is { IsServer: true })
{
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFire });
GameMain.NetworkMember.CreateEntityEvent(item, new Item.ApplyStatusEffectEventData(ActionType.OnFire));
}
}
}
@@ -363,9 +363,9 @@ namespace Barotrauma
if (item.Position.Y < position.Y - size.Y || item.Position.Y > hull.Rect.Y) { continue; }
item.ApplyStatusEffects(ActionType.OnFire, deltaTime);
if (item.Condition <= 0.0f && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
if (item.Condition <= 0.0f && GameMain.NetworkMember is { IsServer: true })
{
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFire });
GameMain.NetworkMember.CreateEntityEvent(item, new Item.ApplyStatusEffectEventData(ActionType.OnFire));
}
}
}
@@ -248,16 +248,17 @@ namespace Barotrauma
}
linkedTo.Clear();
int tolerance = 1;
Vector2[] searchPos = new Vector2[2];
if (IsHorizontal)
{
searchPos[0] = new Vector2(rect.X, rect.Y - rect.Height / 2);
searchPos[1] = new Vector2(rect.Right, rect.Y - rect.Height / 2);
searchPos[0] = new Vector2(rect.X - tolerance, rect.Y - rect.Height / 2);
searchPos[1] = new Vector2(rect.Right + tolerance, rect.Y - rect.Height / 2);
}
else
{
searchPos[0] = new Vector2(rect.Center.X, rect.Y);
searchPos[1] = new Vector2(rect.Center.X, rect.Y - rect.Height);
searchPos[0] = new Vector2(rect.Center.X, rect.Y + tolerance);
searchPos[1] = new Vector2(rect.Center.X, rect.Y - rect.Height - tolerance);
}
for (int i = 0; i < 2; i++)
@@ -320,7 +320,8 @@ namespace Barotrauma
roomName != null && (
roomName.Contains("ballast", StringComparison.OrdinalIgnoreCase) ||
roomName.Contains("bilge", StringComparison.OrdinalIgnoreCase) ||
roomName.Contains("airlock", StringComparison.OrdinalIgnoreCase));
roomName.Contains("airlock", StringComparison.OrdinalIgnoreCase) ||
roomName.Contains("dockingport", StringComparison.OrdinalIgnoreCase));
private bool isWetRoom;
[Editable, Serialize(false, IsPropertySaveable.Yes, description: "It's normal for this hull to be filled with water. If the room name contains 'ballast', 'bilge', or 'airlock', you can't disable this setting.")]
@@ -729,9 +730,9 @@ namespace Barotrauma
var decal = DecalManager.CreateDecal(decalName, scale, worldPosition, this, spriteIndex);
if (decal != null)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
if (GameMain.NetworkMember is { IsServer: true })
{
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { false });
GameMain.NetworkMember.CreateEntityEvent(this, new DecalEventData());
}
decals.Add(decal);
}
@@ -739,6 +740,96 @@ namespace Barotrauma
return decal;
}
#region Shared network write
private void SharedStatusWrite(IWriteMessage msg)
{
msg.WriteRangedSingle(MathHelper.Clamp(waterVolume / Volume, 0.0f, 1.5f), 0.0f, 1.5f, 8);
msg.WriteRangedInteger(Math.Min(FireSources.Count, 16), 0, 16);
for (int i = 0; i < Math.Min(FireSources.Count, 16); i++)
{
var fireSource = FireSources[i];
Vector2 normalizedPos = new Vector2(
(fireSource.Position.X - rect.X) / rect.Width,
(fireSource.Position.Y - (rect.Y - rect.Height)) / rect.Height);
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.X, 0.0f, 1.0f), 0.0f, 1.0f, 8);
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.Y, 0.0f, 1.0f), 0.0f, 1.0f, 8);
msg.WriteRangedSingle(MathHelper.Clamp(fireSource.Size.X / rect.Width, 0.0f, 1.0f), 0, 1.0f, 8);
}
}
private void SharedBackgroundSectionsWrite(IWriteMessage msg, in BackgroundSectionsEventData backgroundSectionsEventData)
{
int sectorToUpdate = backgroundSectionsEventData.SectorStartIndex;
int start = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
int end = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
msg.WriteRangedInteger(sectorToUpdate, 0, BackgroundSections.Count - 1);
for (int i = start; i < end; i++)
{
msg.WriteRangedSingle(BackgroundSections[i].ColorStrength, 0.0f, 1.0f, 8);
msg.Write(BackgroundSections[i].Color.PackedValue);
}
}
#endregion
#region Shared network read
public readonly struct NetworkFireSource
{
public readonly Vector2 Position;
public readonly float Size;
public NetworkFireSource(Hull hull, Vector2 normalizedPosition, float normalizedSize)
{
Position = hull.Rect.Location.ToVector2()
+ new Vector2(0, -hull.Rect.Height)
+ normalizedPosition * hull.Rect.Size.ToVector2();
Size = normalizedSize * hull.Rect.Width;
}
}
private void SharedStatusRead(IReadMessage msg, out float newWaterVolume, out NetworkFireSource[] newFireSources)
{
newWaterVolume = msg.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
int fireSourceCount = msg.ReadRangedInteger(0, 16);
newFireSources = new NetworkFireSource[fireSourceCount];
for (int i = 0; i < fireSourceCount; i++)
{
float x = MathHelper.Clamp(msg.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f);
float y = MathHelper.Clamp(msg.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f);
float size = msg.ReadRangedSingle(0.0f, 1.0f, 8);
newFireSources[i] = new NetworkFireSource(this, new Vector2(x, y), size);
}
}
private readonly struct BackgroundSectionNetworkUpdate
{
public readonly int SectionIndex;
public readonly Color Color;
public readonly float ColorStrength;
public BackgroundSectionNetworkUpdate(int sectionIndex, Color color, float colorStrength)
{
SectionIndex = sectionIndex;
Color = color;
ColorStrength = colorStrength;
}
}
private void SharedBackgroundSectionRead(IReadMessage msg, Action<BackgroundSectionNetworkUpdate> action, out int sectorToUpdate)
{
sectorToUpdate = msg.ReadRangedInteger(0, BackgroundSections.Count - 1);
int start = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
int end = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
for (int i = start; i < end; i++)
{
float colorStrength = msg.ReadRangedSingle(0.0f, 1.0f, 8);
Color color = new Color(msg.ReadUInt32());
action(new BackgroundSectionNetworkUpdate(i, color, colorStrength));
}
}
#endregion
public override void Update(float deltaTime, Camera cam)
{
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Barotrauma.Extensions;
using Barotrauma.MapCreatures.Behavior;
using Barotrauma.Networking;
namespace Barotrauma
{
partial class Hull
{
[Flags]
public enum EventType
{
Status = 0,
Decal = 1,
BackgroundSections = 2,
BallastFlora = 3,
MinValue = 0,
MaxValue = 3
}
public interface IEventData : NetEntityEvent.IData
{
public EventType EventType { get; }
}
private readonly struct StatusEventData : IEventData
{
public EventType EventType => EventType.Status;
}
private readonly struct DecalEventData : IEventData
{
public EventType EventType => EventType.Decal;
public readonly Decal Decal;
public DecalEventData(Decal decal)
{
Decal = decal;
}
}
private readonly struct BackgroundSectionsEventData : IEventData
{
public EventType EventType => EventType.BackgroundSections;
public readonly int SectorStartIndex;
public BackgroundSectionsEventData(int sectorStartIndex)
{
SectorStartIndex = sectorStartIndex;
}
}
public readonly struct BallastFloraEventData : IEventData
{
public EventType EventType => EventType.BallastFlora;
public readonly BallastFloraBehavior Behavior;
public readonly BallastFloraBehavior.IEventData SubEventData;
public BallastFloraEventData(BallastFloraBehavior behavior, BallastFloraBehavior.IEventData subEventData)
{
Behavior = behavior;
SubEventData = subEventData;
}
}
}
}
@@ -1,24 +1,31 @@
using Microsoft.Xna.Framework;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
namespace Barotrauma
{
interface IDamageable
{
Vector2 SimPosition
{
get;
}
Vector2 WorldPosition
{
get;
}
float Health
{
get;
}
Vector2 SimPosition { get; }
Vector2 WorldPosition { get; }
float Health { get; }
AttackResult AddDamage(Character attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound=true);
public readonly struct AttackEventData
{
public readonly ISpatialEntity Attacker;
public readonly IDamageable TargetEntity;
public readonly Limb TargetLimb;
public readonly Vector2 AttackSimPosition;
public AttackEventData(ISpatialEntity attacker, IDamageable targetEntity, Limb targetLimb, Vector2 attackSimPosition)
{
Attacker = attacker;
TargetEntity = targetEntity;
TargetLimb = targetLimb;
AttackSimPosition = attackSimPosition;
}
}
}
}
@@ -18,6 +18,12 @@ namespace Barotrauma
{
partial class Level : Entity, IServerSerializable
{
public enum EventType
{
SingleDestructibleWall,
GlobalDestructibleWall
}
//all entities are disabled after they reach this depth
public const int MaxEntityDepth = -300000;
public const float ShaftHeight = 1000.0f;
@@ -3136,13 +3142,14 @@ namespace Barotrauma
UnsyncedExtraWalls[i].Update(deltaTime);
}
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
#if SERVER
if (GameMain.NetworkMember is { IsServer: true })
{
foreach (LevelWall wall in ExtraWalls)
{
if (wall is DestructibleLevelWall destructibleWall && destructibleWall.NetworkUpdatePending)
if (wall is DestructibleLevelWall { NetworkUpdatePending: true } destructibleWall)
{
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { destructibleWall });
GameMain.NetworkMember.CreateEntityEvent(this, new SingleLevelWallEventData(destructibleWall));
destructibleWall.NetworkUpdatePending = false;
}
}
@@ -3151,11 +3158,12 @@ namespace Barotrauma
{
if (ExtraWalls.Any(w => w.Body.BodyType != BodyType.Static))
{
GameMain.NetworkMember.CreateEntityEvent(this);
GameMain.NetworkMember.CreateEntityEvent(this, new GlobalLevelWallEventData());
}
networkUpdateTimer = 0.0f;
}
}
#endif
#if CLIENT
backgroundCreatureManager.Update(deltaTime, cam);
@@ -4288,28 +4296,5 @@ namespace Barotrauma
Loaded = null;
}
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
if (extraData != null && extraData.Length > 0 && extraData[0] is DestructibleLevelWall destructibleWall)
{
int index = ExtraWalls.IndexOf(destructibleWall);
msg.Write(false);
msg.Write((ushort)(index == -1 ? ushort.MaxValue : index));
//write health using one byte
msg.Write((byte)MathHelper.Clamp((int)(MathUtils.InverseLerp(0.0f, destructibleWall.MaxHealth, destructibleWall.Damage) * 255.0f), 0, 255));
}
else
{
msg.Write(true);
foreach (LevelWall levelWall in ExtraWalls)
{
if (levelWall.Body.BodyType == BodyType.Static) { continue; }
msg.Write(levelWall.Body.Position.X);
msg.Write(levelWall.Body.Position.Y);
msg.WriteRangedSingle(levelWall.MoveState, 0.0f, MathHelper.TwoPi, 16);
}
}
}
}
}
@@ -30,6 +30,16 @@ namespace Barotrauma
{
}
private readonly struct EventData : NetEntityEvent.IData
{
public readonly LevelObject LevelObject;
public EventData(LevelObject levelObject)
{
LevelObject = levelObject;
}
}
class SpawnPosition
{
public readonly GraphEdge GraphEdge;
@@ -522,12 +532,12 @@ namespace Barotrauma
foreach (LevelObject obj in updateableObjects)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
if (GameMain.NetworkMember is { IsServer: true })
{
obj.NetworkUpdateTimer -= deltaTime;
if (obj.NeedsNetworkSyncing && obj.NetworkUpdateTimer <= 0.0f)
{
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { obj });
GameMain.NetworkMember.CreateEntityEvent(this, new EventData(obj));
obj.NeedsNetworkSyncing = false;
obj.NetworkUpdateTimer = NetConfig.LevelObjectUpdateInterval;
}
@@ -607,9 +617,10 @@ namespace Barotrauma
partial void RemoveProjSpecific();
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
{
LevelObject obj = extraData[0] as LevelObject;
if (!(extraData is EventData eventData)) { throw new Exception($"Malformed LevelObjectManager event: expected {nameof(LevelObjectManager)}.{nameof(EventData)}"); }
LevelObject obj = eventData.LevelObject;
msg.WriteRangedInteger(objects.IndexOf(obj), 0, objects.Count);
obj.ServerWrite(msg, c);
}
@@ -734,7 +734,7 @@ namespace Barotrauma
if (prefab == null) { continue; }
var qty = stockElement.GetAttributeInt("qty", 0);
if (qty < 1) { continue; }
StoreStock.Add(new PurchasedItem(prefab, qty));
StoreStock.Add(new PurchasedItem(prefab, qty, buyer: null));
}
StepsSinceSpecialsUpdated = storeElement.GetAttributeInt("stepssincespecialsupdated", 0);
@@ -792,7 +792,7 @@ namespace Barotrauma
{
quantity = priceInfo.MinAvailableAmount;
}
stock.Add(new PurchasedItem(prefab, quantity));
stock.Add(new PurchasedItem(prefab, quantity, buyer: null));
}
}
return stock;
@@ -34,7 +34,7 @@ namespace Barotrauma
public override Sprite Sprite { get; }
public override string OriginalName => Name.Value;
public override string OriginalName { get; }
public override ImmutableHashSet<Identifier> Tags { get; }
@@ -132,7 +132,7 @@ namespace Barotrauma
public StructurePrefab(ContentXElement element, StructureFile file) : base(element, file)
{
Name = element.GetAttributeString("name", "");
OriginalName = element.GetAttributeString("name", "");
ConfigElement = element;
var parentType = element.Parent?.GetAttributeIdentifier("prefabtype", Identifier.Empty) ?? Identifier.Empty;
@@ -144,20 +144,16 @@ namespace Barotrauma
Identifier descriptionIdentifier = element.GetAttributeIdentifier("descriptionidentifier", "");
if (Name.IsNullOrEmpty())
{
Name = TextManager.Get($"EntityName.{Identifier}");
if (!nameIdentifier.IsEmpty)
{
Name = TextManager.Get($"EntityName.{nameIdentifier}").Fallback(Name);
}
Name = TextManager.Get(nameIdentifier.IsEmpty
? $"EntityName.{Identifier}"
: $"EntityName.{nameIdentifier}",
$"EntityName.{fallbackNameIdentifier}");
if (!fallbackNameIdentifier.IsEmpty)
{
Name = Name.Fallback(TextManager.Get($"EntityName.{fallbackNameIdentifier}"));
}
if (parentType == "wrecked")
{
Name = TextManager.GetWithVariable("wreckeditemformat", "[name]", Name);
}
var tags = new HashSet<Identifier>();
string joinedTags = element.GetAttributeString("tags", "");
if (string.IsNullOrEmpty(joinedTags)) joinedTags = element.GetAttributeString("Tags", "");
@@ -251,14 +247,6 @@ namespace Barotrauma
DecorativeSpriteGroups = decorativeSpriteGroups.Select(kvp => (kvp.Key, kvp.Value.ToImmutableArray())).ToImmutableDictionary();
#endif
if (parentType == "wrecked")
{
if (!Name.IsNullOrEmpty())
{
Name = TextManager.GetWithVariable("wreckeditemformat", "[name]", Name);
}
}
string categoryStr = element.GetAttributeString("category", "Structure");
if (!Enum.TryParse(categoryStr, true, out MapEntityCategory category))
{
@@ -323,6 +311,15 @@ namespace Barotrauma
DebugConsole.ThrowError(
"Structure prefab \"" + Name + "\" has no identifier. All structure prefabs have a unique identifier string that's used to differentiate between items during saving and loading.");
}
#if DEBUG
if (!Category.HasFlag(MapEntityCategory.Legacy) && !HideInMenus)
{
if (!string.IsNullOrEmpty(OriginalName))
{
DebugConsole.AddWarning($"Structure \"{(Identifier == Identifier.Empty ? Name : Identifier.Value)}\" has a hard-coded name, and won't be localized to other languages.");
}
}
#endif
Tags = tags.ToImmutableHashSet();
AllowedLinks = Enumerable.Empty<Identifier>().ToImmutableHashSet();
@@ -21,7 +21,7 @@ namespace Barotrauma
None = 0, Left = 1, Right = 2
}
partial class Submarine : Entity, IServerSerializable
partial class Submarine : Entity, IServerPositionSync
{
public SubmarineInfo Info { get; private set; }