using HarmonyLib; using Rebirth.RemoteCrafting; using System.Collections.Generic; using System.Linq; using UnityEngine; // todo - fix as methods have changed namespace Features.RemoteCrafting { /// /// Patches to support repairing from remote storage /// public class ItemActionRepairPatches { private struct UpgradeInfo { public string FromBlock; public string ToBlock; public string Item; public int ItemCount; public string Sound; public int Hits; } [HarmonyPatch(typeof(ItemActionRepair))] [HarmonyPatch("RemoveRequiredResource")] public class RemoveRequiredResource { private static bool Prefix(ref bool __result, ItemActionRepair __instance, ItemInventoryData data, UpgradeInfo ___currentUpgradeInfo) { if (string.IsNullOrEmpty(___currentUpgradeInfo.Item)) { __result = true; return false; } var itemValue = ItemClass.GetItem(___currentUpgradeInfo.Item); if (data.holdingEntity.inventory.DecItem(itemValue, ___currentUpgradeInfo.ItemCount) == ___currentUpgradeInfo.ItemCount) { var entityPlayerLocal = data.holdingEntity as EntityPlayerLocal; if (entityPlayerLocal != null && ___currentUpgradeInfo.ItemCount != 0) { entityPlayerLocal.AddUIHarvestingItem(new ItemStack(itemValue, -___currentUpgradeInfo.ItemCount)); } __result = true; return false; } if (data.holdingEntity.bag.DecItem(itemValue, ___currentUpgradeInfo.ItemCount) == ___currentUpgradeInfo.ItemCount) { var entityPlayerLocal2 = data.holdingEntity as EntityPlayerLocal; if (entityPlayerLocal2 != null) { entityPlayerLocal2.AddUIHarvestingItem(new ItemStack(itemValue, -___currentUpgradeInfo.ItemCount)); } __result = true; return false; } var primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer(); var distance = 150f; var tileEntities = RemoteCraftingUtils.GetTileEntities(primaryPlayer, distance); // counter quantity needed from item var q = ___currentUpgradeInfo.ItemCount; var itemStack = new ItemStack(ItemClass.GetItem(___currentUpgradeInfo.Item, false), ___currentUpgradeInfo.ItemCount); //check player inventory for materials and reduce counter var slots = primaryPlayer.bag.GetSlots(); q = q - slots .Where(x => x.itemValue.ItemClass == itemStack.itemValue.ItemClass) .Sum(y => y.count); // check storage boxes foreach (var tileEntity in tileEntities) { if (q <= 0) break; if (tileEntity is not TileEntityLootContainer lootTileEntity) continue; // If there's no items in this container, skip. if (!lootTileEntity.HasItem(itemStack.itemValue)) continue; for (var y = 0; y < lootTileEntity.items.Length; y++) { var item = lootTileEntity.items[y]; if (item.IsEmpty()) continue; if (item.itemValue.ItemClass != itemStack.itemValue.ItemClass) continue; // If we can completely satisfy the result, let's do that. if (item.count >= q) { item.count -= q; q = 0; } else { // Otherwise, let's just count down until we meet the requirement. while (q >= 0) { item.count--; q--; if (item.count <= 0) break; } } //Update the slot on the container, and do the Setmodified(), so that the dedis can get updated. if (item.count < 1) lootTileEntity.UpdateSlot(y, ItemStack.Empty.Clone()); else lootTileEntity.UpdateSlot(y, item); lootTileEntity.SetModified(); } } primaryPlayer.AddUIHarvestingItem(new ItemStack(itemValue, -___currentUpgradeInfo.ItemCount), false); __result = true; return false; } } [HarmonyPatch(typeof(ItemActionRepair))] [HarmonyPatch("CanRemoveRequiredResource")] public class CanRemoveRequiredResource { private static bool Prefix(ref bool __result, ItemActionRepair __instance, ItemInventoryData data, BlockValue blockValue, ref UpgradeInfo ___currentUpgradeInfo, string ___allowedUpgradeItems, string ___restrictedUpgradeItems, string ___upgradeActionSound, float ___hitCountOffset) { var block = blockValue.Block; var flag = block.Properties.Values.ContainsKey("UpgradeBlock.Item"); var upgradeInfo = default(UpgradeInfo); upgradeInfo.FromBlock = block.GetBlockName(); upgradeInfo.ToBlock = block.Properties.Values[Block.PropUpgradeBlockClassToBlock]; upgradeInfo.Sound = ""; if (flag) { upgradeInfo.Item = block.Properties.Values["UpgradeBlock.Item"]; if (___allowedUpgradeItems.Length > 0 && !___allowedUpgradeItems.ContainsCaseInsensitive(upgradeInfo.Item)) { __result = false; return false; } if (___restrictedUpgradeItems.Length > 0 && ___restrictedUpgradeItems.ContainsCaseInsensitive(upgradeInfo.Item)) { __result = false; return false; } } if (___upgradeActionSound.Length > 0) { upgradeInfo.Sound = ___upgradeActionSound; } else if (flag) { var item = ItemClass.GetItem(upgradeInfo.Item); if (item != null) { var itemClass = ItemClass.GetForId(item.type); if (itemClass != null) { upgradeInfo.Sound = $"ImpactSurface/{data.holdingEntity.inventory.holdingItem.MadeOfMaterial.SurfaceCategory}hit{itemClass.MadeOfMaterial.SurfaceCategory}"; } } } if (!int.TryParse(block.Properties.Values["UpgradeBlock.UpgradeHitCount"], out var num)) { __result = false; return false; } upgradeInfo.Hits = (int)(num + ___hitCountOffset < 1f ? 1f : num + ___hitCountOffset); if (!int.TryParse(block.Properties.Values[Block.PropUpgradeBlockClassItemCount], out upgradeInfo.ItemCount) && flag) { __result = false; return false; } ___currentUpgradeInfo = upgradeInfo; if (___currentUpgradeInfo.FromBlock != null && flag) { var item = ItemClass.GetItem(___currentUpgradeInfo.Item, false); if (data.holdingEntity.inventory.GetItemCount(item) >= ___currentUpgradeInfo.ItemCount) { __result = true; return false; } if (data.holdingEntity.bag.GetItemCount(item) >= ___currentUpgradeInfo.ItemCount) { __result = true; return false; } } else if (!flag) { __result = true; return false; } var primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer(); var itemStack = new ItemStack(ItemClass.GetItem(___currentUpgradeInfo.Item), ___currentUpgradeInfo.ItemCount); var distance = 150f; var totalCount = RemoteCraftingUtils.SearchNearbyContainers(primaryPlayer, itemStack.itemValue, distance).Sum(y => y.count); if (totalCount >= ___currentUpgradeInfo.ItemCount) { __result = true; return false; } __result = false; return false; } } [HarmonyPatch(typeof(ItemActionRepair))] [HarmonyPatch("removeRequiredItem")] public class RemoveRequiredItem { private static bool Prefix(ref bool __result, ItemActionRepair __instance, ItemInventoryData _data, ItemStack _itemStack) { __result = false; __result = _data.holdingEntity.inventory.DecItem(_itemStack.itemValue, _itemStack.count) == _itemStack.count || _data.holdingEntity.bag.DecItem(_itemStack.itemValue, _itemStack.count, false) == _itemStack.count; if (__result) { return false; } var primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer(); var distance = 150f; var tileEntities = RemoteCraftingUtils.GetTileEntities(primaryPlayer, distance); // counter quantity needed from item var q = _itemStack.count; //check player inventory for materials and reduce counter var slots = primaryPlayer.bag.GetSlots(); q -= slots .Where(x => x.itemValue.ItemClass == _itemStack.itemValue.ItemClass) .Sum(y => y.count); // check storage boxes foreach (var tileEntity in tileEntities) { if (q <= 0) break; if (tileEntity is not TileEntityLootContainer lootTileEntity) continue; // If there's no items in this container, skip. if (!lootTileEntity.HasItem(_itemStack.itemValue)) continue; for (var y = 0; y < lootTileEntity.items.Length; y++) { var item = lootTileEntity.items[y]; if (item.IsEmpty()) continue; if (item.itemValue.ItemClass != _itemStack.itemValue.ItemClass) continue; // If we can completely satisfy the result, let's do that. if (item.count >= q) { item.count -= q; q = 0; } else { // Otherwise, let's just count down until we meet the requirement. while (q >= 0) { item.count--; q--; if (item.count <= 0) break; } } //Update the slot on the container, and do the Setmodified(), so that the dedis can get updated. if (item.count < 1) lootTileEntity.UpdateSlot(y, ItemStack.Empty.Clone()); else lootTileEntity.UpdateSlot(y, item); lootTileEntity.SetModified(); } } return false; } } [HarmonyPatch(typeof(ItemActionRepair))] [HarmonyPatch("canRemoveRequiredItem")] public class CanRemoveRequiredItem { private static bool Prefix(ref bool __result, ItemActionRepair __instance, ItemInventoryData _data, ItemStack _itemStack) { __result = false; if (_data.holdingEntity.inventory.GetItemCount(_itemStack.itemValue) >= _itemStack.count || _data.holdingEntity.bag.GetItemCount(_itemStack.itemValue) >= _itemStack.count) { __result = true; return false; } var primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer(); var distance = 150f; var totalCount = RemoteCraftingUtils.SearchNearbyContainers(primaryPlayer, _itemStack.itemValue, distance).Sum(y => y.count); if (totalCount <= 0) return false; __result = true; return false; } } } }