diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj
index df36c2dce..58e062cef 100644
--- a/Subsurface/Barotrauma.csproj
+++ b/Subsurface/Barotrauma.csproj
@@ -134,7 +134,8 @@
-
+
+
diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs
index 5518f79f4..38250136e 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, false);
+ Item.Spawner.QueueItem(itemPrefab, (Vector2)spawnPos);
}
else if (spawnInventory != null)
{
- Item.Spawner.QueueItem(itemPrefab, (Inventory)spawnInventory, false);
+ Item.Spawner.QueueItem(itemPrefab, (Inventory)spawnInventory);
}
break;
diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs
index ecc1c89bb..a78fe3d3b 100644
--- a/Subsurface/Source/GameSession/GameSession.cs
+++ b/Subsurface/Source/GameSession/GameSession.cs
@@ -72,11 +72,14 @@ namespace Barotrauma
Submarine.MainSub = submarine;
GameMain.GameSession = this;
-
+
CrewManager = new CrewManager();
TaskManager = new TaskManager(this);
+ Entity.Spawner.Clear();
+ Entity.Remover.Clear();
+
this.saveFile = saveFile;
//guiRoot = new GUIFrame(new Rectangle(0,0,GameMain.GraphicsWidth,GameMain.GraphicsWidth), Color.Transparent);
diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs
index 13a040815..c4dc90d53 100644
--- a/Subsurface/Source/Items/Item.cs
+++ b/Subsurface/Source/Items/Item.cs
@@ -31,9 +31,6 @@ namespace Barotrauma
public static List- ItemList = new List
- ();
private ItemPrefab prefab;
-
- public static ItemRemover Remover = new ItemRemover();
-
public static bool ShowLinks = true;
private List tags;
diff --git a/Subsurface/Source/Map/Entity.cs b/Subsurface/Source/Map/Entity.cs
index 021a1e73e..994b43280 100644
--- a/Subsurface/Source/Map/Entity.cs
+++ b/Subsurface/Source/Map/Entity.cs
@@ -12,6 +12,7 @@ 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 fe509626c..7a5e73d50 100644
--- a/Subsurface/Source/Map/MapEntity.cs
+++ b/Subsurface/Source/Map/MapEntity.cs
@@ -270,7 +270,7 @@ namespace Barotrauma
}
Entity.Spawner.Update();
- Item.Remover.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 c82a92961..352f31d7f 100644
--- a/Subsurface/Source/Networking/Client.cs
+++ b/Subsurface/Source/Networking/Client.cs
@@ -37,7 +37,7 @@ namespace Barotrauma.Networking
public UInt32 lastRecvChatMsgID = 0; //last msg this client knows about
public UInt32 lastRecvEntitySpawnID = 0;
- public UInt32 lastRecvItemRemoveID = 0;
+ public UInt32 lastRecvEntityRemoveID = 0;
public List ChatMessages = new List();
@@ -64,7 +64,7 @@ namespace Barotrauma.Networking
lastRecvChatMsgID = ChatMessage.LastID;
lastRecvEntitySpawnID = 0;
- lastRecvItemRemoveID = 0;
+ lastRecvEntityRemoveID = 0;
}
public int KickVoteCount
diff --git a/Subsurface/Source/Networking/EntityRemover.cs b/Subsurface/Source/Networking/EntityRemover.cs
new file mode 100644
index 000000000..08a3f081f
--- /dev/null
+++ b/Subsurface/Source/Networking/EntityRemover.cs
@@ -0,0 +1,89 @@
+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)
+ {
+ 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 bc898d7d3..b4365a056 100644
--- a/Subsurface/Source/Networking/EntitySpawner.cs
+++ b/Subsurface/Source/Networking/EntitySpawner.cs
@@ -1,8 +1,8 @@
-using Microsoft.Xna.Framework;
+using Barotrauma.Networking;
+using Microsoft.Xna.Framework;
+using System;
using System.Collections.Generic;
using System.Linq;
-using Barotrauma.Networking;
-using System;
namespace Barotrauma
{
@@ -75,45 +75,40 @@ namespace Barotrauma
spawnQueue = new Queue();
}
- public void QueueItem(ItemPrefab itemPrefab, Vector2 worldPosition, bool isNetworkMessage = false)
+ public void QueueItem(ItemPrefab itemPrefab, Vector2 worldPosition)
{
- //clients aren't allowed to spawn new items unless the server says so
- if (!isNetworkMessage && GameMain.Client != null) return;
+ if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition));
}
- public void QueueItem(ItemPrefab itemPrefab, Vector2 position, Submarine sub, bool isNetworkMessage = false)
+ public void QueueItem(ItemPrefab itemPrefab, Vector2 position, Submarine sub)
{
- //clients aren't allowed to spawn new items unless the server says so
- if (!isNetworkMessage && GameMain.Client != null) return;
+ if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub));
}
- public void QueueItem(ItemPrefab itemPrefab, Inventory inventory, bool isNetworkMessage = false)
+ public void QueueItem(ItemPrefab itemPrefab, Inventory inventory)
{
- //clients aren't allowed to spawn new items unless the server says so
- if (!isNetworkMessage && GameMain.Client != null) return;
+ if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory));
}
public void Update()
{
+ if (GameMain.Client != null) return;
+
if (!spawnQueue.Any()) return;
- //List inventories = new List();
while (spawnQueue.Count>0)
{
var entitySpawnInfo = spawnQueue.Dequeue();
var spawnedEntity = entitySpawnInfo.Spawn();
-
- if (spawnedEntity!= null) AddToSpawnedList(spawnedEntity);
+ if (spawnedEntity != null) AddToSpawnedList(spawnedEntity);
}
-
- //if (GameMain.Server != null) GameMain.Server.SendItemSpawnMessage(items);
}
public void AddToSpawnedList(Entity entity)
@@ -134,7 +129,7 @@ namespace Barotrauma
message.Write((UInt32)spawnedEntities.Count);
- message.Write((byte)entities.Count);
+ message.Write((UInt16)entities.Count);
for (int i = 0; i < entities.Count; i++)
{
if (entities[i] is Item)
@@ -156,7 +151,7 @@ namespace Barotrauma
UInt32 ID = message.ReadUInt32();
- var entityCount = message.ReadByte();
+ var entityCount = message.ReadUInt16();
for (int i = 0; i < entityCount; i++)
{
switch (message.ReadByte())
@@ -186,84 +181,4 @@ namespace Barotrauma
spawnedEntities.Clear();
}
}
-
- //todo: turn into a generic EntityRemover class + sync
- class ItemRemover : IServerSerializable
- {
- public UInt32 NetStateID
- {
- get;
- private set;
- }
-
- private readonly Queue
- removeQueue;
-
- public List
- removedItems = new List
- ();
-
- public ItemRemover()
- {
- removeQueue = new Queue
- ();
- }
-
- public void QueueItem(Item item, bool isNetworkMessage = false)
- {
- if (!isNetworkMessage && GameMain.Client != null)
- {
- //clients aren't allowed to remove items unless the server says so
- return;
- }
-
- removeQueue.Enqueue(item);
- }
-
- public void Update()
- {
- if (!removeQueue.Any()) return;
-
- List
- items = new List
- ();
-
- while (removeQueue.Count > 0)
- {
- var item = removeQueue.Dequeue();
- removedItems.Add(item);
-
- item.Remove();
-
- items.Add(item);
- }
-
- //if (GameMain.Server != null) GameMain.Server.SendItemRemoveMessage(items);
- }
-
- public void ServerWrite(Lidgren.Network.NetOutgoingMessage message, Client client)
- {
- //message.Write((byte)items.Count);
- //foreach (Item item in items)
- //{
- // message.Write(item.ID);
- //}
- }
-
- public void ClientRead(Lidgren.Network.NetIncomingMessage message)
- {
- var itemCount = message.ReadByte();
- for (int i = 0; i cMsg.NetStateID <= lastSentChatMsgID)) != null)
{
diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs
index ddfae63bf..19e17c968 100644
--- a/Subsurface/Source/Networking/GameServer.cs
+++ b/Subsurface/Source/Networking/GameServer.cs
@@ -599,10 +599,11 @@ namespace Barotrauma.Networking
case ClientNetObject.SYNC_IDS:
//TODO: might want to use a clever class for this
- 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.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:
ChatMessage.ServerRead(inc, c);
@@ -663,6 +664,14 @@ namespace Barotrauma.Networking
outmsg.WritePadBits();
}
+ if (Item.Remover.NetStateID > c.lastRecvEntityRemoveID)
+ {
+ outmsg.Write((byte)ServerNetObject.ENTITY_REMOVE);
+ Item.Remover.ServerWrite(outmsg, c);
+ outmsg.WritePadBits();
+ }
+
+
outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE);
server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable);
}
diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs
index 2a3623289..9285927d0 100644
--- a/Subsurface/Source/Networking/NetworkMember.cs
+++ b/Subsurface/Source/Networking/NetworkMember.cs
@@ -47,7 +47,8 @@ namespace Barotrauma.Networking
CHARACTER_POSITION,
ITEM_STATE,
- ENTITY_SPAWN
+ ENTITY_SPAWN,
+ ENTITY_REMOVE
}
enum VoteType