Removing & spawning entities in the same order as the server, EntitySpawner does both removing and spawning

This commit is contained in:
Regalis
2016-10-26 16:44:59 +03:00
parent df9f89e383
commit 6f9160e4a7
13 changed files with 91 additions and 150 deletions
+2 -2
View File
@@ -337,12 +337,12 @@ namespace Barotrauma
if (spawnPos != null) if (spawnPos != null)
{ {
Item.Spawner.QueueItem(itemPrefab, (Vector2)spawnPos); Item.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
} }
else if (spawnInventory != null) else if (spawnInventory != null)
{ {
Item.Spawner.QueueItem(itemPrefab, (Inventory)spawnInventory); Item.Spawner.AddToSpawnQueue(itemPrefab, (Inventory)spawnInventory);
} }
break; break;
@@ -78,7 +78,6 @@ namespace Barotrauma
TaskManager = new TaskManager(this); TaskManager = new TaskManager(this);
Entity.Spawner.Clear(); Entity.Spawner.Clear();
Entity.Remover.Clear();
this.saveFile = saveFile; this.saveFile = saveFile;
@@ -68,11 +68,11 @@ namespace Barotrauma.Items.Components
DebugConsole.ThrowError("Tried to deconstruct item \""+targetItem.Name+"\" but couldn't find item prefab \""+deconstructProduct+"\"!"); DebugConsole.ThrowError("Tried to deconstruct item \""+targetItem.Name+"\" but couldn't find item prefab \""+deconstructProduct+"\"!");
continue; continue;
} }
Item.Spawner.QueueItem(itemPrefab, containers[1].Inventory); Item.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory);
} }
container.Inventory.RemoveItem(targetItem); container.Inventory.RemoveItem(targetItem);
Item.Remover.QueueItem(targetItem); Item.Spawner.AddToRemoveQueue(targetItem);
activateButton.Text = "Deconstruct"; activateButton.Text = "Deconstruct";
progressBar.BarSize = 0.0f; progressBar.BarSize = 0.0f;
@@ -321,14 +321,12 @@ namespace Barotrauma.Items.Components
var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1); var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1);
if (requiredItem == null) continue; if (requiredItem == null) continue;
Item.Remover.QueueItem(requiredItem); Item.Spawner.AddToRemoveQueue(requiredItem);
containers[0].Inventory.RemoveItem(requiredItem); containers[0].Inventory.RemoveItem(requiredItem);
} }
} }
Item.Spawner.QueueItem(fabricatedItem.TargetItem, containers[1].Inventory); Item.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory);
CancelFabricating(); CancelFabricating();
} }
-1
View File
@@ -12,7 +12,6 @@ namespace Barotrauma
private static Dictionary<ushort, Entity> dictionary = new Dictionary<ushort, Entity>(); private static Dictionary<ushort, Entity> dictionary = new Dictionary<ushort, Entity>();
public static EntitySpawner Spawner = new EntitySpawner(); public static EntitySpawner Spawner = new EntitySpawner();
public static EntityRemover Remover = new EntityRemover();
private ushort id; private ushort id;
-1
View File
@@ -270,7 +270,6 @@ namespace Barotrauma
} }
Entity.Spawner.Update(); Entity.Spawner.Update();
Entity.Remover.Update();
} }
public virtual void Update(Camera cam, float deltaTime) { } public virtual void Update(Camera cam, float deltaTime) { }
-3
View File
@@ -37,8 +37,6 @@ namespace Barotrauma.Networking
public UInt32 lastRecvChatMsgID = 0; //last msg this client knows about public UInt32 lastRecvChatMsgID = 0; //last msg this client knows about
public UInt32 lastRecvEntitySpawnID = 0; public UInt32 lastRecvEntitySpawnID = 0;
public UInt32 lastRecvEntityRemoveID = 0;
public List<string> ChatMessages = new List<string>(); public List<string> ChatMessages = new List<string>();
public float ChatSpamSpeed; public float ChatSpamSpeed;
@@ -64,7 +62,6 @@ namespace Barotrauma.Networking
lastRecvChatMsgID = ChatMessage.LastID; lastRecvChatMsgID = ChatMessage.LastID;
lastRecvEntitySpawnID = 0; lastRecvEntitySpawnID = 0;
lastRecvEntityRemoveID = 0;
} }
public int KickVoteCount public int KickVoteCount
@@ -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<Entity> removeQueue;
public List<Entity> removedEntities = new List<Entity>();
public EntityRemover()
{
removeQueue = new Queue<Entity>();
}
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<Entity> 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();
}
}
}
+82 -27
View File
@@ -67,35 +67,57 @@ namespace Barotrauma
} }
private readonly Queue<IEntitySpawnInfo> spawnQueue; private readonly Queue<IEntitySpawnInfo> spawnQueue;
private readonly Queue<Entity> removeQueue;
private List<Entity> spawnedEntities = new List<Entity>(); class SpawnOrRemove
{
public readonly Entity Entity;
public readonly bool Remove = false;
public SpawnOrRemove(Entity entity, bool remove)
{
Entity = entity;
Remove = remove;
}
}
private List<SpawnOrRemove> spawnHistory = new List<SpawnOrRemove>();
public EntitySpawner() public EntitySpawner()
{ {
spawnQueue = new Queue<IEntitySpawnInfo>(); spawnQueue = new Queue<IEntitySpawnInfo>();
removeQueue = new Queue<Entity>();
} }
public void QueueItem(ItemPrefab itemPrefab, Vector2 worldPosition) public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition)
{ {
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition)); 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; if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub)); 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; if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory)); spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory));
} }
public void AddToRemoveQueue(Item item)
{
if (GameMain.Client != null) return;
removeQueue.Enqueue(item);
}
public void Update() public void Update()
{ {
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
@@ -109,6 +131,15 @@ namespace Barotrauma
var spawnedEntity = entitySpawnInfo.Spawn(); var spawnedEntity = entitySpawnInfo.Spawn();
if (spawnedEntity != null) AddToSpawnedList(spawnedEntity); 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) public void AddToSpawnedList(Entity entity)
@@ -116,8 +147,9 @@ namespace Barotrauma
if (GameMain.Server == null) return; if (GameMain.Server == null) return;
if (entity == null) return; if (entity == null) return;
spawnedEntities.Add(entity); spawnHistory.Add(new SpawnOrRemove(entity, false));
NetStateID = (UInt32)spawnedEntities.Count;
NetStateID = (UInt32)spawnHistory.Count;
} }
public void ServerWrite(Lidgren.Network.NetOutgoingMessage message, Client client) public void ServerWrite(Lidgren.Network.NetOutgoingMessage message, Client client)
@@ -125,22 +157,31 @@ namespace Barotrauma
if (GameMain.Server == null) return; if (GameMain.Server == null) return;
//skip items that the client already knows about //skip items that the client already knows about
List<Entity> entities = spawnedEntities.Skip((int)client.lastRecvEntitySpawnID).ToList(); List<SpawnOrRemove> entities = spawnHistory.Skip((int)client.lastRecvEntitySpawnID).ToList();
message.Write((UInt32)spawnedEntities.Count); message.Write((UInt32)spawnHistory.Count);
message.Write((UInt16)entities.Count); message.Write((UInt16)entities.Count);
for (int i = 0; i < entities.Count; i++) 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); message.Write(entities[i].Entity.ID);
((Item)entities[i]).WriteSpawnData(message);
} }
else if (entities[i] is Character) else
{ {
message.Write((byte)SpawnableType.Character); if (entities[i].Entity is Item)
((Character)entities[i]).WriteSpawnData(message); {
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(); var entityCount = message.ReadUInt16();
for (int i = 0; i < entityCount; i++) for (int i = 0; i < entityCount; i++)
{ {
switch (message.ReadByte()) bool remove = message.ReadBoolean();
{
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;
}
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); NetStateID = Math.Max(ID, NetStateID);
@@ -178,7 +232,8 @@ namespace Barotrauma
NetStateID = 0; NetStateID = 0;
spawnQueue.Clear(); spawnQueue.Clear();
spawnedEntities.Clear(); removeQueue.Clear();
spawnHistory.Clear();
} }
} }
} }
@@ -560,7 +560,6 @@ namespace Barotrauma.Networking
if (Character != null) Character.Remove(); if (Character != null) Character.Remove();
Entity.Spawner.Clear(); Entity.Spawner.Clear();
Entity.Remover.Clear();
endVoteTickBox.Selected = false; endVoteTickBox.Selected = false;
@@ -730,10 +729,6 @@ namespace Barotrauma.Networking
Item.Spawner.ClientRead(inc, sendingTime); Item.Spawner.ClientRead(inc, sendingTime);
inc.ReadPadBits(); inc.ReadPadBits();
break; break;
case ServerNetObject.ENTITY_REMOVE:
Item.Remover.ClientRead(inc, sendingTime);
inc.ReadPadBits();
break;
default: default:
DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)"); DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)");
break; break;
@@ -772,7 +767,6 @@ namespace Barotrauma.Networking
outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID);
outmsg.Write(ChatMessage.LastID); outmsg.Write(ChatMessage.LastID);
outmsg.Write(Entity.Spawner.NetStateID); outmsg.Write(Entity.Spawner.NetStateID);
outmsg.Write(Entity.Remover.NetStateID);
ChatMessage removeMsg; ChatMessage removeMsg;
while ((removeMsg = chatMsgQueue.Find(cMsg => cMsg.NetStateID <= lastSentChatMsgID)) != null) while ((removeMsg = chatMsgQueue.Find(cMsg => cMsg.NetStateID <= lastSentChatMsgID)) != null)
@@ -602,7 +602,6 @@ namespace Barotrauma.Networking
c.lastRecvGeneralUpdate = Math.Max(c.lastRecvGeneralUpdate, inc.ReadUInt32()); c.lastRecvGeneralUpdate = Math.Max(c.lastRecvGeneralUpdate, inc.ReadUInt32());
c.lastRecvChatMsgID = Math.Max(c.lastRecvChatMsgID, inc.ReadUInt32()); c.lastRecvChatMsgID = Math.Max(c.lastRecvChatMsgID, inc.ReadUInt32());
c.lastRecvEntitySpawnID = Math.Max(c.lastRecvEntitySpawnID, inc.ReadUInt32()); c.lastRecvEntitySpawnID = Math.Max(c.lastRecvEntitySpawnID, inc.ReadUInt32());
c.lastRecvEntityRemoveID = Math.Max(c.lastRecvEntityRemoveID, inc.ReadUInt32());
break; break;
case ClientNetObject.CHAT_MESSAGE: case ClientNetObject.CHAT_MESSAGE:
@@ -653,13 +652,6 @@ namespace Barotrauma.Networking
outmsg.WritePadBits(); 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) foreach (Character character in Character.CharacterList)
{ {
if (character is AICharacter) continue; if (character is AICharacter) continue;
@@ -835,7 +827,6 @@ namespace Barotrauma.Networking
private IEnumerable<object> StartGame(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode) private IEnumerable<object> StartGame(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode)
{ {
Item.Spawner.Clear(); Item.Spawner.Clear();
Item.Remover.Clear();
GameMain.NetLobbyScreen.StartButton.Enabled = false; GameMain.NetLobbyScreen.StartButton.Enabled = false;
@@ -996,7 +987,6 @@ namespace Barotrauma.Networking
GameMain.LightManager.LosEnabled = false; GameMain.LightManager.LosEnabled = false;
Item.Spawner.Clear(); Item.Spawner.Clear();
Item.Remover.Clear();
#if DEBUG #if DEBUG
messageCount.Clear(); messageCount.Clear();
@@ -47,8 +47,7 @@ namespace Barotrauma.Networking
ENTITY_POSITION, ENTITY_POSITION,
ITEM_STATE, ITEM_STATE,
ENTITY_SPAWN, ENTITY_SPAWN
ENTITY_REMOVE
} }
enum VoteType enum VoteType
@@ -325,7 +325,7 @@ namespace Barotrauma.Networking
if (item.body != null && item.body.Enabled && item.ParentInventory == null) if (item.body != null && item.body.Enabled && item.ParentInventory == null)
{ {
Item.Remover.QueueItem(item); Item.Spawner.AddToRemoveQueue(item);
} }
item.Condition = 100.0f; item.Condition = 100.0f;