using Microsoft.Xna.Framework; using System.Collections.Generic; using System.Linq; namespace Barotrauma { class ItemSpawner { class ItemSpawnInfo { public readonly ItemPrefab Prefab; public readonly Vector2 Position; public readonly Inventory Inventory; public readonly Submarine Submarine; public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition) { Prefab = prefab; Position = worldPosition; } public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub) { Prefab = prefab; Position = position; Submarine = sub; } public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory) { Prefab = prefab; Inventory = inventory; } } private readonly Queue spawnQueue; public List spawnItems = new List(); public ItemSpawner() { spawnQueue = new Queue(); } public void QueueItem(ItemPrefab itemPrefab, Vector2 worldPosition, bool isNetworkMessage = false) { //clients aren't allowed to spawn new items unless the server says so if (!isNetworkMessage && GameMain.Client != null) return; spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition)); } public void QueueItem(ItemPrefab itemPrefab, Vector2 position, Submarine sub, bool isNetworkMessage = false) { //clients aren't allowed to spawn new items unless the server says so if (!isNetworkMessage && GameMain.Client != null) return; spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub)); } public void QueueItem(ItemPrefab itemPrefab, Inventory inventory, bool isNetworkMessage = false) { //clients aren't allowed to spawn new items unless the server says so if (!isNetworkMessage && GameMain.Client != null) return; spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory)); } public void Update() { if (!spawnQueue.Any()) return; List items = new List(); //List inventories = new List(); while (spawnQueue.Count>0) { var itemInfo = spawnQueue.Dequeue(); Item spawnedItem = null; if (itemInfo.Inventory != null) { spawnedItem = new Item(itemInfo.Prefab, Vector2.Zero, null); itemInfo.Inventory.TryPutItem(spawnedItem, spawnedItem.AllowedSlots, false); } else { spawnedItem = new Item(itemInfo.Prefab, itemInfo.Position, itemInfo.Submarine); } AddToSpawnedList(spawnedItem); items.Add(spawnedItem); } if (GameMain.Server != null) GameMain.Server.SendItemSpawnMessage(items); } public void AddToSpawnedList(Item item) { spawnItems.Add(item); } public void FillNetworkData(Lidgren.Network.NetBuffer message, List items) { message.Write((byte)items.Count); for (int i = 0; i < items.Count; i++) { message.Write(items[i].Prefab.Name); message.Write(items[i].ID); if (items[i].ParentInventory == null || items[i].ParentInventory.Owner == null) { message.Write((ushort)0); message.Write(items[i].Position.X); message.Write(items[i].Position.Y); message.Write(items[i].Submarine != null ? items[i].Submarine.ID : (ushort)0); } else { message.Write(items[i].ParentInventory.Owner.ID); int index = items[i].ParentInventory.FindIndex(items[i]); message.Write(index < 0 ? (byte)255 : (byte)index); } if (items[i].Name == "ID Card") { message.Write(items[i].Tags); } } } public void ReadNetworkData(Lidgren.Network.NetBuffer message) { var itemCount = message.ReadByte(); for (int i = 0; i < itemCount; i++) { string itemName = message.ReadString(); ushort itemId = message.ReadUInt16(); Vector2 pos = Vector2.Zero; Submarine sub = null; ushort inventoryId = message.ReadUInt16(); int inventorySlotIndex = -1; if (inventoryId > 0) { inventorySlotIndex = message.ReadByte(); } else { pos = new Vector2(message.ReadSingle(), message.ReadSingle()); ushort subID = message.ReadUInt16(); if (subID > 0) { sub = Submarine.Loaded.Find(s => s.ID == subID); } } string tags = ""; if (itemName == "ID Card") { tags = message.ReadString(); } var prefab = MapEntityPrefab.list.Find(me => me.Name == itemName); if (prefab == null) continue; var itemPrefab = prefab as ItemPrefab; if (itemPrefab == null) continue; Inventory inventory = null; var inventoryOwner = Entity.FindEntityByID(inventoryId); if (inventoryOwner != null) { if (inventoryOwner is Character) { inventory = (inventoryOwner as Character).Inventory; } else if (inventoryOwner is Item) { var containers = (inventoryOwner as Item).GetComponents(); if (containers!=null && containers.Any()) { inventory = containers.Last().Inventory; } } } var item = new Item(itemPrefab, pos, sub); item.ID = itemId; if (sub != null) { item.CurrentHull = Hull.FindHull(pos + sub.Position, null, true); item.Submarine = item.CurrentHull == null ? null : item.CurrentHull.Submarine; } if (!string.IsNullOrEmpty(tags)) item.Tags = tags; if (inventory != null) { if (inventorySlotIndex >= 0 && inventorySlotIndex < 255 && inventory.TryPutItem(item, inventorySlotIndex, false, false)) { continue; } inventory.TryPutItem(item, item.AllowedSlots, false); } } } public void Clear() { spawnQueue.Clear(); spawnItems.Clear(); } } class ItemRemover { 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 FillNetworkData(Lidgren.Network.NetBuffer message, List items) { message.Write((byte)items.Count); foreach (Item item in items) { message.Write(item.ID); } } public void ReadNetworkData(Lidgren.Network.NetBuffer message) { var itemCount = message.ReadByte(); for (int i = 0; i