using HarmonyLib; using System.Collections.Generic; using System.Linq; using SCore.Features.RemoteCrafting.Scripts; using UnityEngine; namespace Features.RemoteCrafting { /// /// Patches to support repairing from remote storage /// public class ItemActionRepairPatches { private const string AdvFeatureClass = "BlockUpgradeRepair"; private const string Feature = "ReadFromContainers"; 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, BlockValue blockValue) { if (!Configuration.CheckFeatureStatus(AdvFeatureClass, Feature)) return true; var block = blockValue.Block; var itemValue = ItemClass.GetItem(__instance.GetUpgradeItemName(block), false); int num; if (!int.TryParse(block.Properties.Values[Block.PropUpgradeBlockClassItemCount], out num)) { return false; } if (data.holdingEntity.inventory.DecItem(itemValue, num) == num) { var entityPlayerLocal = data.holdingEntity as EntityPlayerLocal; if (entityPlayerLocal != null && num != 0) { entityPlayerLocal.AddUIHarvestingItem(new ItemStack(itemValue, -num)); } __result = true; return false; } if (data.holdingEntity.bag.DecItem(itemValue, num) == num) { var entityPlayerLocal2 = data.holdingEntity as EntityPlayerLocal; if (entityPlayerLocal2 != null) { entityPlayerLocal2.AddUIHarvestingItem(new ItemStack(itemValue, -num)); } __result = true; return false; } var primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer(); var distance = 30f; var strDistance = Configuration.GetPropertyValue(AdvFeatureClass, "Distance"); if (!string.IsNullOrEmpty(strDistance)) distance = StringParsers.ParseFloat(strDistance); var tileEntities = RemoteCraftingUtils.GetTileEntities(primaryPlayer, distance); // counter quantity needed from item var q = num; var itemStack = new ItemStack(ItemClass.GetItem(__instance.GetUpgradeItemName(block)), num); //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.TryGetSelfOrFeature(out var 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, -num)); __result = true; return false; } } [HarmonyPatch(typeof(ItemActionRepair))] [HarmonyPatch("CanRemoveRequiredResource")] public class CanRemoveRequiredResource { private static void Postfix(ref bool __result, ItemActionRepair __instance, ItemInventoryData data, BlockValue blockValue) { if (__result) return; if (Configuration.CheckFeatureStatus(AdvFeatureClass, "BlockOnNearbyEnemies")) { var distanceE = 30f; var strDistanceE = Configuration.GetPropertyValue(AdvFeatureClass, "DistanceEnemy"); if (!string.IsNullOrEmpty(strDistanceE)) distanceE = StringParsers.ParseFloat(strDistanceE); if (RemoteCraftingUtils.IsEnemyNearby(data.holdingEntity, distanceE)) { return; // make sure you only skip if really necessary } } if (!Configuration.CheckFeatureStatus(AdvFeatureClass, Feature)) { return; } var primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer(); var block = blockValue.Block; var upgradeItemName = __instance.GetUpgradeItemName(block); int quantity; if (!int.TryParse(block.Properties.Values[Block.PropUpgradeBlockClassItemCount], out quantity)) { return; } var itemStack = new ItemStack(ItemClass.GetItem(upgradeItemName), quantity); var distance = 30f; var strDistance = Configuration.GetPropertyValue(AdvFeatureClass, "Distance"); if (!string.IsNullOrEmpty(strDistance)) distance = StringParsers.ParseFloat(strDistance); var totalCount = RemoteCraftingUtils .SearchNearbyContainers(primaryPlayer, itemStack.itemValue, distance).Sum(y => y.count); if (totalCount >= quantity) { __result = true; return; } __result = false; } } [HarmonyPatch(typeof(ItemActionRepair))] [HarmonyPatch("removeRequiredItem")] public class RemoveRequiredItem { private static bool Prefix(ref bool __result, ItemActionRepair __instance, ItemInventoryData _data, ItemStack _itemStack) { __result = false; if (!Configuration.CheckFeatureStatus(AdvFeatureClass, Feature)) { return true; } __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 = 30f; var strDistance = Configuration.GetPropertyValue(AdvFeatureClass, "Distance"); if (!string.IsNullOrEmpty(strDistance)) distance = StringParsers.ParseFloat(strDistance); 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.TryGetSelfOrFeature(out var 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 (Configuration.CheckFeatureStatus(AdvFeatureClass, "BlockOnNearbyEnemies")) { var distanceE = 30f; var strDistanceE = Configuration.GetPropertyValue(AdvFeatureClass, "DistanceEnemy"); if (!string.IsNullOrEmpty(strDistanceE)) distanceE = StringParsers.ParseFloat(strDistanceE); if (RemoteCraftingUtils.IsEnemyNearby(_data.holdingEntity, distanceE)) { __result = false; return false; // make sure you only skip if really necessary } } if (!Configuration.CheckFeatureStatus(AdvFeatureClass, Feature)) { return true; } 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 = 30f; var strDistance = Configuration.GetPropertyValue(AdvFeatureClass, "Distance"); if (!string.IsNullOrEmpty(strDistance)) distance = StringParsers.ParseFloat(strDistance); var totalCount = RemoteCraftingUtils .SearchNearbyContainers(primaryPlayer, _itemStack.itemValue, distance).Sum(y => y.count); if (totalCount <= 0) return false; __result = true; return false; } } } }