From 6f9160e4a7aabaa81f117ce8f5b403cf33f62057 Mon Sep 17 00:00:00 2001 From: Regalis Date: Wed, 26 Oct 2016 16:44:59 +0300 Subject: [PATCH] Removing & spawning entities in the same order as the server, EntitySpawner does both removing and spawning --- Subsurface/Source/DebugConsole.cs | 4 +- Subsurface/Source/GameSession/GameSession.cs | 1 - .../Components/Machines/Deconstructor.cs | 4 +- .../Items/Components/Machines/Fabricator.cs | 6 +- Subsurface/Source/Map/Entity.cs | 1 - Subsurface/Source/Map/MapEntity.cs | 1 - Subsurface/Source/Networking/Client.cs | 3 - Subsurface/Source/Networking/EntityRemover.cs | 89 -------------- Subsurface/Source/Networking/EntitySpawner.cs | 109 +++++++++++++----- Subsurface/Source/Networking/GameClient.cs | 6 - Subsurface/Source/Networking/GameServer.cs | 12 +- Subsurface/Source/Networking/NetworkMember.cs | 3 +- .../Source/Networking/RespawnManager.cs | 2 +- 13 files changed, 91 insertions(+), 150 deletions(-) delete mode 100644 Subsurface/Source/Networking/EntityRemover.cs diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index f3bae7522..3f1eac6f4 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -337,12 +337,12 @@ namespace Barotrauma if (spawnPos != null) { - Item.Spawner.QueueItem(itemPrefab, (Vector2)spawnPos); + Item.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos); } else if (spawnInventory != null) { - Item.Spawner.QueueItem(itemPrefab, (Inventory)spawnInventory); + Item.Spawner.AddToSpawnQueue(itemPrefab, (Inventory)spawnInventory); } break; diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index a78fe3d3b..ca273bcfa 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -78,7 +78,6 @@ namespace Barotrauma TaskManager = new TaskManager(this); Entity.Spawner.Clear(); - Entity.Remover.Clear(); this.saveFile = saveFile; diff --git a/Subsurface/Source/Items/Components/Machines/Deconstructor.cs b/Subsurface/Source/Items/Components/Machines/Deconstructor.cs index 187d2dbbf..e208013c3 100644 --- a/Subsurface/Source/Items/Components/Machines/Deconstructor.cs +++ b/Subsurface/Source/Items/Components/Machines/Deconstructor.cs @@ -68,11 +68,11 @@ namespace Barotrauma.Items.Components DebugConsole.ThrowError("Tried to deconstruct item \""+targetItem.Name+"\" but couldn't find item prefab \""+deconstructProduct+"\"!"); continue; } - Item.Spawner.QueueItem(itemPrefab, containers[1].Inventory); + Item.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory); } container.Inventory.RemoveItem(targetItem); - Item.Remover.QueueItem(targetItem); + Item.Spawner.AddToRemoveQueue(targetItem); activateButton.Text = "Deconstruct"; progressBar.BarSize = 0.0f; diff --git a/Subsurface/Source/Items/Components/Machines/Fabricator.cs b/Subsurface/Source/Items/Components/Machines/Fabricator.cs index b4e54a3d5..83b530633 100644 --- a/Subsurface/Source/Items/Components/Machines/Fabricator.cs +++ b/Subsurface/Source/Items/Components/Machines/Fabricator.cs @@ -321,14 +321,12 @@ namespace Barotrauma.Items.Components var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1); if (requiredItem == null) continue; - Item.Remover.QueueItem(requiredItem); + Item.Spawner.AddToRemoveQueue(requiredItem); containers[0].Inventory.RemoveItem(requiredItem); - - } } - Item.Spawner.QueueItem(fabricatedItem.TargetItem, containers[1].Inventory); + Item.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory); CancelFabricating(); } diff --git a/Subsurface/Source/Map/Entity.cs b/Subsurface/Source/Map/Entity.cs index 994b43280..021a1e73e 100644 --- a/Subsurface/Source/Map/Entity.cs +++ b/Subsurface/Source/Map/Entity.cs @@ -12,7 +12,6 @@ namespace Barotrauma private static Dictionary dictionary = new Dictionary(); public static EntitySpawner Spawner = new EntitySpawner(); - public static EntityRemover Remover = new EntityRemover(); private ushort id; diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs index 7a5e73d50..13ae6bd4d 100644 --- a/Subsurface/Source/Map/MapEntity.cs +++ b/Subsurface/Source/Map/MapEntity.cs @@ -270,7 +270,6 @@ namespace Barotrauma } Entity.Spawner.Update(); - Entity.Remover.Update(); } public virtual void Update(Camera cam, float deltaTime) { } diff --git a/Subsurface/Source/Networking/Client.cs b/Subsurface/Source/Networking/Client.cs index 352f31d7f..754158eb9 100644 --- a/Subsurface/Source/Networking/Client.cs +++ b/Subsurface/Source/Networking/Client.cs @@ -37,8 +37,6 @@ namespace Barotrauma.Networking public UInt32 lastRecvChatMsgID = 0; //last msg this client knows about public UInt32 lastRecvEntitySpawnID = 0; - public UInt32 lastRecvEntityRemoveID = 0; - public List ChatMessages = new List(); public float ChatSpamSpeed; @@ -64,7 +62,6 @@ namespace Barotrauma.Networking lastRecvChatMsgID = ChatMessage.LastID; lastRecvEntitySpawnID = 0; - lastRecvEntityRemoveID = 0; } public int KickVoteCount diff --git a/Subsurface/Source/Networking/EntityRemover.cs b/Subsurface/Source/Networking/EntityRemover.cs deleted file mode 100644 index 2c26d761a..000000000 --- a/Subsurface/Source/Networking/EntityRemover.cs +++ /dev/null @@ -1,89 +0,0 @@ -using Barotrauma.Networking; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Barotrauma -{ - class EntityRemover : IServerSerializable - { - public UInt32 NetStateID - { - get; - private set; - } - - private readonly Queue removeQueue; - - public List removedEntities = new List(); - - public EntityRemover() - { - removeQueue = new Queue(); - } - - public void QueueItem(Item item) - { - if (GameMain.Client != null) return; - - removeQueue.Enqueue(item); - } - - public void Update() - { - if (GameMain.Client != null) return; - - while (removeQueue.Count > 0) - { - var entity = removeQueue.Dequeue(); - removedEntities.Add(entity); - - entity.Remove(); - NetStateID = (UInt32)removedEntities.Count; - } - } - - public void ServerWrite(Lidgren.Network.NetOutgoingMessage message, Client client) - { - if (GameMain.Server == null) return; - - List entities = removedEntities.Skip((int)client.lastRecvEntityRemoveID).ToList(); - - message.Write((UInt32)removedEntities.Count); - - message.Write((UInt16)entities.Count); - foreach (Entity entity in entities) - { - message.Write(entity.ID); - } - } - - public void ClientRead(Lidgren.Network.NetIncomingMessage message, float sendingTime) - { - if (GameMain.Server != null) return; - - UInt32 ID = message.ReadUInt32(); - - var entityCount = message.ReadUInt16(); - for (int i = 0; i < entityCount; i++) - { - ushort entityId = message.ReadUInt16(); - - var entity = Entity.FindEntityByID(entityId); - if (entity == null || ID - entityCount + i < NetStateID) continue; //already removed - - entity.Remove(); - } - - NetStateID = Math.Max(ID, NetStateID); - } - - public void Clear() - { - NetStateID = 0; - - removeQueue.Clear(); - removedEntities.Clear(); - } - } -} diff --git a/Subsurface/Source/Networking/EntitySpawner.cs b/Subsurface/Source/Networking/EntitySpawner.cs index 084906cb1..7b7755241 100644 --- a/Subsurface/Source/Networking/EntitySpawner.cs +++ b/Subsurface/Source/Networking/EntitySpawner.cs @@ -67,35 +67,57 @@ namespace Barotrauma } private readonly Queue spawnQueue; + private readonly Queue removeQueue; + + class SpawnOrRemove + { + public readonly Entity Entity; + + public readonly bool Remove = false; + + public SpawnOrRemove(Entity entity, bool remove) + { + Entity = entity; + Remove = remove; + } + } - private List spawnedEntities = new List(); + private List spawnHistory = new List(); public EntitySpawner() { spawnQueue = new Queue(); + removeQueue = new Queue(); } - public void QueueItem(ItemPrefab itemPrefab, Vector2 worldPosition) + public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition) { if (GameMain.Client != null) return; spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition)); } - public void QueueItem(ItemPrefab itemPrefab, Vector2 position, Submarine sub) + public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub) { if (GameMain.Client != null) return; spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub)); } - public void QueueItem(ItemPrefab itemPrefab, Inventory inventory) + public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory) { if (GameMain.Client != null) return; spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory)); } + public void AddToRemoveQueue(Item item) + { + if (GameMain.Client != null) return; + + removeQueue.Enqueue(item); + } + public void Update() { if (GameMain.Client != null) return; @@ -109,6 +131,15 @@ namespace Barotrauma var spawnedEntity = entitySpawnInfo.Spawn(); if (spawnedEntity != null) AddToSpawnedList(spawnedEntity); } + + while (removeQueue.Count > 0) + { + var entity = removeQueue.Dequeue(); + spawnHistory.Add(new SpawnOrRemove(entity, true)); + + entity.Remove(); + NetStateID = (UInt32)spawnHistory.Count; + } } public void AddToSpawnedList(Entity entity) @@ -116,8 +147,9 @@ namespace Barotrauma if (GameMain.Server == null) return; if (entity == null) return; - spawnedEntities.Add(entity); - NetStateID = (UInt32)spawnedEntities.Count; + spawnHistory.Add(new SpawnOrRemove(entity, false)); + + NetStateID = (UInt32)spawnHistory.Count; } public void ServerWrite(Lidgren.Network.NetOutgoingMessage message, Client client) @@ -125,22 +157,31 @@ namespace Barotrauma if (GameMain.Server == null) return; //skip items that the client already knows about - List entities = spawnedEntities.Skip((int)client.lastRecvEntitySpawnID).ToList(); + List entities = spawnHistory.Skip((int)client.lastRecvEntitySpawnID).ToList(); - message.Write((UInt32)spawnedEntities.Count); + message.Write((UInt32)spawnHistory.Count); message.Write((UInt16)entities.Count); for (int i = 0; i < entities.Count; i++) { - if (entities[i] is Item) + message.Write(entities[i].Remove); + + if (entities[i].Remove) { - message.Write((byte)SpawnableType.Item); - ((Item)entities[i]).WriteSpawnData(message); + message.Write(entities[i].Entity.ID); } - else if (entities[i] is Character) + else { - message.Write((byte)SpawnableType.Character); - ((Character)entities[i]).WriteSpawnData(message); + if (entities[i].Entity is Item) + { + message.Write((byte)SpawnableType.Item); + ((Item)entities[i].Entity).WriteSpawnData(message); + } + else if (entities[i].Entity is Character) + { + message.Write((byte)SpawnableType.Character); + ((Character)entities[i].Entity).WriteSpawnData(message); + } } } } @@ -154,19 +195,32 @@ namespace Barotrauma var entityCount = message.ReadUInt16(); for (int i = 0; i < entityCount; i++) { - switch (message.ReadByte()) - { - case (byte)SpawnableType.Item: - Item.ReadSpawnData(message, ID - entityCount + i >= NetStateID); - break; - case (byte)SpawnableType.Character: - Character.ReadSpawnData(message, ID - entityCount + i >= NetStateID); - break; - default: - DebugConsole.ThrowError("Received invalid entity spawn message (unknown spawnable type)"); - break; - } + bool remove = message.ReadBoolean(); + if (remove) + { + ushort entityId = message.ReadUInt16(); + + var entity = Entity.FindEntityByID(entityId); + if (entity == null || ID - entityCount + i < NetStateID) continue; //already removed + + entity.Remove(); + } + else + { + switch (message.ReadByte()) + { + case (byte)SpawnableType.Item: + Item.ReadSpawnData(message, ID - entityCount + i >= NetStateID); + break; + case (byte)SpawnableType.Character: + Character.ReadSpawnData(message, ID - entityCount + i >= NetStateID); + break; + default: + DebugConsole.ThrowError("Received invalid entity spawn message (unknown spawnable type)"); + break; + } + } } NetStateID = Math.Max(ID, NetStateID); @@ -178,7 +232,8 @@ namespace Barotrauma NetStateID = 0; spawnQueue.Clear(); - spawnedEntities.Clear(); + removeQueue.Clear(); + spawnHistory.Clear(); } } } diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index d86ed7923..635af34e6 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -560,7 +560,6 @@ namespace Barotrauma.Networking if (Character != null) Character.Remove(); Entity.Spawner.Clear(); - Entity.Remover.Clear(); endVoteTickBox.Selected = false; @@ -730,10 +729,6 @@ namespace Barotrauma.Networking Item.Spawner.ClientRead(inc, sendingTime); inc.ReadPadBits(); break; - case ServerNetObject.ENTITY_REMOVE: - Item.Remover.ClientRead(inc, sendingTime); - inc.ReadPadBits(); - break; default: DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)"); break; @@ -772,7 +767,6 @@ namespace Barotrauma.Networking outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); outmsg.Write(ChatMessage.LastID); outmsg.Write(Entity.Spawner.NetStateID); - outmsg.Write(Entity.Remover.NetStateID); ChatMessage removeMsg; while ((removeMsg = chatMsgQueue.Find(cMsg => cMsg.NetStateID <= lastSentChatMsgID)) != null) diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index b7e002dad..7c7f65627 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -602,7 +602,6 @@ namespace Barotrauma.Networking c.lastRecvGeneralUpdate = Math.Max(c.lastRecvGeneralUpdate, inc.ReadUInt32()); c.lastRecvChatMsgID = Math.Max(c.lastRecvChatMsgID, inc.ReadUInt32()); c.lastRecvEntitySpawnID = Math.Max(c.lastRecvEntitySpawnID, inc.ReadUInt32()); - c.lastRecvEntityRemoveID = Math.Max(c.lastRecvEntityRemoveID, inc.ReadUInt32()); break; case ClientNetObject.CHAT_MESSAGE: @@ -652,14 +651,7 @@ namespace Barotrauma.Networking Item.Spawner.ServerWrite(outmsg, c); outmsg.WritePadBits(); } - - if (Item.Remover.NetStateID > c.lastRecvEntityRemoveID) - { - outmsg.Write((byte)ServerNetObject.ENTITY_REMOVE); - Item.Remover.ServerWrite(outmsg, c); - outmsg.WritePadBits(); - } - + foreach (Character character in Character.CharacterList) { if (character is AICharacter) continue; @@ -835,7 +827,6 @@ namespace Barotrauma.Networking private IEnumerable StartGame(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode) { Item.Spawner.Clear(); - Item.Remover.Clear(); GameMain.NetLobbyScreen.StartButton.Enabled = false; @@ -996,7 +987,6 @@ namespace Barotrauma.Networking GameMain.LightManager.LosEnabled = false; Item.Spawner.Clear(); - Item.Remover.Clear(); #if DEBUG messageCount.Clear(); diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index 98f81a12c..eb37a276b 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -47,8 +47,7 @@ namespace Barotrauma.Networking ENTITY_POSITION, ITEM_STATE, - ENTITY_SPAWN, - ENTITY_REMOVE + ENTITY_SPAWN } enum VoteType diff --git a/Subsurface/Source/Networking/RespawnManager.cs b/Subsurface/Source/Networking/RespawnManager.cs index 49ac8a4e0..3ec9cd424 100644 --- a/Subsurface/Source/Networking/RespawnManager.cs +++ b/Subsurface/Source/Networking/RespawnManager.cs @@ -325,7 +325,7 @@ namespace Barotrauma.Networking if (item.body != null && item.body.Enabled && item.ParentInventory == null) { - Item.Remover.QueueItem(item); + Item.Spawner.AddToRemoveQueue(item); } item.Condition = 100.0f;