From 721bc9b9a299ff0a0beb6f220539e660796acf67 Mon Sep 17 00:00:00 2001 From: Inari Date: Sun, 3 Jan 2016 11:09:52 +0100 Subject: [PATCH 1/2] Add trading card upgrade code, recipes, config options, and language names (for EN/DE) --- src/main/resources/application.conf | 4 + .../assets/opencomputers/lang/de_DE.lang | 1 + .../assets/opencomputers/lang/en_US.lang | 1 + .../opencomputers/recipes/default.recipes | 6 + .../opencomputers/recipes/hardmode.recipes | 6 + src/main/scala/li/cil/oc/Constants.scala | 1 + src/main/scala/li/cil/oc/Settings.scala | 1 + .../scala/li/cil/oc/common/init/Items.scala | 2 + .../cil/oc/common/item/UpgradeTrading.scala | 3 + .../opencomputers/DriverUpgradeTrading.scala | 37 +++ .../opencomputers/ModOpenComputers.scala | 10 +- .../li/cil/oc/server/component/Trade.scala | 256 ++++++++++++++++++ .../oc/server/component/UpgradeTrading.scala | 47 ++++ 13 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala create mode 100644 src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTrading.scala create mode 100644 src/main/scala/li/cil/oc/server/component/Trade.scala create mode 100644 src/main/scala/li/cil/oc/server/component/UpgradeTrading.scala diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index ca4f0c98a..0ecf518f3 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -1317,6 +1317,10 @@ opencomputers { # such as the redstone card and redstone I/O block. Lowering this can # have very negative impact on server TPS, so beware. redstoneDelay: 0.1 + + # The maximum range between the drone/robot and a villager for a trade to + # be performed by the trading upgrade + tradingRange: 8.0 } # Settings for mod integration (the mod previously known as OpenComponents). diff --git a/src/main/resources/assets/opencomputers/lang/de_DE.lang b/src/main/resources/assets/opencomputers/lang/de_DE.lang index b9ccb64b9..03d61ba85 100644 --- a/src/main/resources/assets/opencomputers/lang/de_DE.lang +++ b/src/main/resources/assets/opencomputers/lang/de_DE.lang @@ -145,6 +145,7 @@ item.oc.UpgradeSolarGenerator.name=Solargenerator-Upgrade item.oc.UpgradeTank.name=Tank-Upgrade item.oc.UpgradeTankController.name=Tankbedienungs-Upgrade item.oc.UpgradeTractorBeam.name=Traktorstrahl-Upgrade +item.oc.UpgradeTrading.name=Handels-Upgrade item.oc.WirelessNetworkCard.name=Drahtlosnetzwerkkarte item.oc.WorldSensorCard.name=Weltsensorkarte item.oc.wrench.name=Schraubenziehschlüssel diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index 8c5f358ce..8be5a375b 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -150,6 +150,7 @@ item.oc.UpgradeSolarGenerator.name=Solar Generator Upgrade item.oc.UpgradeTank.name=Tank Upgrade item.oc.UpgradeTankController.name=Tank Controller Upgrade item.oc.UpgradeTractorBeam.name=Tractor Beam Upgrade +item.oc.UpgradeTrading.name=Trading Upgrade item.oc.WirelessNetworkCard.name=Wireless Network Card item.oc.WorldSensorCard.name=World Sensor Card item.oc.wrench.name=Scrench diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes index a66017648..660b269bd 100644 --- a/src/main/resources/assets/opencomputers/recipes/default.recipes +++ b/src/main/resources/assets/opencomputers/recipes/default.recipes @@ -367,6 +367,12 @@ upgradeContainer3 { [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]] } +upgradeTrading { + input: [[ingotGold, chest, ingotGold] + [emerald, "oc:circuitChip2", emerald] + [dropper, "oc:materialCircuitBoardPrinted", craftingPiston]] +} + # Note: iron ingot and nugget recipes are *only* registered if no other mod # already provides the same functionality. nuggetIron { diff --git a/src/main/resources/assets/opencomputers/recipes/hardmode.recipes b/src/main/resources/assets/opencomputers/recipes/hardmode.recipes index c5f642ed1..3623657f0 100644 --- a/src/main/resources/assets/opencomputers/recipes/hardmode.recipes +++ b/src/main/resources/assets/opencomputers/recipes/hardmode.recipes @@ -182,6 +182,12 @@ solarGeneratorUpgrade { ["oc:circuitChip3", "oc:generatorUpgrade", "oc:circuitChip3"]] } +upgradeTrading { + input: [["oc:circuitChip2", chest, "oc:circuitChip2"] + [emerald, "oc:circuitChip2", emerald] + [dropper, "oc:materialCircuitBoardPrinted", craftingPiston]] +} + nuggetIron { type: shapeless input: ingotIron diff --git a/src/main/scala/li/cil/oc/Constants.scala b/src/main/scala/li/cil/oc/Constants.scala index 29dbb654e..8d096f31f 100644 --- a/src/main/scala/li/cil/oc/Constants.scala +++ b/src/main/scala/li/cil/oc/Constants.scala @@ -154,6 +154,7 @@ object Constants { final val TerminalServer = "terminalServer" final val TexturePicker = "texturePicker" final val TractorBeamUpgrade = "tractorBeamUpgrade" + final val TradingUpgrade = "upgradeTrading" final val Transistor = "transistor" final val UpgradeContainerTier1 = "upgradeContainer1" final val UpgradeContainerTier2 = "upgradeContainer2" diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 82ef081f4..2ff695476 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -342,6 +342,7 @@ class Settings(val config: Config) { val dataCardTimeout = config.getDouble("misc.dataCardTimeout") max 0 val serverRackSwitchTier = (config.getInt("misc.serverRackSwitchTier") - 1) max Tier.None min Tier.Three val redstoneDelay = config.getDouble("misc.redstoneDelay") max 0 + val tradingRange = config.getDouble("misc.tradingRange") max 0 // ----------------------------------------------------------------------- // // nanomachines 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 f8c7b60ee..35bfe2c3a 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -533,6 +533,8 @@ object Items extends ItemAPI { Recipes.addSubItem(new item.TerminalServer(multi), Constants.ItemName.TerminalServer, "oc:terminalServer") Recipes.addSubItem(new item.DiskDriveMountable(multi), Constants.ItemName.DiskDriveMountable, "oc:diskDriveMountable") + Recipes.addSubItem(new item.UpgradeTrading(multi), Constants.ItemName.TradingUpgrade, "oc:upgradeTrading") + // Register aliases. for ((k, v) <- aliases) { descriptors.getOrElseUpdate(k, descriptors(v)) diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala b/src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala new file mode 100644 index 000000000..1cb2b27ab --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala @@ -0,0 +1,3 @@ +package li.cil.oc.common.item + +class UpgradeTrading(val parent: Delegator) extends traits.Delegate with traits.ItemTier \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTrading.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTrading.scala new file mode 100644 index 000000000..9809f5b60 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverUpgradeTrading.scala @@ -0,0 +1,37 @@ +package li.cil.oc.integration.opencomputers + +import li.cil.oc.api +import li.cil.oc.Constants +import li.cil.oc.api.driver.EnvironmentProvider +import li.cil.oc.api.network.EnvironmentHost +import li.cil.oc.api.driver.item.HostAware +import li.cil.oc.common.{Tier, Slot} +import li.cil.oc.server.component.UpgradeTrading +import net.minecraft.item.ItemStack +import li.cil.oc.common.entity.Drone +import li.cil.oc.common.tileentity.Robot +import li.cil.oc.server.component + +object DriverUpgradeTrading extends Item with HostAware { + override def worksWith(stack: ItemStack) = isOneOf(stack, + api.Items.get(Constants.ItemName.TradingUpgrade)) + + override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = + if (host.world.isRemote) null + else host match { + case host: EnvironmentHost with Robot => new UpgradeTrading(host) + case host: EnvironmentHost with Drone => new UpgradeTrading(host) + case _ => null + } + + override def slot(stack: ItemStack) = Slot.Upgrade + + override def tier(stack: ItemStack) = Tier.Two + + object Provider extends EnvironmentProvider { + override def getEnvironment(stack: ItemStack): Class[_] = + if (worksWith(stack)) + classOf[component.UpgradeTrading] + 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 98eae5eec..b18bef72d 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala @@ -146,6 +146,7 @@ object ModOpenComputers extends ModProxy { api.Driver.add(DriverUpgradeTank) api.Driver.add(DriverUpgradeTankController) api.Driver.add(DriverUpgradeTractorBeam) + api.Driver.add(DriverUpgradeTrading) api.Driver.add(DriverAPU.Provider) api.Driver.add(DriverDataCard.Provider) @@ -200,7 +201,8 @@ object ModOpenComputers extends ModProxy { Constants.ItemName.SolarGeneratorUpgrade, Constants.ItemName.TankUpgrade, Constants.ItemName.TractorBeamUpgrade, - Constants.ItemName.LeashUpgrade) + Constants.ItemName.LeashUpgrade, + Constants.ItemName.TradingUpgrade) blacklistHost(classOf[internal.Drone], Constants.BlockName.Keyboard, Constants.BlockName.ScreenTier1, @@ -240,7 +242,8 @@ object ModOpenComputers extends ModProxy { Constants.ItemName.TankUpgrade, Constants.ItemName.TankControllerUpgrade, Constants.ItemName.TractorBeamUpgrade, - Constants.ItemName.LeashUpgrade) + Constants.ItemName.LeashUpgrade, + Constants.ItemName.TradingUpgrade) blacklistHost(classOf[internal.Robot], Constants.BlockName.Transposer, Constants.ItemName.LeashUpgrade) @@ -263,7 +266,8 @@ object ModOpenComputers extends ModProxy { Constants.ItemName.InventoryControllerUpgrade, Constants.ItemName.TankUpgrade, Constants.ItemName.TankControllerUpgrade, - Constants.ItemName.LeashUpgrade) + Constants.ItemName.LeashUpgrade, + Constants.ItemName.TradingUpgrade) if (!WirelessRedstone.isAvailable) { blacklistHost(classOf[internal.Drone], Constants.ItemName.RedstoneCardTier2) diff --git a/src/main/scala/li/cil/oc/server/component/Trade.scala b/src/main/scala/li/cil/oc/server/component/Trade.scala new file mode 100644 index 000000000..917de78f3 --- /dev/null +++ b/src/main/scala/li/cil/oc/server/component/Trade.scala @@ -0,0 +1,256 @@ +package li.cil.oc.server.component + +import java.util.UUID + +import li.cil.oc.Settings +import li.cil.oc.api.machine._ +import li.cil.oc.api.prefab.AbstractValue +import li.cil.oc.common.EventHandler +import li.cil.oc.util.InventoryUtils +import net.minecraft.entity.passive.EntityVillager +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.village.MerchantRecipe +import net.minecraftforge.common.DimensionManager +import net.minecraftforge.common.util.ForgeDirection +import ref.WeakReference +import li.cil.oc.api.network.EnvironmentHost +import scala.collection.JavaConverters._ + +class Trade(info: TradeInfo) extends AbstractValue { + + def this() = this(new TradeInfo()) + def this(upgr: UpgradeTrading, villager: EntityVillager, recipeID: Int) = { + this(new TradeInfo(upgr.host, villager, recipeID)) + } + + + override def load(nbt: NBTTagCompound) = { + EventHandler.scheduleServer(() => { + //Tell the info to load from NBT, behind EventHandler because when load is called we can't access the world yet + //and we need to access it to get the Robot/Drone TileEntity/Entity + info.load(nbt) + }) + } + + override def save(nbt: NBTTagCompound) = { + //Tell info to save to nbt + info.save(nbt) + } + + def inventory = info.inventory + + @Callback(doc="function():table, table -- returns the items the villager wants for this trade") + def getInput(context: Context, arguments: Arguments): Array[AnyRef] = { + Array(info.recipe.getItemToBuy.copy(), + info.recipe.hasSecondItemToBuy match { + case true => info.recipe.getSecondItemToBuy.copy() + case false => null + }) + } + + @Callback(doc = "function():table -- returns the item the villager offers for this trade") + def getOutput(context: Context, arguments: Arguments): Array[AnyRef] = { + Array(info.recipe.getItemToSell.copy()) + } + + @Callback(doc="function():boolean -- returns whether the villager currently wants to trade this") + def isEnabled(context: Context, arguments: Arguments): Array[AnyRef] = { + Array(info.villager.exists((villager: EntityVillager) => // Make sure villager is neither dead/gone nor the recipe + !info.recipe.isRecipeDisabled // has been disabled + ).asInstanceOf[AnyRef]) + } + + val maxRange = Settings.get.tradingRange + def inRange = info.villager.isDefined && distance.exists((distance: Double) => distance < maxRange) + def distance = info.villager match { + case Some(villager: EntityVillager) => + info.host match { + case Some(h: EnvironmentHost) => Some(Math.sqrt(Math.pow(villager.posX - h.xPosition, 2) + Math.pow(villager.posY - h.yPosition, 2) + Math.pow(villager.posZ - h.zPosition, 2))) + case _ => None + } + case None => None + } + + @Callback(doc="function():boolean, string -- returns true when trade succeeds and nil, error when not") + def trade(context: Context, arguments: Arguments): Array[AnyRef] = { + //Make sure we can access an inventory + val inventory = info.inventory match { + case Some(i) => i + case None => return result(false, "trading requires an inventory upgrade to be installed") + } + + //Make sure villager hasn't died, it somehow gone or moved out of range + if (info.villager.isEmpty) + return result(false, "trade has become invalid") + else if (!info.villager.get.isEntityAlive) + return result(false, "trader died") + if (!inRange) { + return result(false, "out of range") + } + + //Make sure villager wants to trade this + if (info.recipe.isRecipeDisabled) + return result(false, "recipe is disabled") + + //Now we'll check if we have enough items to perform the trade, caching first + val firstItem = info.recipe.getItemToBuy + val secondItem = info.recipe.hasSecondItemToBuy match { + case true => Some(info.recipe.getSecondItemToBuy) + case false => None + } + + //Check if we have enough of the first item + var extracting: Int = firstItem.stackSize + for (slot <- 0 until inventory.getSizeInventory) { + val stack = inventory.getStackInSlot(slot) + if (stack != null && stack.isItemEqual(firstItem) && extracting > 0) + //Takes the stack in the slot, extracts up to limit and calls the function in the first argument + //We don't actually consume anything, we just count that we have extracted as much as we need + InventoryUtils.extractFromInventorySlot((stack: ItemStack) => extracting -= stack.stackSize, inventory, ForgeDirection.UNKNOWN, slot, extracting) + } + //If we had enough, the left-over amount will be 0 + if (extracting != 0) + return result(false, "not enough items to trade") + + //Do the same with the second item if there is one + if (secondItem.isDefined) { + extracting = secondItem.orNull.stackSize + for (slot <- 0 until inventory.getSizeInventory) { + val stack = inventory.getStackInSlot(slot) + if (stack != null && stack.isItemEqual(secondItem.orNull) && extracting > 0) + InventoryUtils.extractFromInventorySlot((stack: ItemStack) => extracting -= stack.stackSize, inventory, ForgeDirection.UNKNOWN, slot, extracting) + } + if (extracting != 0) + return result(false, "not enough items to trade") + } + + //Now we need to check if we have enough inventory space to accept the item we get for the trade + val outputItemSim = info.recipe.getItemToSell.copy() + InventoryUtils.insertIntoInventory(outputItemSim, inventory, None, 64, simulate = true) + if (outputItemSim.stackSize != 0) + return result(false, "not enough inventory space to trade") + + //We established that out inventory allows to perform the trade, now actaully do the trade + extracting = firstItem.stackSize + for (slot <- 0 until inventory.getSizeInventory) { + if (extracting != 0) { + val stack = inventory.getStackInSlot(slot) + if (stack != null && stack.isItemEqual(firstItem)) + //Pretty much the same as earlier (but counting down, and not up now) + //but this time we actually consume the stack we get + InventoryUtils.extractFromInventorySlot((stack: ItemStack) => { + extracting -= stack.stackSize + stack.stackSize = 0 + }, inventory, ForgeDirection.UNKNOWN, slot, extracting) + } + } + + //Do the same for the second item + if (secondItem.isDefined) { + extracting = secondItem.orNull.stackSize + for (slot <- 0 until inventory.getSizeInventory) { + if (extracting != 0) { + val stack = inventory.getStackInSlot(slot) + if (stack != null && stack.isItemEqual(secondItem.orNull)) + InventoryUtils.extractFromInventorySlot((stack: ItemStack) => { + extracting -= stack.stackSize + stack.stackSize = 0 + }, inventory, ForgeDirection.UNKNOWN, slot, extracting) + } + } + } + + //Now put our output item into the inventory + val outputItem = info.recipe.getItemToSell.copy() + while (outputItem.stackSize != 0) + InventoryUtils.insertIntoInventory(outputItem, inventory, None, outputItem.stackSize) + + //Tell the villager we used the recipe, so MC can disable it and/or enable more recipes + info.villager.orNull.useRecipe(info.recipe) + result(true) + } +} + +class TradeInfo() { + def this(host: EnvironmentHost, villager: EntityVillager, recipeID: Int) = { + this() + _vilRef = new WeakReference[EntityVillager](villager) + _recipeID = recipeID + this.host = host + } + + def getEntityByUUID(dimID: Int, uuid: UUID) = DimensionManager.getProvider(dimID).worldObj.getLoadedEntityList.asScala.find { + case entAny: net.minecraft.entity.Entity if entAny.getPersistentID == uuid => true + case _ => false + } + + def getTileEntity(dimID: Int, posX: Int, posY: Int, posZ: Int) = Option(DimensionManager.getProvider(dimID).worldObj.getTileEntity(posX, posY, posZ) match { + case robot : li.cil.oc.common.tileentity.Robot => robot + case robotProxy : li.cil.oc.common.tileentity.RobotProxy => robotProxy.robot + case null => None + }) + + def load(nbt: NBTTagCompound): Unit = { + val dimID = nbt.getInteger("dimensionID") + val _hostIsDrone = nbt.getBoolean("hostIsDrone") + //If drone we find it again by its UUID, if Robot we know the X/Y/Z of the TileEntity + host = Option(_hostIsDrone match { + case true => getEntityByUUID(dimID, UUID.fromString(nbt.getString("hostUUID"))).orNull.asInstanceOf[EnvironmentHost] + case false => getTileEntity( + dimID, + nbt.getInteger("hostX"), + nbt.getInteger("hostY"), + nbt.getInteger("hostZ") + ).orNull.asInstanceOf[EnvironmentHost] + }) + _recipeID = nbt.getInteger("recipeID") + _vilRef = new WeakReference[EntityVillager](getEntityByUUID(dimID, UUID.fromString(nbt.getString("villagerUUID"))).orNull.asInstanceOf[EntityVillager]) + } + + def save(nbt: NBTTagCompound): Unit = { + host match { + case Some(h) => + nbt.setInteger("dimensionID", h.world.provider.dimensionId) + hostIsDrone match { + case true => nbt.setString("hostUUID", h.asInstanceOf[li.cil.oc.common.entity.Drone].getPersistentID.toString) + case false => + nbt.setInteger("hostX", h.xPosition.floor.toInt) + nbt.setInteger("hostY", h.yPosition.floor.toInt) + nbt.setInteger("hostZ", h.zPosition.floor.toInt) + } + case None => + } + villager match { + case Some(v) => nbt.setString("villagerUUID", v.getPersistentID.toString) + case None => + } + nbt.setBoolean("hostIsDrone", hostIsDrone) + nbt.setInteger("recipeID", _recipeID) + } + + def hostIsDrone = host.orNull match { + case h : li.cil.oc.common.tileentity.Robot => false + case h : li.cil.oc.common.entity.Drone => true + case _ => false + } + private var _host: Option[EnvironmentHost] = None + private var _recipeID: Int = _ + private var _vilRef: WeakReference[EntityVillager] = new WeakReference[EntityVillager](null) + + def host = _host + private def host_= (value: EnvironmentHost): Unit = _host = Option(value) + private def host_= (value: Option[EnvironmentHost]): Unit = _host = value + + def villager = _vilRef.get + def recipeID = _recipeID + def recipe : MerchantRecipe = villager.orNull.getRecipes(null).get(recipeID).asInstanceOf[MerchantRecipe] + + def inventory = host match { + case Some(h) => hostIsDrone match { + case true => Some(h.asInstanceOf[li.cil.oc.common.entity.Drone].mainInventory) + case false => Some(h.asInstanceOf[li.cil.oc.common.tileentity.Robot].mainInventory) + } + case None => None + } +} \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/server/component/UpgradeTrading.scala b/src/main/scala/li/cil/oc/server/component/UpgradeTrading.scala new file mode 100644 index 000000000..3aaadecb4 --- /dev/null +++ b/src/main/scala/li/cil/oc/server/component/UpgradeTrading.scala @@ -0,0 +1,47 @@ +package li.cil.oc.server.component + +import li.cil.oc.Settings +import li.cil.oc.api.network.EnvironmentHost +import li.cil.oc.api.prefab +import li.cil.oc.api.Network +import li.cil.oc.api.network.Visibility +import li.cil.oc.util.BlockPosition +import li.cil.oc.api.machine.{Callback, Arguments, Context} +import net.minecraft.entity.passive.EntityVillager +import net.minecraft.util.Vec3 + +import scala.collection.mutable.ArrayBuffer + +class UpgradeTrading(val host: EnvironmentHost) extends prefab.ManagedEnvironment with traits.WorldAware { + override val node = Network.newNode(this, Visibility.Network). + withComponent("trading"). + create() + + override def position = BlockPosition(host) + + var maxRange = Settings.get.tradingRange + + def inRange(vil: EntityVillager): Boolean = { + Vec3.createVectorHelper(vil.posX, vil.posY, vil.posZ).distanceTo(position.toVec3) <= maxRange + } + + @Callback(doc = "function():table -- Returns a table of trades in range as userdata objects") + def getTrades(context: Context, args: Arguments): Array[AnyRef] = { + + val boundsLow = position.bounds.offset(-maxRange, -maxRange, -maxRange) + val boundsHigh = position.bounds.offset(maxRange, maxRange, maxRange) + val bounds = boundsLow.func_111270_a(boundsHigh) + + val trades = ArrayBuffer[Trade]() + entitiesInBounds[EntityVillager](bounds).foreach((vil: EntityVillager) => { + if (inRange(vil)) { + val merchantRecipes = vil.getRecipes(null) + for (i <- 0 to merchantRecipes.size() - 1) { + val trade = new Trade(this, vil, i) + trades += trade + } + } + }) + trades.toArray[Object] + } +} From e6a97f046a6866f399919f88c25f4e9fa1de9955 Mon Sep 17 00:00:00 2001 From: Negi Springfield Date: Sun, 3 Jan 2016 15:04:05 +0100 Subject: [PATCH 2/2] Add trading upgrade icon --- .../textures/items/UpgradeTrading.png | Bin 0 -> 18312 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/textures/items/UpgradeTrading.png diff --git a/src/main/resources/assets/opencomputers/textures/items/UpgradeTrading.png b/src/main/resources/assets/opencomputers/textures/items/UpgradeTrading.png new file mode 100644 index 0000000000000000000000000000000000000000..9eae15eae6280c097efb9c674b8b83c6d6fbd4e7 GIT binary patch literal 18312 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 literal 0 HcmV?d00001