From 518ef75133a2b44ceb7de55acba40c45928e0e1d Mon Sep 17 00:00:00 2001 From: AX3Lino Date: Thu, 24 Jul 2025 12:44:40 +0200 Subject: [PATCH] Added new item ArcaneCraftingUpgrade --- .../assets/opencomputers/lang/en_US.lang | 1 + .../assets/opencomputers/recipes/user.recipes | 8 +- .../textures/items/UpgradeArcaneCrafting.png | Bin 0 -> 593 bytes src/main/scala/li/cil/oc/Constants.scala | 1 + .../scala/li/cil/oc/client/Textures.scala | 1 + .../renderer/item/UpgradeRenderer.scala | 13 +- .../scala/li/cil/oc/common/init/Items.scala | 2 + .../common/item/UpgradeArcaneCrafting.scala | 3 + .../DriverUpgradeArcaneCrafting.scala | 36 +++ .../opencomputers/ModOpenComputers.scala | 6 + .../component/UpgradeArcaneCrafting.scala | 238 ++++++++++++++++++ 11 files changed, 305 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/textures/items/UpgradeArcaneCrafting.png create mode 100644 src/main/scala/li/cil/oc/common/item/UpgradeArcaneCrafting.scala create mode 100644 src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeArcaneCrafting.scala create mode 100644 src/main/scala/li/cil/oc/server/component/UpgradeArcaneCrafting.scala diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index 76e7a8fced..1246f2cecf 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -143,6 +143,7 @@ item.oc.UpgradeContainerUpgrade0.name=Upgrade Container (Tier 1) item.oc.UpgradeContainerUpgrade1.name=Upgrade Container (Tier 2) item.oc.UpgradeContainerUpgrade2.name=Upgrade Container (Tier 3) item.oc.UpgradeCrafting.name=Crafting Upgrade +item.oc.UpgradeArcaneCrafting.name=Arcane Crafting Upgrade item.oc.UpgradeDatabase0.name=Database Upgrade (Tier 1) item.oc.UpgradeDatabase1.name=Database Upgrade (Tier 2) item.oc.UpgradeDatabase2.name=Database Upgrade (Tier 3) diff --git a/src/main/resources/assets/opencomputers/recipes/user.recipes b/src/main/resources/assets/opencomputers/recipes/user.recipes index 69c4632ba0..dbb0b0bbb9 100644 --- a/src/main/resources/assets/opencomputers/recipes/user.recipes +++ b/src/main/resources/assets/opencomputers/recipes/user.recipes @@ -17,4 +17,10 @@ include file("default.recipes") # You can also specify custom recipes in this file directly. Have a look at the # default.recipes file to get an idea how recipes have to be structured. You'll # want to define your recipes after all includes, to avoid those overwriting -# your recipes. \ No newline at end of file +# your recipes. + +arcaneCraftingUpgrade { + input: [[ingotIron, "", ingotIron] + ["oc:circuitChip1", workbench, "oc:circuitChip1"] + [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]] +} \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/textures/items/UpgradeArcaneCrafting.png b/src/main/resources/assets/opencomputers/textures/items/UpgradeArcaneCrafting.png new file mode 100644 index 0000000000000000000000000000000000000000..40e018b557263eb0687f516b3808b6376a3f2262 GIT binary patch literal 593 zcmV-X0Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0p>|WK~y+Tm6A

4IVZpK~Ew%D+q$3r>>U%hDM-Lp+@U;H&i!fQBa&LO3f+Ul`~K;tTkxF0ZmZ*g?&y5l?40bU4g# zw3mEgjl5mans$&l8|MA55{YX=?2qha@ZsmR=L`00000NkvXXu0mjf4|V?T literal 0 HcmV?d00001 diff --git a/src/main/scala/li/cil/oc/Constants.scala b/src/main/scala/li/cil/oc/Constants.scala index 954d9a2755..32fb34bfec 100644 --- a/src/main/scala/li/cil/oc/Constants.scala +++ b/src/main/scala/li/cil/oc/Constants.scala @@ -81,6 +81,7 @@ object Constants { final val CPUTier2 = "cpu2" final val CPUTier3 = "cpu3" final val CraftingUpgrade = "craftingUpgrade" + final val ArcaneCraftingUpgrade = "arcaneCraftingUpgrade" final val ControlUnit = "cu" final val CuttingWire = "cuttingWire" final val DatabaseUpgradeTier1 = "databaseUpgrade1" diff --git a/src/main/scala/li/cil/oc/client/Textures.scala b/src/main/scala/li/cil/oc/client/Textures.scala index 2265dbe0d5..a2f24e076b 100644 --- a/src/main/scala/li/cil/oc/client/Textures.scala +++ b/src/main/scala/li/cil/oc/client/Textures.scala @@ -69,6 +69,7 @@ object Textures { val blockRackTerminalServerPresence = new ResourceLocation(Settings.resourceDomain, "textures/blocks/TerminalServerFrontPresence.png") val upgradeCrafting = new ResourceLocation(Settings.resourceDomain, "textures/model/UpgradeCrafting.png") + val upgradeArcaneCrafting = new ResourceLocation(Settings.resourceDomain, "textures/items/UpgradeArcaneCrafting.png") val upgradeGenerator = new ResourceLocation(Settings.resourceDomain, "textures/model/UpgradeGenerator.png") val upgradeInventory = new ResourceLocation(Settings.resourceDomain, "textures/model/UpgradeInventory.png") diff --git a/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala index 1b44fa01e7..55115b4a63 100644 --- a/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala @@ -14,13 +14,13 @@ import org.lwjgl.opengl.GL11 object UpgradeRenderer { lazy val craftingUpgrade = api.Items.get(Constants.ItemName.CraftingUpgrade) + lazy val arcaneCraftingUpgrade = api.Items.get(Constants.ItemName.ArcaneCraftingUpgrade) lazy val generatorUpgrade = api.Items.get(Constants.ItemName.GeneratorUpgrade) lazy val inventoryUpgrade = api.Items.get(Constants.ItemName.InventoryUpgrade) def preferredMountPoint(stack: ItemStack, availableMountPoints: java.util.Set[String]): String = { val descriptor = api.Items.get(stack) - - if (descriptor == craftingUpgrade || descriptor == generatorUpgrade || descriptor == inventoryUpgrade) { + if (descriptor == craftingUpgrade || descriptor == arcaneCraftingUpgrade || descriptor == generatorUpgrade || descriptor == inventoryUpgrade) { if (descriptor == generatorUpgrade && availableMountPoints.contains(MountPointName.BottomBack)) MountPointName.BottomBack else if (descriptor == inventoryUpgrade && availableMountPoints.contains(MountPointName.TopBack)) MountPointName.TopBack else MountPointName.Any @@ -31,7 +31,7 @@ object UpgradeRenderer { def canRender(stack: ItemStack): Boolean = { val descriptor = api.Items.get(stack) - descriptor == craftingUpgrade || descriptor == generatorUpgrade || descriptor == inventoryUpgrade + descriptor == craftingUpgrade || descriptor == arcaneCraftingUpgrade || descriptor == generatorUpgrade || descriptor == inventoryUpgrade } def render(stack: ItemStack, mountPoint: MountPoint): Unit = { @@ -44,6 +44,13 @@ object UpgradeRenderer { RenderState.checkError(getClass.getName + ".renderItem: crafting upgrade") } + else if (descriptor == api.Items.get(Constants.ItemName.ArcaneCraftingUpgrade)) { + Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.upgradeArcaneCrafting) + drawSimpleBlock(mountPoint) + + RenderState.checkError(getClass.getName + ".renderItem: arcane crafting upgrade") + } + else if (descriptor == api.Items.get(Constants.ItemName.GeneratorUpgrade)) { Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.upgradeGenerator) drawSimpleBlock(mountPoint, if (Item.dataTag(stack).getInteger("remainingTicks") > 0) 0.5f else 0) diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index 2d5e376e8e..a54cba4047 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -241,6 +241,7 @@ object Items extends ItemAPI { safeGetStack(Constants.ItemName.TankUpgrade), safeGetStack(Constants.ItemName.TankControllerUpgrade), safeGetStack(Constants.ItemName.CraftingUpgrade), + safeGetStack(Constants.ItemName.ArcaneCraftingUpgrade), safeGetStack(Constants.ItemName.HoverUpgradeTier2), safeGetStack(Constants.ItemName.TradingUpgrade), safeGetStack(Constants.ItemName.ExperienceUpgrade), @@ -553,6 +554,7 @@ object Items extends ItemAPI { Recipes.addSubItem(new item.UpgradeRITEG(multi), Constants.ItemName.RITEGUpgrade, "oc:rtgUpgrade") Recipes.addSubItem(new item.TpsCard(multi), Constants.ItemName.TpsCard, "oc:tpsCard") + Recipes.addSubItem(new item.UpgradeArcaneCrafting(multi), Constants.ItemName.ArcaneCraftingUpgrade, "oc:arcaneCraftingUpgrade") // Register aliases. for ((k, v) <- aliases) { diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeArcaneCrafting.scala b/src/main/scala/li/cil/oc/common/item/UpgradeArcaneCrafting.scala new file mode 100644 index 0000000000..e3e13757a2 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/UpgradeArcaneCrafting.scala @@ -0,0 +1,3 @@ +package li.cil.oc.common.item + +class UpgradeArcaneCrafting(val parent: Delegator) extends traits.Delegate with traits.ItemTier diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeArcaneCrafting.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeArcaneCrafting.scala new file mode 100644 index 0000000000..f2a3f84b03 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeArcaneCrafting.scala @@ -0,0 +1,36 @@ +package li.cil.oc.integration.opencomputers + +import li.cil.oc.Constants +import li.cil.oc.api +import li.cil.oc.api.driver.EnvironmentProvider +import li.cil.oc.api.driver.item.HostAware +import li.cil.oc.api.internal.Robot +import li.cil.oc.api.network.EnvironmentHost +import li.cil.oc.common.Slot +import li.cil.oc.common.Tier +import li.cil.oc.server.component +import net.minecraft.item.ItemStack + +object DriverUpgradeArcaneCrafting extends Item with HostAware { + override def worksWith(stack: ItemStack) = isOneOf(stack, + api.Items.get(Constants.ItemName.ArcaneCraftingUpgrade)) + + override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = + if (host.world != null && host.world.isRemote) null + else host match { + case robot: EnvironmentHost with Robot => new component.UpgradeArcaneCrafting(robot) + case _ => null + } + + override def slot(stack: ItemStack) = Slot.Upgrade + + override def tier(stack: ItemStack) = Tier.Three + + object Provider extends EnvironmentProvider { + override def getEnvironment(stack: ItemStack): Class[_] = + if (worksWith(stack)) + classOf[component.UpgradeArcaneCrafting] + else null + } + +} diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala index 86f2a58e1c..a0f6678114 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala @@ -156,6 +156,7 @@ object ModOpenComputers extends ModProxy { api.Driver.add(DriverUpgradeBattery) api.Driver.add(DriverUpgradeChunkloader) api.Driver.add(DriverUpgradeCrafting) + api.Driver.add(DriverUpgradeArcaneCrafting) api.Driver.add(DriverUpgradeDatabase) api.Driver.add(DriverUpgradeExperience) api.Driver.add(DriverUpgradeGenerator) @@ -195,6 +196,7 @@ object ModOpenComputers extends ModProxy { api.Driver.add(DriverUpgradeChunkloader.Provider) api.Driver.add(DriverUpgradeCrafting.Provider) + api.Driver.add(DriverUpgradeArcaneCrafting.Provider) api.Driver.add(DriverUpgradeDatabase.Provider) api.Driver.add(DriverUpgradeExperience.Provider) api.Driver.add(DriverUpgradeGenerator.Provider) @@ -227,6 +229,7 @@ object ModOpenComputers extends ModProxy { Constants.ItemName.BatteryUpgradeTier3, Constants.ItemName.ChunkloaderUpgrade, Constants.ItemName.CraftingUpgrade, + Constants.ItemName.ArcaneCraftingUpgrade, Constants.ItemName.ExperienceUpgrade, Constants.ItemName.GeneratorUpgrade, Constants.ItemName.HoverUpgradeTier1, @@ -260,6 +263,7 @@ object ModOpenComputers extends ModProxy { Constants.ItemName.RedstoneCardTier1, Constants.ItemName.AngelUpgrade, Constants.ItemName.CraftingUpgrade, + Constants.ItemName.ArcaneCraftingUpgrade, Constants.ItemName.HoverUpgradeTier1, Constants.ItemName.HoverUpgradeTier2, Constants.ItemName.BeekeeperUpgrade, @@ -277,6 +281,7 @@ object ModOpenComputers extends ModProxy { Constants.ItemName.GraphicsCardTier3, Constants.ItemName.AngelUpgrade, Constants.ItemName.CraftingUpgrade, + Constants.ItemName.ArcaneCraftingUpgrade, Constants.ItemName.DatabaseUpgradeTier1, Constants.ItemName.DatabaseUpgradeTier2, Constants.ItemName.DatabaseUpgradeTier3, @@ -313,6 +318,7 @@ object ModOpenComputers extends ModProxy { Constants.ItemName.AngelUpgrade, Constants.ItemName.ChunkloaderUpgrade, Constants.ItemName.CraftingUpgrade, + Constants.ItemName.ArcaneCraftingUpgrade, Constants.ItemName.DatabaseUpgradeTier1, Constants.ItemName.DatabaseUpgradeTier2, Constants.ItemName.DatabaseUpgradeTier3, diff --git a/src/main/scala/li/cil/oc/server/component/UpgradeArcaneCrafting.scala b/src/main/scala/li/cil/oc/server/component/UpgradeArcaneCrafting.scala new file mode 100644 index 0000000000..bc01cd73b8 --- /dev/null +++ b/src/main/scala/li/cil/oc/server/component/UpgradeArcaneCrafting.scala @@ -0,0 +1,238 @@ +package li.cil.oc.server.component + +import java.util + +import cpw.mods.fml.common.FMLCommonHandler +import li.cil.oc.Constants +import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute +import li.cil.oc.api.driver.DeviceInfo.DeviceClass +import li.cil.oc.api.Network +import li.cil.oc.api.driver.DeviceInfo +import li.cil.oc.api.network.EnvironmentHost +import li.cil.oc.api.internal +import li.cil.oc.api.machine.Arguments +import li.cil.oc.api.machine.Callback +import li.cil.oc.api.machine.Context +import li.cil.oc.api.network._ +import li.cil.oc.api.prefab +import li.cil.oc.server.agent.Player +import li.cil.oc.util.InventoryUtils +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.inventory +import net.minecraft.inventory.IInventory +import net.minecraft.item.ItemStack +import net.minecraft.item.crafting.CraftingManager +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent +import net.minecraft.server.MinecraftServer +import scala.collection.mutable +import scala.util.control.Breaks._ +import thaumcraft.api.ThaumcraftApi +import thaumcraft.api.crafting.IArcaneRecipe +import scala.collection.JavaConverters._ +import thaumcraft.common.tiles.TileMagicWorkbench +import thaumcraft.api.ThaumcraftApiHelper +import thaumcraft.common.items.wands.ItemWandCasting +import thaumcraft.api.aspects.Aspect +import scala.collection.convert.WrapAsJava._ + + +class UpgradeArcaneCrafting(val host: EnvironmentHost with internal.Robot) extends prefab.ManagedEnvironment with DeviceInfo { + override val node = Network.newNode(this, Visibility.Network). + withComponent("crafting"). + create() + + private final lazy val deviceInfo = Map( + DeviceAttribute.Class -> DeviceClass.Generic, + DeviceAttribute.Description -> "Assembly controller", + DeviceAttribute.Vendor -> Constants.DeviceInfo.DefaultVendor, + DeviceAttribute.Product -> "MultiCombinator-9S" + ) + + override def getDeviceInfo: util.Map[String, String] = deviceInfo + + @Callback(doc = """function([count:number]):number -- Tries to craft the specified number of items in the top left area of the inventory.""") + def craft(context: Context, args: Arguments): Array[AnyRef] = { + val count = args.optInteger(0, 64) max 0 min 64 + result(CraftingInventory.craft(count): _*) + } + + private object CraftingInventory extends inventory.InventoryCrafting(new inventory.Container { + override def canInteractWith(player: EntityPlayer) = true + }, 3, 3) { + var amountPossible = 0 + + def craft(wantedCount: Int): Seq[_] = { + var player = host.player + val wandSlotIndex = 12 // Change this if your wand is in a different slot + val workbenchTile = new TileMagicWorkbench() // Simulate arcane workbench for ThaumcraftApi + val real_player = getRealPlayer + + load(player.inventory) + loadArcane(player.inventory, workbenchTile) + val cm = CraftingManager.getInstance + var countCrafted = 0 + + // Find matching arcane recipe, if any + val recipes = ThaumcraftApi.getCraftingRecipes.asInstanceOf[java.util.List[Any]].asScala + val arcaneRecipeOpt = recipes.collectFirst { + case arc: IArcaneRecipe if arc.matches(workbenchTile, host.world, real_player) => arc + } + val isArcaneTime = arcaneRecipeOpt.isDefined + val arcaneRecipe = arcaneRecipeOpt.orNull + + val originalCraft = + if (isArcaneTime && arcaneRecipe.matches(workbenchTile, host.world, real_player)) arcaneRecipe.getCraftingResult(workbenchTile) + else cm.findMatchingRecipe(CraftingInventory, host.world) + if (originalCraft == null) { + return Seq(false, 0) + } + breakable { + while (countCrafted < wantedCount) { + val result = + if (isArcaneTime && arcaneRecipe.matches(workbenchTile, host.world, real_player)) arcaneRecipe.getCraftingResult(workbenchTile) + else cm.findMatchingRecipe(CraftingInventory, host.world) + if (result == null || result.stackSize < 1) break() + if (!originalCraft.isItemEqual(result)) { + break() + } + + if (isArcaneTime) { + // Arcane path: vis manipulation + val wand = getWandFromToolSlot() + if (wand == null) return Seq(false, countCrafted, "no wand in slot 12") + if (!checkVis(wand, arcaneRecipe, workbenchTile, real_player)) return Seq(false, countCrafted, "not enough vis for craft: ") + deductVis(wand, arcaneRecipe, workbenchTile, real_player) + } + + countCrafted += result.stackSize + FMLCommonHandler.instance.firePlayerCraftingEvent(real_player, result, this) + + val surplus = mutable.ArrayBuffer.empty[ItemStack] + for (slot <- 0 until getSizeInventory) { + val stack = getStackInSlot(slot) + if (stack != null) { + decrStackSize(slot, 1) + val item = stack.getItem + if (item.hasContainerItem(stack)) { + val container = item.getContainerItem(stack) + if (container.isItemStackDamageable && container.getItemDamage > container.getMaxDamage) { + MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(player, container)) + } + else if (container.getItem.doesContainerItemLeaveCraftingGrid(container) || getStackInSlot(slot) != null) { + surplus += container + } + else { + setInventorySlotContents(slot, container) + } + } + } + } + save(player.inventory) + InventoryUtils.addToPlayerInventory(result, player) + for (stack <- surplus) { + InventoryUtils.addToPlayerInventory(stack, player) + } + load(player.inventory) + if (isArcaneTime) loadArcane(player.inventory, workbenchTile) + } + } + Seq(originalCraft != null, countCrafted, if (isArcaneTime) "arcane crafting completed" else "normal crafting completed") + } + + def load(inventory: IInventory) { + amountPossible = Int.MaxValue + for (slot <- 0 until getSizeInventory) { + val stack = inventory.getStackInSlot(toParentSlot(slot)) + setInventorySlotContents(slot, stack) + if (stack != null) { + amountPossible = math.min(amountPossible, stack.stackSize) + } + } + } + + def save(inventory: IInventory) { + for (slot <- 0 until getSizeInventory) { + inventory.setInventorySlotContents(toParentSlot(slot), getStackInSlot(slot)) + } + } + + private def toParentSlot(slot: Int) = { + val col = slot % 3 + val row = slot / 3 + row * 4 + col + } + + // --- Arcane helpers --- + def getWandFromToolSlot(): ItemStack = { + val wandSlot = host.mainInventory.getStackInSlot(12) + if (wandSlot != null && wandSlot.getItem.getClass.getName.contains("Wand")) return wandSlot + null + } + + // Loads items into arcane crafting table inventory for futher processes + def loadArcane(inventory: IInventory, workbenchTile: TileMagicWorkbench): Unit = { + for (slot <- 0 until 9) { + val stack = inventory.getStackInSlot(toParentSlot(slot)) + workbenchTile.setInventorySlotContentsSoftly(slot, if (stack != null) stack.copy() else null) + } + } + + // Real player for reasearch and vis calculation + def getRealPlayer: EntityPlayer = { + val world = host.world + val playerName = try { + val n = host.player.getCommandSenderName + if (n != null && n.nonEmpty) n else null + } catch { case _: Throwable => null } + val playerInWorld = world.playerEntities.asScala.collectFirst { + case p: EntityPlayer if p.getCommandSenderName == playerName => p + } + if (playerInWorld.isDefined) return playerInWorld.get + val server = MinecraftServer.getServer + if (server != null) { + val playerMP = server.getConfigurationManager.func_152612_a(playerName) + if (playerMP != null) return playerMP + } + world.playerEntities.asScala.collectFirst { + case p: EntityPlayer if !p.getCommandSenderName.toLowerCase.contains("[oc]") => p + }.orNull + } + + + // Check if wand/scepter does have enought vis + def checkVis(wand: ItemStack, arcaneRecipe: IArcaneRecipe, workbenchTile: TileMagicWorkbench, player: EntityPlayer): Boolean = { + val requiredAspectsList = Option(arcaneRecipe.getAspects(workbenchTile)) + val requiredAspects = requiredAspectsList.filter(_ != null).map(_.getAspects.map(a => a.getTag -> requiredAspectsList.get.getAmount(a)).toMap).getOrElse(Map.empty) + val wandItem = wand.getItem.asInstanceOf[ItemWandCasting] + val wandAspectList = wandItem.getAllVis(wand) + var hasAll = true + for ((aspectTag, baseVis) <- requiredAspects) { + val aspect = Aspect.getAspect(aspectTag) + val requiredVis = (baseVis * 100 * wandItem.getConsumptionModifier(wand, player, aspect, true)).toInt + val wandAmount = wandAspectList.getAmount(aspect) + if (wandAmount < requiredVis) { + hasAll = false + } + } + hasAll + } + + // Syphon vis from wand/scepter based on craft + def deductVis(wand: ItemStack, arcaneRecipe: IArcaneRecipe, workbenchTile: TileMagicWorkbench, player: EntityPlayer): Unit = { + val requiredAspectsList = Option(arcaneRecipe.getAspects(workbenchTile)) + val requiredAspects = requiredAspectsList.filter(_ != null).map(_.getAspects.map(a => a.getTag -> requiredAspectsList.get.getAmount(a)).toMap).getOrElse(Map.empty) + val wandItem = wand.getItem.asInstanceOf[ItemWandCasting] + for ((aspectTag, baseVis) <- requiredAspects) { + val aspect = Aspect.getAspect(aspectTag) + val requiredVis = (baseVis * 100 * wandItem.getConsumptionModifier(wand, player, aspect, true)).toInt + val tag = aspect.getTag + if (wand.getTagCompound.hasKey(tag)) { + val current = wand.getTagCompound.getInteger(tag) + val newValue = Math.max(0, current - requiredVis) + wand.getTagCompound.setInteger(tag, newValue) + } + } + } + } +}