diff --git a/Barotrauma/BarotraumaShared/Source/Map/Entity.cs b/Barotrauma/BarotraumaShared/Source/Map/Entity.cs index 8546ff782..def927532 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Entity.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Entity.cs @@ -20,6 +20,8 @@ namespace Barotrauma protected AITarget aiTarget; + private bool idFreed; + public virtual bool Removed { get; @@ -52,7 +54,8 @@ namespace Barotrauma DebugConsole.Log("The id of " + this + " is now " + value); } - id = value; + id = value; + idFreed = false; dictionary.Add(id, this); } } @@ -199,21 +202,24 @@ namespace Barotrauma dictionary.Clear(); } - public virtual void Remove() + /// + /// Removes the entity from the entity dictionary and frees up the ID it was using. + /// + public void FreeID() { DebugConsole.Log("Removing entity " + ToString() + " (" + ID + ") from entity dictionary."); if (!dictionary.TryGetValue(ID, out Entity existingEntity)) { DebugConsole.Log("Entity " + ToString() + " (" + ID + ") not present in entity dictionary."); GameAnalyticsManager.AddErrorEventOnce( - "Entity.Remove:EntityNotFound" + ID, + "Entity.FreeID:EntityNotFound" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Entity " + ToString() + " (" + ID + ") not present in entity dictionary.\n" + Environment.StackTrace); } else if (existingEntity != this) { DebugConsole.Log("Entity ID mismatch in entity dictionary. Entity " + existingEntity + " had the ID " + ID + " (expecting " + ToString() + ")"); - GameAnalyticsManager.AddErrorEventOnce("Entity.Remove:EntityMismatch" + ID, + GameAnalyticsManager.AddErrorEventOnce("Entity.FreeID:EntityMismatch" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Entity ID mismatch in entity dictionary. Entity " + existingEntity + " had the ID " + ID + " (expecting " + ToString() + ")"); @@ -224,6 +230,13 @@ namespace Barotrauma } dictionary.Remove(ID); + id = 0; + idFreed = true; + } + + public virtual void Remove() + { + if (!idFreed) FreeID(); Removed = true; } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs index 7348e0aa5..69974ebb2 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs @@ -18,11 +18,7 @@ namespace Barotrauma public Rectangle rect; public float damage; public Gap gap; - - public int GapID; - - //public float lastSentDamage; - + public WallSection(Rectangle rect) { System.Diagnostics.Debug.Assert(rect.Width > 0 && rect.Height > 0); @@ -687,7 +683,7 @@ namespace Barotrauma return new AttackResult(damageAmount, 0.0f); } - private void SetDamage(int sectionIndex, float damage, Character attacker = null) + private void SetDamage(int sectionIndex, float damage, Character attacker = null, bool createNetworkEvent = true) { if (Submarine != null && Submarine.GodMode) return; if (!prefab.Body) return; @@ -695,7 +691,7 @@ namespace Barotrauma damage = MathHelper.Clamp(damage, 0.0f, prefab.Health); - if (GameMain.Server != null && damage != sections[sectionIndex].damage) + if (GameMain.Server != null && createNetworkEvent && damage != sections[sectionIndex].damage) { GameMain.Server.CreateEntityEvent(this); } @@ -720,7 +716,9 @@ namespace Barotrauma GameServer.Log((sections[sectionIndex].gap.IsRoomToRoom ? "Inner" : "Outer") + " wall repaired by " + attacker.Name, ServerLog.MessageType.ItemInteraction); } - //remove existing gap if damage is below 50% + DebugConsole.Log("Removing gap (ID " + sections[sectionIndex].gap.ID + ", section: " + sectionIndex + ") from wall " + ID); + //remove existing gap if damage is below leak threshold + sections[sectionIndex].gap.Open = 0.0f; sections[sectionIndex].gap.Remove(); sections[sectionIndex].gap = null; #if CLIENT @@ -730,17 +728,21 @@ namespace Barotrauma } else { - if (sections[sectionIndex].gap == null) { - Rectangle gapRect = sections[sectionIndex].rect; gapRect.X -= 10; gapRect.Y += 10; gapRect.Width += 20; gapRect.Height += 20; sections[sectionIndex].gap = new Gap(gapRect, !isHorizontal, Submarine); + //free the ID, because if we give gaps IDs we have to make sure they always match between the clients and the server and + //that clients create them in the correct order along with every other entity created/removed during the round + //which COULD be done via entityspawner, but it's unnecessary because we never access these gaps by ID + sections[sectionIndex].gap.FreeID(); + sections[sectionIndex].gap.ShouldBeSaved = false; sections[sectionIndex].gap.ConnectedWall = this; + DebugConsole.Log("Created gap (ID " + sections[sectionIndex].gap.ID + ", section: " + sectionIndex + ") on wall " + ID); //AdjustKarma(attacker, 300); //the structure didn't have any other gaps yet, log the breach @@ -856,9 +858,8 @@ namespace Barotrauma { for (int i = 0; i < sections.Length; i++) { - float damage = msg.ReadRangedSingle(0.0f, 1.0f, 8) * Health; - - SetDamage(i, damage); + float damage = msg.ReadRangedSingle(0.0f, 1.0f, 8) * Health; + SetDamage(i, damage); } } public override void FlipX() @@ -900,10 +901,12 @@ namespace Barotrauma } Rectangle rect = element.GetAttributeRect("rect", Rectangle.Empty); - Structure s = new Structure(rect, prefab, submarine); - s.Submarine = submarine; - s.ID = (ushort)int.Parse(element.Attribute("ID").Value); - + Structure s = new Structure(rect, prefab, submarine) + { + Submarine = submarine, + ID = (ushort)int.Parse(element.Attribute("ID").Value) + }; + foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString()) @@ -911,12 +914,7 @@ namespace Barotrauma case "section": int index = subElement.GetAttributeInt("i", -1); if (index == -1) continue; - - s.sections[index].damage = - subElement.GetAttributeFloat("damage", 0.0f); - - s.sections[index].GapID = subElement.GetAttributeInt("gap", -1); - + s.sections[index].damage = subElement.GetAttributeFloat("damage", 0.0f); break; } } @@ -938,17 +936,10 @@ namespace Barotrauma for (int i = 0; i < sections.Length; i++) { if (sections[i].damage == 0.0f) continue; - var sectionElement = new XElement("section", new XAttribute("i", i), new XAttribute("damage", sections[i].damage)); - - if (sections[i].gap != null) - { - sectionElement.Add(new XAttribute("gap", sections[i].gap.ID)); - } - element.Add(sectionElement); } @@ -961,14 +952,10 @@ namespace Barotrauma public override void OnMapLoaded() { - foreach (WallSection s in sections) + for (int i = 0; i < sections.Length; i++) { - if (s.GapID == -1) continue; - - s.gap = FindEntityByID((ushort)s.GapID) as Gap; - if (s.gap != null) s.gap.ConnectedWall = this; + SetDamage(i, sections[i].damage, createNetworkEvent: false); } } - } } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs index 276bf8177..ddba249ca 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs @@ -322,7 +322,7 @@ namespace Barotrauma DockedTo = new List(); ID = ushort.MaxValue; - base.Remove(); + FreeID(); } public bool HasTag(SubmarineTag tag)