Files
zzz_REBIRTH__Utils/Score/RemoteCrafting/Scripts/RemoteCraftingUtils.cs
2025-06-04 16:44:53 +09:30

281 lines
10 KiB
C#

using JetBrains.Annotations;
using System.Collections.Generic;
using System.Linq;
namespace Rebirth.RemoteCrafting
{
[UsedImplicitly]
public class RemoteCraftingUtils
{
public static List<TileEntity> GetTileEntities(EntityAlive player)
{
var distance = 150f;
var tileEntities = RebirthUtilities.GetTileEntities(player, distance);
return tileEntities;
}
public static bool DisableSender(IEnumerable<string> 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<ItemStack> SearchNearbyContainers(EntityAlive player)
{
var items = new List<ItemStack>();
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<ItemStack> SearchNearbyContainers(EntityAlive player, ItemValue itemValue)
{
var item = new List<ItemStack>();
var items = new List<ItemStack>();
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<ItemStack> SearchNearbyContainers(EntityAlive player, ItemValue itemValue, float distance)
{
var item = new List<ItemStack>();
var items = new List<ItemStack>();
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<ItemStack> itemStacks, EntityPlayerLocal localPlayer, int multiplier, IList<ItemStack> _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();
}
}
}
}
}