using JetBrains.Annotations; using System.Collections.Generic; using System.Linq; namespace Rebirth.RemoteCrafting { [UsedImplicitly] public class RemoteCraftingUtils { public static List GetTileEntities(EntityAlive player) { var distance = 150f; var tileEntities = RebirthUtilities.GetTileEntities(player, distance); return tileEntities; } public static bool DisableSender(IEnumerable value, TileEntity tileEntity) { if (tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) { if (value.All(x => x.Trim() != storage.lootListName)) { return true; } } else { return false; } return false; } private static bool BindToWorkstation(string value, EntityAlive player, TileEntity tileEntity) { var result = false; if (player is not EntityPlayerLocal playerLocal) return false; if (!tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) return false; // TODO: we want to refactor this to remove the complex LinQ. // what could be easier than linq? // bind storage to workstation if (value.Split(';').Where(x => x.Split(':')[0].Split(',').Any(ws => ws.Trim() == playerLocal.PlayerUI.xui.currentWorkstation)) .Any(x => x.Split(':')[1].Split(',').Any(y => y == storage.lootListName))) result = true; // bind storage to other workstations if allowed if (value.Split(';').Any(x => x.Split(':')[0].Split(',').Any(ws => ws.Trim() == playerLocal.PlayerUI.xui.currentWorkstation))) return result; { if (value.Split(';').Any(x => x.Split(':')[1].Split(',').Any(y => y == storage.lootListName))) { result = false; } else { result = true; } } return result; } private static bool NotToWorkstation(string value, EntityAlive player, TileEntity tileEntity) { var result = false; if (player is not EntityPlayerLocal playerLocal) return false; if (!tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) return false; foreach (var bind in value.Split(';')) { var workstation = bind.Split(':')[0].Split(','); var disablebinding = bind.Split(':')[1].Split(','); if ((workstation.Any(ws => ws.Trim() == playerLocal.PlayerUI.xui.currentWorkstation)) && (disablebinding.Any(x => x.Trim() == storage.lootListName))) result = true; } return result; } public static List SearchNearbyContainers(EntityAlive player) { var items = new List(); var tileEntities = GetTileEntities(player); foreach (var tileEntity in tileEntities) { if (!tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) continue; if (storage.IsUserAccessing()) continue; items.AddRange(storage.items); } return items; } public static List SearchNearbyContainers(EntityAlive player, ItemValue itemValue) { var item = new List(); var items = new List(); var tileEntities = GetTileEntities(player); foreach (var tileEntity in tileEntities) { if (!tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) continue; // If the container is open, don't use it. if (storage.IsUserAccessing()) continue; item.AddRange(storage.items); } foreach (var t in item) { if ((!t.itemValue.HasModSlots || !t.itemValue.HasMods()) && t.itemValue.type == itemValue.type) { items.Add(t); } } return items; } public static List SearchNearbyContainers(EntityAlive player, ItemValue itemValue, float distance) { var item = new List(); var items = new List(); var tileEntities = RebirthUtilities.GetTileEntities(player, distance); foreach (var tileEntity in tileEntities) { if (tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) { if (storage.IsUserAccessing()) continue; item.AddRange(storage.items); } } foreach (var t in item) { if ((!t.itemValue.HasModSlots || !t.itemValue.HasMods()) && t.itemValue.type == itemValue.type) { items.Add(t); } } return items; } public static bool AddToNearbyContainer(EntityAlive player, ItemStack itemStack, float distance) { var tileEntities = RebirthUtilities.GetTileEntities(player, distance); foreach (var tileEntity in tileEntities) { if (!tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) continue; // If the container is open, don't include it. if (storage.IsUserAccessing()) continue; // Don't try to add to a drop box. if (storage.blockValue.Block.Properties.Values.ContainsKey("DropBox")) continue; // Can we quickly find a incomplete stack? //if (lootTileEntity.TryStackItem(0, itemStack)) return true; var result = storage.TryStackItem(0, itemStack); if (result.allMoved) return true; var matchingItem = false; // Loop through the items and see if we have any matching items. foreach (var item in storage.items) { // We match with something. if (item.itemValue.type != itemStack.itemValue.type) continue; matchingItem = true; break; } // If we don't match, don't try to add. if (!matchingItem) continue; // We added a full stack! No need to keep processing. if (storage.AddItem(itemStack)) return true; } return false; } public static void ConsumeItem(IEnumerable itemStacks, EntityPlayerLocal localPlayer, int multiplier, IList _removedItems, Bag bag, Inventory toolbelt) { var tileEntities = GetTileEntities(localPlayer); var enumerable = itemStacks as ItemStack[] ?? itemStacks.ToArray(); for (var i = 0; i < enumerable.Count(); i++) { // Grab from the backpack first. var num = enumerable[i].count * multiplier; if (bag != null) { num -= bag.DecItem(enumerable[i].itemValue, num, true, _removedItems); if (num > 0) { // Check tool belt if (toolbelt != null) { num -= toolbelt.DecItem(enumerable[i].itemValue, num, true, _removedItems); } } } // We've met our goals for this. if (num <= 0) continue; // check storage boxes foreach (var tileEntity in tileEntities) { if (num <= 0) break; if (!tileEntity.TryGetSelfOrFeature(out ITileEntityLootable storage)) continue; // If someone is using the tool account, skip it. if (storage.IsUserAccessing()) continue; // If there's no items in this container, skip. if (!storage.HasItem(enumerable[i].itemValue)) continue; for (var y = 0; y < storage.items.Length; y++) { var item = storage.items[y]; if (item.IsEmpty()) continue; if (item.itemValue.ItemClass != enumerable[i].itemValue.ItemClass) continue; // If we can completely satisfy the result, let's do that. if (item.count >= num) { item.count -= num; // Add the item to the removed items list so we can return it. _removedItems.Add(new ItemStack(item.itemValue.Clone(), num)); num = 0; } else { // Otherwise, let's just count down until we meet the requirement. while (num >= 0) { item.count--; num--; if (item.count <= 0) { _removedItems.Add(new ItemStack(item.itemValue.Clone(), num)); break; } } } //Update the slot on the container, and do the Setmodified(), so that the dedis can get updated. if (item.count < 1) { // Add it to the removed list. _removedItems.Add(item.Clone()); storage.UpdateSlot(y, ItemStack.Empty.Clone()); } else { storage.UpdateSlot(y, item); } } storage.SetModified(); } } } } }