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/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes index b27d1f6188..c6bab1e0dd 100644 --- a/src/main/resources/assets/opencomputers/recipes/default.recipes +++ b/src/main/resources/assets/opencomputers/recipes/default.recipes @@ -249,6 +249,9 @@ beekeeperUpgrade { ["oc:circuitChip3", {item="Forestry:beealyzer"}, "oc:circuitChip3"] [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]] } +arcaneCraftingUpgrade { + input: [["oc:craftingUpgrade", {item="Thaumcraft:blockTable", subID=15}, "oc:circuitChip2"]] +} configuratorUpgrade { input: [[ingotIron, "", ingotIron] 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 0000000000..40e018b557 Binary files /dev/null and b/src/main/resources/assets/opencomputers/textures/items/UpgradeArcaneCrafting.png differ 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/integration/opencomputers/ModOpenComputers.scala b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala index 15703fc82d..54a26dc61b 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala @@ -36,6 +36,7 @@ import li.cil.oc.common.nanomachines.provider.PotionProvider import li.cil.oc.common.template._ import li.cil.oc.integration.ModProxy import li.cil.oc.integration.Mods +import li.cil.oc.integration.thaumcraft.DriverUpgradeArcaneCrafting import li.cil.oc.integration.util.BundledRedstone import li.cil.oc.integration.util.WirelessRedstone import li.cil.oc.server.machine.luac.LuaStateFactory @@ -156,6 +157,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 +197,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 +230,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 +264,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 +282,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 +319,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/integration/thaumcraft/DriverUpgradeArcaneCrafting.scala b/src/main/scala/li/cil/oc/integration/thaumcraft/DriverUpgradeArcaneCrafting.scala new file mode 100644 index 0000000000..8ac1699622 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/thaumcraft/DriverUpgradeArcaneCrafting.scala @@ -0,0 +1,34 @@ +package li.cil.oc.integration.thaumcraft + +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, ManagedEnvironment} +import li.cil.oc.common.{Slot, Tier} +import li.cil.oc.integration.opencomputers.Item +import li.cil.oc.{Constants, api} +import net.minecraft.item.ItemStack + +object DriverUpgradeArcaneCrafting extends Item with HostAware { + override def worksWith(stack: ItemStack): Boolean = isOneOf(stack, + api.Items.get(Constants.ItemName.ArcaneCraftingUpgrade)) + + override def createEnvironment(stack: ItemStack, host: EnvironmentHost): ManagedEnvironment = + if (host.world != null && host.world.isRemote) null + else host match { + case robot: EnvironmentHost with Robot => new UpgradeArcaneCrafting(robot) + case _ => null + } + + override def slot(stack: ItemStack): String = Slot.Upgrade + + override def tier(stack: ItemStack): Int = Tier.Two + + object Provider extends EnvironmentProvider { + override def getEnvironment(stack: ItemStack): Class[_] = + if (worksWith(stack)) + classOf[UpgradeArcaneCrafting] + else null + } + +} \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/integration/thaumcraft/ModThaumcraft.scala b/src/main/scala/li/cil/oc/integration/thaumcraft/ModThaumcraft.scala index 5696146854..a720b49d18 100644 --- a/src/main/scala/li/cil/oc/integration/thaumcraft/ModThaumcraft.scala +++ b/src/main/scala/li/cil/oc/integration/thaumcraft/ModThaumcraft.scala @@ -1,8 +1,17 @@ package li.cil.oc.integration.thaumcraft -import li.cil.oc.api.Driver -import li.cil.oc.integration.ModProxy -import li.cil.oc.integration.Mods +import cpw.mods.fml.common.registry.GameRegistry +import li.cil.oc.Constants +import li.cil.oc.api.{Driver, Items} +import li.cil.oc.api.driver.item.UpgradeRenderer.MountPointName +import li.cil.oc.api.event.RobotRenderEvent.MountPoint +import li.cil.oc.api.internal.Robot +import li.cil.oc.common.recipe.Recipes +import li.cil.oc.integration.{ModProxy, Mods} +import net.minecraft.item.ItemStack +import org.lwjgl.opengl.GL11 +import thaumcraft.client.lib.UtilsFX +import thaumcraft.client.renderers.models.ModelArcaneWorkbench object ModThaumcraft extends ModProxy { override def getMod = Mods.Thaumcraft @@ -10,5 +19,31 @@ object ModThaumcraft extends ModProxy { override def initialize() { Driver.add(new DriverAspectContainer) Driver.add(ConverterAspectItem) + + val multi = new li.cil.oc.common.item.Delegator() { + private lazy val workbenchModel = new ModelArcaneWorkbench + private lazy val ArcaneUpgrade = Items.get(Constants.ItemName.ArcaneCraftingUpgrade) + + override def computePreferredMountPoint(stack: ItemStack, robot: Robot, availableMountPoints: java.util.Set[String]): String = Items.get(stack) match { + case ArcaneUpgrade => MountPointName.Any + case _ => MountPointName.None + } + + override def render(stack: ItemStack, mountPoint: MountPoint, robot: Robot, pt: Float): Unit = Items.get(stack) match { + case ArcaneUpgrade => + UtilsFX.bindTexture("textures/models/worktable.png") + GL11.glRotatef(mountPoint.rotation.getW, mountPoint.rotation.getX, mountPoint.rotation.getY, mountPoint.rotation.getZ) + GL11.glTranslatef(mountPoint.offset.getX, mountPoint.offset.getY, mountPoint.offset.getZ) + GL11.glRotatef(180.0F, 1.0F, 0.0F, 0.0F) + GL11.glTranslatef(0.0F, -0.1F, 0.0F) + GL11.glScalef(0.2F, 0.2F, 0.2F) + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F) + workbenchModel.renderAll() + case _ => + } + } + + GameRegistry.registerItem(multi, "item..thaumcraft") + Recipes.addSubItem(new item.UpgradeArcaneCrafting(multi), Constants.ItemName.ArcaneCraftingUpgrade, "oc:arcaneCraftingUpgrade") } } \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/integration/thaumcraft/UpgradeArcaneCrafting.scala b/src/main/scala/li/cil/oc/integration/thaumcraft/UpgradeArcaneCrafting.scala new file mode 100644 index 0000000000..9f0f9d3ab3 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/thaumcraft/UpgradeArcaneCrafting.scala @@ -0,0 +1,320 @@ +package li.cil.oc.integration.thaumcraft + +import com.mojang.authlib.GameProfile +import cpw.mods.fml.common.{FMLCommonHandler, ObfuscationReflectionHelper} +import li.cil.oc.api.driver.DeviceInfo +import li.cil.oc.api.driver.DeviceInfo.{DeviceAttribute, DeviceClass} +import li.cil.oc.api.machine.{Arguments, Callback, Context} +import li.cil.oc.api.network._ +import li.cil.oc.api.{Network, internal, prefab} +import li.cil.oc.server.component.result +import li.cil.oc.util.InventoryUtils +import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP} +import net.minecraft.inventory +import net.minecraft.inventory.{IInventory, InventoryCrafting} +import net.minecraft.item.crafting.CraftingManager +import net.minecraft.item.{Item, ItemStack} +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.server.MinecraftServer +import net.minecraft.world.WorldServer +import net.minecraft.world.storage.SaveHandler +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.common.util.FakePlayer +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent +import net.minecraftforge.event.entity.player.PlayerEvent.LoadFromFile +import thaumcraft.api.ThaumcraftApi +import thaumcraft.api.aspects.AspectList +import thaumcraft.api.crafting.IArcaneRecipe +import thaumcraft.common.Thaumcraft +import thaumcraft.common.config.{Config, ConfigBlocks, ConfigItems} +import thaumcraft.common.items.ItemEssence +import thaumcraft.common.items.wands.ItemWandCasting +import thaumcraft.common.lib.research.ResearchManager +import thaumcraft.common.tiles.{TileMagicWorkbench, TileMagicWorkbenchCharger} + +import java.io.File +import java.util +import scala.collection.JavaConverters._ +import scala.collection.convert.WrapAsJava._ +import scala.collection.mutable.ArrayBuffer + + +class UpgradeArcaneCrafting(val host: EnvironmentHost with internal.Robot) extends prefab.ManagedEnvironment with DeviceInfo { + override val node = Network.newNode(this, Visibility.Network). + withComponent("arcane_crafting"). + create() + + private final lazy val deviceInfo = Map( + DeviceAttribute.Class -> DeviceClass.Generic, + DeviceAttribute.Description -> "Arcane matrix controller", + DeviceAttribute.Vendor -> "Thaumic Logic Industries", + DeviceAttribute.Product -> "ArcaneCombinator-X1" + ) + + override def getDeviceInfo: util.Map[String, String] = deviceInfo + + @Callback(doc = """function([count:number]):boolean, number, string -- Tries to craft the specified number of items in the top left area of the inventory using both normal and arcane recipes.""") + def craft(context: Context, args: Arguments): Array[AnyRef] = { + val wantedCount = args.optInteger(0, 64) max 0 min 64 + var res = CraftingInventory.craftNormal(wantedCount) + if (res.count == 0) res = CraftingInventory.craftArcane(wantedCount) + res.error match { + case Some(msg) => result(res.count != 0, res.count, msg) + case None => result(res.count != 0, res.count) + } + } + + @Callback(doc = """function([count:number]):boolean, number, string -- Tries to craft the specified number of items in the top left area of the inventory using only vanilla crafting recipes.""") + def craftNormal(context: Context, args: Arguments): Array[AnyRef] = { + val wantedCount = args.optInteger(0, 64) max 0 min 64 + var res = CraftingInventory.craftNormal(wantedCount) + res.error match { + case Some(msg) => result(res.count != 0, res.count, msg) + case None => result(res.count != 0, res.count) + } + } + + @Callback(doc = """function([count:number]):boolean, number, string -- Tries to craft the specified number of items in the top left area of the inventory using only Thaumcraft crafting recipes.""") + def craftArcane(context: Context, args: Arguments): Array[AnyRef] = { + val wantedCount = args.optInteger(0, 64) max 0 min 64 + var res = CraftingInventory.craftArcane(wantedCount) + res.error match { + case Some(msg) => result(res.count != 0, res.count, msg) + case None => result(res.count != 0, res.count) + } + } + + override val canUpdate = true + + private var checkDelay = 0 + + override def update(): Unit = { + super.update() + if (checkDelay > 0) { + checkDelay -= 1 + return + } + val hasWork = for { + tm <- Option(host.world().getTileEntity(host.xPosition.toInt, host.yPosition.toInt + 1, host.zPosition.toInt)) + .collect { case t: TileMagicWorkbenchCharger => t } + wandStack <- Option(host.getStackInSlot(0)) + wand <- Option(wandStack.getItem).collect { case w: ItemWandCasting => w } + } yield { + val al = wand.getAspectsWithRoom(wandStack) + if (al.size > 0) { + for (aspect <- al.getAspects) { + val drain = Math.min(5, wand.getMaxVis(wandStack) - wand.getVis(wandStack, aspect)) + if (drain > 0) wand.addRealVis(wandStack, aspect, tm.consumeVis(aspect, drain), true) + } + } + true + } + if (hasWork.isEmpty) { + checkDelay = 20 + } + } + + private object CraftingInventory extends inventory.InventoryCrafting(new inventory.Container { + override def canInteractWith(player: EntityPlayer) = true + }, 3, 3) { + def craftNormal(wantedCount: Int): CraftResult = { + craft(wantedCount) { (inv, player) => + val result = CraftingManager.getInstance.findMatchingRecipe(inv, player.worldObj) + Option(result) + .map(r => RecipeMatch(r, () => {})) + .getOrElse(RecipeNotFound) + } + } + + def craftArcane(wantedCount: Int): CraftResult = { + craft(wantedCount) { (inv, player) => + Option(findArcaneRecipe(inv, player)) match { + case Some(recipe) => + val result = recipe.getCraftingResult(inv) + val wandStack = host.getStackInSlot(0) + val aspects = Option(recipe.getAspects(inv)).getOrElse(recipe.getAspects) + + if (wandStack == null || !wandStack.getItem.isInstanceOf[ItemWandCasting]) { + RecipeMissingRequirement("Missing a valid Wand to craft.") + } else if (!consumeAllVis(wandStack, aspects, doit = false)) { + RecipeMissingRequirement("Insufficient Vis in wand to perform crafting.") + } else { + RecipeMatch(result, () => { + consumeAllVis(wandStack, aspects, doit = true) + onCrafting(result) + }) + } + case None => RecipeNotFound + } + } + } + + sealed trait RecipeResult + + case object RecipeNotFound extends RecipeResult + + case class RecipeMissingRequirement(reason: String) extends RecipeResult + + case class RecipeMatch(output: ItemStack, onCraft: () => Unit) extends RecipeResult + + case class CraftResult(count: Int = 0, error: Option[String] = None) + + def craft(wantedCount: Int)(findResult: (InventoryCrafting, EntityPlayer) => RecipeResult): CraftResult = { + val player = host.player + var countCrafted = 0 + var firstResult: ItemStack = null + + while (countCrafted < wantedCount) { + load(player.inventory) + findResult(this, player) match { + case RecipeMatch(result, onCraft) => + if (firstResult == null) firstResult = result + if (result.isItemEqual(firstResult) && result.stackSize > 0) { + onCraft() + FMLCommonHandler.instance.firePlayerCraftingEvent(player, result, this) + val surplus = consumeGrid(player) + countCrafted += result.stackSize + save(player.inventory) + InventoryUtils.addToPlayerInventory(result, player) + surplus.foreach(InventoryUtils.addToPlayerInventory(_, player)) + } + else return CraftResult(count = countCrafted) + case RecipeNotFound => + val err = if (countCrafted == 0) Some("Can't find the recipe.") else None + return CraftResult(count = countCrafted, error = err) + case RecipeMissingRequirement(error) => return CraftResult(count = countCrafted, error = Some(error)) + } + } + CraftResult(count = countCrafted) + } + + private def consumeGrid(player: EntityPlayer): ArrayBuffer[ItemStack] = { + def isDestroyed(s: ItemStack): Boolean = + s.isItemStackDamageable && s.getItemDamage > s.getMaxDamage + + def shouldLeaveGrid(slot: Int, s: ItemStack): Boolean = + s.getItem.doesContainerItemLeaveCraftingGrid(s) || getStackInSlot(slot) != null + + val surplus = new ArrayBuffer[ItemStack] + for (slot <- 0 until getSizeInventory) { + Option(getStackInSlot(slot)).foreach { stack => + decrStackSize(slot, 1) + val item = stack.getItem + if (item.hasContainerItem(stack)) { + val container = item.getContainerItem(stack) + if (isDestroyed(container)) { + MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(player, container)) + } else if (shouldLeaveGrid(slot, container)) { + surplus += container + } else { + setInventorySlotContents(slot, container) + } + } + } + } + surplus + } + + private def load(inventory: IInventory): Unit = { + for (slot <- 0 until getSizeInventory) { + setInventorySlotContents(slot, inventory.getStackInSlot(toParentSlot(slot))) + } + } + + private def save(inventory: IInventory): Unit = { + 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 + } + + private val mockWorkbench = new TileMagicWorkbench + + private def findArcaneRecipe(inv: IInventory, player: EntityPlayer): IArcaneRecipe = { + for (slotIndex <- 0 until 9) { + mockWorkbench.setInventorySlotContentsSoftly(slotIndex, inv.getStackInSlot(slotIndex)) + } + ThaumcraftApi.getCraftingRecipes.asScala.collectFirst { + case r: IArcaneRecipe if r.matches(mockWorkbench, player.worldObj, ArcaneProxy) => r + }.orNull + } + } + + private def consumeAllVis(is: ItemStack, aspects: AspectList, doit: Boolean): Boolean = { + if (aspects == null || aspects.size == 0) return false + val wand = is.getItem match { + case w: ItemWandCasting => w + case _ => return false + } + val finalCosts = aspects.getAspects.map { aspect => + val baseCost = aspects.getAmount(aspect) * 100 + val actualCost = (baseCost * wand.getConsumptionModifier(is, null, aspect, true)).toInt + if (wand.getVis(is, aspect) < actualCost) return false + aspect -> actualCost + }.toMap + if (doit) { + finalCosts.foreach { case (aspect, cost) => + val currentVis = wand.getVis(is, aspect) + wand.storeVis(is, aspect, currentVis - cost) + } + } + true + } + + private def onCrafting(crafting: ItemStack): Unit = { + val warp = ThaumcraftApi.getWarp(crafting) + if (!Config.wuss && warp > 0) addStickyWarpToOwner(warp) + if ((crafting.getItem eq ConfigItems.itemResource) && crafting.getItemDamage == 13 && crafting.hasTagCompound) for (var2 <- 0 until 9) { + val var3 = CraftingInventory.getStackInSlot(var2) + if (var3 != null && var3.getItem.isInstanceOf[ItemEssence]) { + var3.stackSize += 1 + CraftingInventory.setInventorySlotContents(var2, var3) + } + } + if ((crafting.getItem eq Item.getItemFromBlock(ConfigBlocks.blockMetalDevice)) && crafting.getItemDamage == 3) { + val var3 = CraftingInventory.getStackInSlot(4) + var3.stackSize += 1 + CraftingInventory.setInventorySlotContents(4, var3) + } + } + + object ArcaneProxy extends FakePlayer(host.world.asInstanceOf[WorldServer], new GameProfile(null, "ArcaneProxy")) { + override def getCommandSenderName: String = host.ownerName() + } + + private var cachedStickyWarp = 0 + + private def findOwner(): Option[EntityPlayerMP] = Option(MinecraftServer.getServer.getConfigurationManager.func_152612_a(host.ownerName())) + + private def addStickyWarpToOwner(amount: Int): Unit = { + cachedStickyWarp = cachedStickyWarp + amount + findOwner().foreach { + owner => + Thaumcraft.addStickyWarpToPlayer(owner, cachedStickyWarp) + cachedStickyWarp = 0 + } + } + + private def getPlayerDir: File = { + val sh = host.world.getSaveHandler.getSaveHandler.asInstanceOf[SaveHandler] + ObfuscationReflectionHelper.getPrivateValue(classOf[SaveHandler], sh, "playersDirectory", "field_" + "75771_c") + } + + override def load(nbt: NBTTagCompound): Unit = { + super.load(nbt) + cachedStickyWarp = nbt.getInteger("cachedStickyWarp") + if (ResearchManager.getResearchForPlayerSafe(host.ownerName()) == null) { + Thaumcraft.instance.entityEventHandler.playerLoad(new LoadFromFile(ArcaneProxy, getPlayerDir, "")) + } + } + + override def save(nbt: NBTTagCompound): Unit = { + super.save(nbt) + nbt.setInteger("cachedStickyWarp", cachedStickyWarp) + } +} diff --git a/src/main/scala/li/cil/oc/integration/thaumcraft/item/UpgradeArcaneCrafting.scala b/src/main/scala/li/cil/oc/integration/thaumcraft/item/UpgradeArcaneCrafting.scala new file mode 100644 index 0000000000..188a2c8b00 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/thaumcraft/item/UpgradeArcaneCrafting.scala @@ -0,0 +1,5 @@ +package li.cil.oc.integration.thaumcraft.item + +import li.cil.oc.common.item.{Delegator, traits} + +class UpgradeArcaneCrafting(val parent: Delegator) extends traits.Delegate {}