diff --git a/.gitignore b/.gitignore index b72b8df91..84ff5b95b 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ /config /options.txt /usernamecache.json +/classes diff --git a/build.gradle b/build.gradle index 72b04ecac..bd9063214 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,8 @@ buildscript { repositories { mavenCentral() maven { - name = "forge" - url = "https://files.minecraftforge.net/maven" + name = "gt" + url = "https://gregtech.overminddl1.com/" } maven { name = "sonatype" @@ -14,16 +14,17 @@ buildscript { } } dependencies { - classpath 'com.github.CDAGaming:ForgeGradle:1c670759c5' - classpath 'com.github.CDAGaming:CurseGradle:184e4322fd' + classpath 'com.github.GTNH2:ForgeGradle:FG_1.2-SNAPSHOT' } } apply plugin: 'scala' apply plugin: 'forge' apply plugin: 'idea' -apply plugin: 'maven-publish' -apply plugin: 'com.matthewprenger.cursegradle' + +tasks.withType(ScalaCompile) { + scalaCompileOptions.additionalParameters = ["-deprecation:false"] +} file "build.properties" withReader { def prop = new Properties() @@ -103,6 +104,17 @@ repositories { name = "gt" url = "http://gregtech.overminddl1.com/" } + ivy { + name 'gtnh_download_source' + artifactPattern "http://downloads.gtnewhorizons.com/Mods_for_Jenkins/[module]-[revision].[ext]" + } + maven { // GalacticGreg, YAMCore,.. + name 'UsrvDE' + url "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/" + } + maven { + url "http://downloads.gtnewhorizons.com/Mods_for_Jenkins/" + } } configurations { @@ -121,7 +133,7 @@ dependencies { compileOnly "codechicken:NotEnoughItems:${config.minecraft.version}-${config.nei.version}:dev" compileOnly "codechicken:WR-CBE:${config.minecraft.version}-${config.wrcbe.version}:dev" compileOnly "com.bluepowermod:BluePower:${config.bluepower.version}:deobf" - compileOnly "com.gregoriust.gregtech:gregtech_${config.minecraft.version}:${config.gt.version}:dev" + compileOnly "com.gregoriust.gregtech:gregtech:${config.gt.version}:dev" compileOnly "igwmod:IGW-Mod-1.7.10:${config.igwmod.version}:userdev" compileOnly "li.cil.tis3d:TIS-3D:${config.tis3d.version}:dev" compileOnly "mcp.mobius.waila:Waila:${config.waila.version}_${config.minecraft.version}:dev" @@ -248,36 +260,6 @@ artifacts { archives sourcesJar } -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - artifact apiJar - artifact javadocJar - artifact sourcesJar - artifact deobfJar { classifier 'dev' } - } - } - repositories { - maven { - url System.getenv("MAVEN_PATH") - } - } -} - -curseforge { - apiKey = project.hasProperty("curseForgeApiKey") ? project.curseForgeApiKey : "" - project { - id = config.curse.project.id - releaseType = config.curse.project.releaseType - changelogType = "markdown" - changelog = file("changelog.md") - addGameVersion config.minecraft.version - addGameVersion "Java 8" - mainArtifact jar - } -} - // this is needed for IntelliJ so we don't have to copy over the assets manually every time idea { module { diff --git a/build.properties b/build.properties index b9a087922..29ab96fba 100644 --- a/build.properties +++ b/build.properties @@ -1,9 +1,9 @@ minecraft.version=1.7.10 forge.version=10.13.4.1614-1.7.10 -oc.version=1.7.5.5 +oc.version=1.7.5.12-GTNH -ae2.version=rv2-beta-26 +ae2.version=rv3-beta-31 bc.version=7.0.9 bloodmagic.cf=2223/203 bloodmagic.version=1.3.0a-1 @@ -18,13 +18,13 @@ coloredlights.build=35 ec.cf=2242/839 ec.version=deobf-1.7.10-2.2.73b129 eio.cf=2219/296 -eio.version=1.7.10-2.2.1.276 +eio.version=1.7.10-2.3.0.429_beta es.version=1.4.5.24 fmp.version=1.1.0.308 -forestry.version=4.1.0.44 +forestry.version=4.4.0.0 gc.build=3 gc.version=3.0.7 -gt.version=5.04.06 +gt.version=5.09.33.52 ic2.version=2.2.828-experimental igwmod.version=1.1.3-18 mekanism.build=5 diff --git a/libs/Avaritiaddons-1.4b.jar b/libs/Avaritiaddons-1.4b.jar new file mode 100644 index 000000000..136477a8d Binary files /dev/null and b/libs/Avaritiaddons-1.4b.jar differ diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 70b8432c5..1df5280e1 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -1391,6 +1391,11 @@ opencomputers { # Radius the MFU is able to operate in mfuRange: 3 + + # Transposer fluid transfer rate in millibuckets per second + # It may transfer unlimited amount per operation, but will then + # wait ((Amount in buckets)/16) seconds + transposerFluidTransferRate=16000 } # Settings for mod integration (the mod previously known as OpenComponents). diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 72c06a1d2..ef60188ac 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -53,7 +53,7 @@ class Settings(val config: Config) { (-1.0, -1.0) } val enableNanomachinePfx = config.getBoolean("client.enableNanomachinePfx") - + val transposerFluidTransferRate = try { config.getInt("misc.transposerFluidTransferRate") } catch { case _ : Throwable => 16000 } // ----------------------------------------------------------------------- // // computer val threads = config.getInt("computer.threads") max 1 diff --git a/src/main/scala/li/cil/oc/integration/Mods.scala b/src/main/scala/li/cil/oc/integration/Mods.scala index f24c39634..3a5c81a04 100644 --- a/src/main/scala/li/cil/oc/integration/Mods.scala +++ b/src/main/scala/li/cil/oc/integration/Mods.scala @@ -19,6 +19,7 @@ object Mods { val AgriCraft = new SimpleMod(IDs.AgriCraft, version = "@[1.4.0,)") val AppliedEnergistics2 = new SimpleMod(IDs.AppliedEnergistics2, version = "@[rv1,)") + val AvaritiaAddons = new SimpleMod(IDs.AvaritiaAddons) val BattleGear2 = new SimpleMod(IDs.BattleGear2) val BetterRecords = new SimpleMod(IDs.BetterRecords) val BloodMagic = new SimpleMod(IDs.BloodMagic) @@ -89,6 +90,7 @@ object Mods { val Proxies = Array( integration.agricraft.ModAgriCraft, integration.appeng.ModAppEng, + integration.avaritiaaddons.ModAvaritiaAddons, integration.betterrecords.ModBetterRecords, integration.bloodmagic.ModBloodMagic, integration.bluepower.ModBluePower, @@ -168,6 +170,7 @@ object Mods { object IDs { final val AgriCraft = "AgriCraft" final val AppliedEnergistics2 = "appliedenergistics2" + final val AvaritiaAddons = "avaritiaddons" final val BattleGear2 = "battlegear2" final val BetterRecords = "betterrecords" final val BloodMagic = "AWWayofTime" diff --git a/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala b/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala index 9fe7cb6e6..3c72f0b1f 100644 --- a/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala +++ b/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala @@ -1,12 +1,15 @@ package li.cil.oc.integration.appeng +import java.lang + import appeng.api.AEApi import appeng.api.config.Actionable import appeng.api.networking.crafting.ICraftingLink import appeng.api.networking.crafting.ICraftingRequester -import appeng.api.networking.security.IActionHost -import appeng.api.networking.security.MachineSource -import appeng.api.storage.data.IAEItemStack +import appeng.api.networking.security.{BaseActionSource, IActionHost, MachineSource} +import appeng.api.networking.storage.IBaseMonitor +import appeng.api.storage.IMEMonitorHandlerReceiver +import appeng.api.storage.data.{IAEItemStack, IItemList} import appeng.me.helpers.IGridProxyable import appeng.util.item.AEItemStack import com.google.common.collect.ImmutableSet @@ -18,6 +21,7 @@ import li.cil.oc.api.network.Node import li.cil.oc.api.prefab.AbstractValue import li.cil.oc.common.EventHandler import li.cil.oc.integration.Mods +import li.cil.oc.integration.appeng.NetworkControl._ import li.cil.oc.integration.ec.ECUtil import li.cil.oc.server.driver.Registry import li.cil.oc.util.DatabaseAccess @@ -44,43 +48,8 @@ trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActi def node: Node - private def aeCraftItem(aeItem: IAEItemStack): IAEItemStack = { - val patterns = tile.getProxy.getCrafting.getCraftingFor(aeItem, null, 0, tile.getWorldObj) - patterns.find(pattern => pattern.getOutputs.exists(_.isSameType(aeItem))) match { - case Some(pattern) => pattern.getOutputs.find(_.isSameType(aeItem)).get - case _ => aeItem.copy.setStackSize(0) // Should not be possible, but hey... - } - } - - private def aePotentialItem(aeItem: IAEItemStack): IAEItemStack = { - if (aeItem.getStackSize > 0 || !aeItem.isCraftable) - aeItem - else - aeCraftItem(aeItem) - } - private def allItems: Iterable[IAEItemStack] = tile.getProxy.getStorage.getItemInventory.getStorageList - private def allCraftables: Iterable[IAEItemStack] = allItems.collect{ case aeItem if aeItem.isCraftable => aeCraftItem(aeItem) } - - private def convert(aeItem: IAEItemStack): java.util.HashMap[String, AnyRef] = { - def hashConvert(value: java.util.HashMap[_, _]) = { - val hash = new java.util.HashMap[String, AnyRef] - value.collect{ case (k:String, v:AnyRef) => hash += k -> v } - hash - } - val potentialItem = aePotentialItem(aeItem) - val result = Registry.convert(Array[AnyRef](potentialItem.getItemStack)) - .collect { case hash: java.util.HashMap[_,_] => hashConvert(hash) } - if (result.length > 0) { - val hash = result(0) - // it would have been nice to put these fields in a registry convert - // but the potential ae item needs the tile and position data - hash.update("size", Int.box(aeItem.getStackSize.toInt)) - hash.update("isCraftable", Boolean.box(aeItem.isCraftable)) - return hash - } - null - } + private def allCraftables: Iterable[IAEItemStack] = allItems.collect{ case aeItem if aeItem.isCraftable => aeCraftItem(aeItem, tile) } @Callback(doc = "function():table -- Get a list of tables representing the available CPUs in the network.") def getCpus(context: Context, args: Arguments): Array[AnyRef] = { @@ -101,7 +70,7 @@ trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActi case (key: String, value: AnyRef) => (key, value) } result(allCraftables - .collect{ case aeCraftItem if filter.isEmpty || matches(convert(aeCraftItem), filter) => new NetworkControl.Craftable(tile, aeCraftItem) } + .collect{ case aeCraftItem if filter.isEmpty || matches(convert(aeCraftItem, tile), filter) => new NetworkControl.Craftable(tile, aeCraftItem) } .toArray) } @@ -111,11 +80,16 @@ trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActi case (key: String, value: AnyRef) => (key, value) } result(allItems - .map(convert) + .map(item => convert(item, tile)) .filter(hash => matches(hash, filter)) .toArray) } + @Callback(doc = "function():userdata -- Get an iterator object for the list of the items in the network.") + def allItems(context: Context, args: Arguments): Array[AnyRef] = { + result(new NetworkContents(tile)) + } + @Callback(doc = "function(filter:table, dbAddress:string[, startSlot:number[, count:number]]): Boolean -- Store items in the network matching the specified filter in the database with the specified address.") def store(context: Context, args: Arguments): Array[AnyRef] = { val filter = args.checkTable(0).collect { @@ -123,7 +97,7 @@ trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActi } DatabaseAccess.withDatabase(node, args.checkString(1), database => { val items = allItems - .collect{ case aeItem if matches(convert(aeItem), filter) => aePotentialItem(aeItem)}.toArray + .collect{ case aeItem if matches(convert(aeItem, tile), filter) => aePotentialItem(aeItem, tile)}.toArray val offset = args.optSlot(database.data, 2, 0) val count = args.optInteger(3, Int.MaxValue) min (database.size - offset) min items.length var slot = offset @@ -344,4 +318,105 @@ object NetworkControl { } } + class NetworkContents(var controller: TileEntity with IGridProxyable) extends AbstractValue with IMEMonitorHandlerReceiver[IAEItemStack] + { + def this() = this(null) + if (controller != null) + controller.getProxy.getStorage.getItemInventory.addListener(this, null) + var items : IItemList[IAEItemStack] = null + var i : java.util.Iterator[IAEItemStack] = null + var index = 0 + + override def call(context: Context, arguments: Arguments): Array[AnyRef] = { + if (controller == null) return null + if (items == null) { + items = controller.getProxy.getStorage.getItemInventory.getStorageList + if (items != null) + i = items.iterator + if (i != null) + for (_ <- 1 to index) { + if (i.hasNext) + i.next + } + } + if (this.i == null && this.items != null) + this.i = items.iterator + if (!this.i.hasNext()) return null + index += 1 + Array[AnyRef](convert(i.next(), controller)) + } + override def load(nbt: NBTTagCompound) { + super.load(nbt) + if (nbt.hasKey("dimension")) { + val dimension = nbt.getInteger("dimension") + val x = nbt.getInteger("x") + val y = nbt.getInteger("y") + val z = nbt.getInteger("z") + index = nbt.getInteger("index") + EventHandler.scheduleServer(() => { + val tileEntity = DimensionManager.getWorld(dimension).getTileEntity(x, y, z) + if (tileEntity != null && tileEntity.isInstanceOf[TileEntity with IGridProxyable]) { + controller = tileEntity.asInstanceOf[TileEntity with IGridProxyable] + if (controller!= null) + controller.getProxy.getStorage.getItemInventory.addListener(this, null) + } + }) + } + } + override def save(nbt: NBTTagCompound) { + super.save(nbt) + nbt.setInteger("index", index) + if (controller != null && !controller.isInvalid) { + nbt.setInteger("dimension", controller.getWorldObj.provider.dimensionId) + nbt.setInteger("x", controller.xCoord) + nbt.setInteger("y", controller.yCoord) + nbt.setInteger("z", controller.zCoord) + } + } + var valid = true + def dispose(context: Nothing): Unit = { + valid = false + } + + override def isValid(verificationToken: Any): Boolean = valid + override def onListUpdate(): Unit = { + this.items = null + } + override def postChange(monitor: IBaseMonitor[IAEItemStack], change: lang.Iterable[IAEItemStack], actionSource: BaseActionSource): Unit = { + this.items = null + } + } + def aeCraftItem(aeItem: IAEItemStack, tile: TileEntity with IGridProxyable): IAEItemStack = { + val patterns = tile.getProxy.getCrafting.getCraftingFor(aeItem, null, 0, tile.getWorldObj) + patterns.find(pattern => pattern.getOutputs.exists(_.isSameType(aeItem))) match { + case Some(pattern) => pattern.getOutputs.find(_.isSameType(aeItem)).get + case _ => aeItem.copy.setStackSize(0) // Should not be possible, but hey... + } + } + + def aePotentialItem(aeItem: IAEItemStack, tile: TileEntity with IGridProxyable): IAEItemStack = { + if (aeItem.getStackSize > 0 || !aeItem.isCraftable) + aeItem + else + aeCraftItem(aeItem, tile) + } + def convert(aeItem: IAEItemStack, tile: TileEntity with IGridProxyable): java.util.HashMap[String, AnyRef] = { + def hashConvert(value: java.util.HashMap[_, _]) = { + val hash = new java.util.HashMap[String, AnyRef] + value.collect{ case (k:String, v:AnyRef) => hash += k -> v } + hash + } + val potentialItem = aePotentialItem(aeItem, tile) + val result = Registry.convert(Array[AnyRef](potentialItem.getItemStack)) + .collect { case hash: java.util.HashMap[_,_] => hashConvert(hash) } + if (result.length > 0) { + val hash = result(0) + // it would have been nice to put these fields in a registry convert + // but the potential ae item needs the tile and position data + hash.update("size", Long.box(aeItem.getStackSize)) + hash.update("isCraftable", Boolean.box(aeItem.isCraftable)) + return hash + } + null + } } \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/integration/avaritiaaddons/DriverExtremeAutocrafter.scala b/src/main/scala/li/cil/oc/integration/avaritiaaddons/DriverExtremeAutocrafter.scala new file mode 100644 index 000000000..e21c14ea7 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/avaritiaaddons/DriverExtremeAutocrafter.scala @@ -0,0 +1,64 @@ +package li.cil.oc.integration.avaritiaaddons + +import li.cil.oc.api.driver.EnvironmentProvider +import li.cil.oc.api.internal.Database +import li.cil.oc.api.machine.{Arguments, Callback, Context} +import li.cil.oc.api.network.{Component, ManagedEnvironment} +import li.cil.oc.api.prefab.DriverSidedTileEntity +import li.cil.oc.integration.ManagedTileEntityEnvironment +import li.cil.oc.util.ResultWrapper.result +import net.minecraft.item.ItemStack +import net.minecraft.item.Item +import net.minecraft.world.World +import net.minecraftforge.common.util.ForgeDirection +import wanion.avaritiaddons.block.extremeautocrafter.{BlockExtremeAutoCrafter, TileEntityExtremeAutoCrafter} + +object DriverExtremeAutocrafter extends DriverSidedTileEntity { + def getTileEntityClass: Class[_] = classOf[TileEntityExtremeAutoCrafter] + + override def createEnvironment(world: World, x: Int, y: Int, z: Int, side: ForgeDirection): ManagedEnvironment = new Environment(world.getTileEntity(x, y, z).asInstanceOf[TileEntityExtremeAutoCrafter]) + + final class Environment(val tile: TileEntityExtremeAutoCrafter) extends ManagedTileEntityEnvironment[TileEntityExtremeAutoCrafter](tile, "extreme_autocrafter") { + @Callback(doc = "function(slot:number, database:string, database_slot:number):boolean -- Set the ghost item at the specified slot. Item should be in database.") + def setGhostItem(context: Context, args: Arguments): Array[AnyRef] = { + val slot = args.checkInteger(0) + if (slot > 80) throw new IllegalArgumentException("Slot number should be from 0 to 80 (inclusive)") + tile.setInventorySlotContents(slot + 81, getStack(args)) + result(true) + } + @Callback(doc = "function(slot:number):table -- Returns the ghost item at the specified slot.") + def getGhostItem(context: Context, args: Arguments): Array[AnyRef] = { + val slot = args.checkInteger(0) + if (slot > 80) throw new IllegalArgumentException("Slot number should be from 0 to 80 (inclusive)") + result(tile.getStackInSlot(slot + 81)) + } + private def getStack(args: Arguments) = + if (args.count > 1) { + val (address, entry, size) = + if (args.isString(0)) (args.checkString(0), args.checkInteger(1), args.optInteger(2, 1)) + else (args.checkString(1), args.checkInteger(2), args.optInteger(3, 1)) + + node.network.node(address) match { + case component: Component => component.host match { + case database: Database => + val dbStack = database.getStackInSlot(entry - 1) + if (dbStack == null || size < 1) null + else { + dbStack.stackSize = math.min(size, dbStack.getMaxStackSize) + dbStack + } + case _ => throw new IllegalArgumentException("not a database") + } + case _ => throw new IllegalArgumentException("no such component") + } + } + else null + } + object Provider extends EnvironmentProvider { + override def getEnvironment(stack: ItemStack): Class[_] = { + if (stack.getItem == Item.getItemFromBlock(BlockExtremeAutoCrafter.instance)) + classOf[Environment] + else null + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/avaritiaaddons/ModAvaritiaAddons.scala b/src/main/scala/li/cil/oc/integration/avaritiaaddons/ModAvaritiaAddons.scala new file mode 100644 index 000000000..c9643853c --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/avaritiaaddons/ModAvaritiaAddons.scala @@ -0,0 +1,11 @@ +package li.cil.oc.integration.avaritiaaddons + +import li.cil.oc.api.Driver +import li.cil.oc.integration.{ModProxy, Mods} + +object ModAvaritiaAddons extends ModProxy { + override def getMod = Mods.AvaritiaAddons + override def initialize(): Unit = { + Driver.add(DriverExtremeAutocrafter) + } +} diff --git a/src/main/scala/li/cil/oc/integration/bloodmagic/ConverterBloodOrb.java b/src/main/scala/li/cil/oc/integration/bloodmagic/ConverterBloodOrb.java index 7d33b3dce..12402b2d4 100644 --- a/src/main/scala/li/cil/oc/integration/bloodmagic/ConverterBloodOrb.java +++ b/src/main/scala/li/cil/oc/integration/bloodmagic/ConverterBloodOrb.java @@ -14,7 +14,7 @@ public class ConverterBloodOrb implements Converter { if (value instanceof ItemStack) { final ItemStack stack = (ItemStack) value; final Item item = stack.getItem(); - if (item instanceof IBloodOrb) { + if (item instanceof IBloodOrb && stack.stackTagCompound != null) { final IBloodOrb bloodOrb = (IBloodOrb) item; final String ownerName = stack.stackTagCompound.getString("ownerName"); final int maxOrbTier = SoulNetworkHandler.getCurrentMaxOrb(ownerName); diff --git a/src/main/scala/li/cil/oc/integration/enderio/EventHandlerEnderIO.scala b/src/main/scala/li/cil/oc/integration/enderio/EventHandlerEnderIO.scala index 0daebf856..723f7253d 100644 --- a/src/main/scala/li/cil/oc/integration/enderio/EventHandlerEnderIO.scala +++ b/src/main/scala/li/cil/oc/integration/enderio/EventHandlerEnderIO.scala @@ -1,6 +1,6 @@ package li.cil.oc.integration.enderio -import crazypants.enderio.tool.ITool +import crazypants.enderio.api.tool.ITool import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack diff --git a/src/main/scala/li/cil/oc/integration/ic2/DriverTeleporter.java b/src/main/scala/li/cil/oc/integration/ic2/DriverTeleporter.java new file mode 100644 index 000000000..64079c215 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/DriverTeleporter.java @@ -0,0 +1,37 @@ +package li.cil.oc.integration.ic2; + +import ic2.core.block.machine.tileentity.TileEntityTeleporter; +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.ManagedEnvironment; +import li.cil.oc.api.prefab.DriverSidedTileEntity; +import li.cil.oc.integration.ManagedTileEntityEnvironment; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +public class DriverTeleporter extends DriverSidedTileEntity { + @Override + public Class getTileEntityClass() { + return TileEntityTeleporter.class; + } + + @Override + public ManagedEnvironment createEnvironment(World world, int x, int y, int z, ForgeDirection side) { + return new DriverTeleporter.Environment((TileEntityTeleporter)world.getTileEntity(x, y, z)); + } + + public static final class Environment extends ManagedTileEntityEnvironment { + public Environment(final TileEntityTeleporter tileEntity) { + super(tileEntity,"ic2_teleporter"); + } + @Callback(doc = "function(X:number, Y:number, Z:number)") + public Object[] setCoords(final Context context, final Arguments args) { + if (args.isInteger(0) && args.isInteger(1) && args.isInteger(2)) { + tileEntity.setTarget(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)); + } + return new Object[]{}; + } + } + +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala b/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala index a33931336..468beb9b1 100644 --- a/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala +++ b/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala @@ -32,6 +32,7 @@ object ModIndustrialCraft2 extends ModProxy { Driver.add(new DriverEnergyStorage) Driver.add(new DriverReactor) Driver.add(new DriverReactorChamber) + Driver.add(new DriverTeleporter) Driver.add(new ConverterElectricItem) Driver.add(new ConverterBaseSeed) diff --git a/src/main/scala/li/cil/oc/integration/tis3d/SerialInterfaceProviderAdapter.scala b/src/main/scala/li/cil/oc/integration/tis3d/SerialInterfaceProviderAdapter.scala index 40d2cc4f2..9d9e8a910 100644 --- a/src/main/scala/li/cil/oc/integration/tis3d/SerialInterfaceProviderAdapter.scala +++ b/src/main/scala/li/cil/oc/integration/tis3d/SerialInterfaceProviderAdapter.scala @@ -18,6 +18,7 @@ import li.cil.tis3d.api.serial.SerialInterface import li.cil.tis3d.api.serial.SerialInterfaceProvider import li.cil.tis3d.api.serial.SerialProtocolDocumentationReference import net.minecraft.nbt.NBTTagCompound +import net.minecraft.tileentity.TileEntity import net.minecraft.util.EnumFacing import net.minecraft.world.World @@ -36,7 +37,7 @@ object SerialInterfaceProviderAdapter extends SerialInterfaceProvider { override def interfaceFor(world: World, x: Int, y: Int, z: Int, side: EnumFacing): SerialInterface = new SerialInterfaceAdapter(world.getTileEntity(x, y, z).asInstanceOf[Adapter]) override def isValid(world: World, x: Int, y: Int, z: Int, side: EnumFacing, serialInterface: SerialInterface): Boolean = serialInterface match { - case adapter: SerialInterfaceAdapter => adapter.tileEntity == world.getTileEntity(x, y, z) + case adapter: SerialInterfaceAdapter => adapter.tileEntity.asInstanceOf[TileEntity] == world.getTileEntity(x, y, z) case _ => false } @@ -48,7 +49,7 @@ object SerialInterfaceProviderAdapter extends SerialInterfaceProvider { // ----------------------------------------------------------------------- // - val node = api.Network.newNode(this, Visibility.Network).withComponent("serial_port").create() + val node: Node = api.Network.newNode(this, Visibility.Network).withComponent("serial_port").create() override def onMessage(message: Message): Unit = {} diff --git a/src/main/scala/li/cil/oc/server/component/Geolyzer.scala b/src/main/scala/li/cil/oc/server/component/Geolyzer.scala index 71308416c..460301cf5 100644 --- a/src/main/scala/li/cil/oc/server/component/Geolyzer.scala +++ b/src/main/scala/li/cil/oc/server/component/Geolyzer.scala @@ -18,7 +18,7 @@ import li.cil.oc.api.machine.Context import li.cil.oc.api.network.Message import li.cil.oc.api.network.Visibility import li.cil.oc.api.prefab -import li.cil.oc.common.tileentity.{Robot => EntityRobot, Microcontroller} +import li.cil.oc.common.tileentity.{Microcontroller, Robot => EntityRobot} import li.cil.oc.common.entity.{Drone => EntityDrone} import li.cil.oc.common.item.TabletWrapper import li.cil.oc.util.BlockPosition @@ -30,6 +30,7 @@ import net.minecraft.item.Item import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound import net.minecraft.world.biome.BiomeGenDesert +import net.minecraft.world.chunk.Chunk import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.util.ForgeDirection @@ -183,6 +184,12 @@ class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment with }) } } + @Callback(doc = """function():table -- Returns GregTech underground fluids information""") + def scanUndergroundFluids(computer: Context, args: Arguments): Array[AnyRef] = { + val blockPos = BlockPosition(host) + val fluid = gregtech.common.GT_UndergroundOil.undergroundOilReadInformation(new Chunk(host.world, blockPos.x>>4, blockPos.z>>4)) + result(Map("type" -> fluid.getLocalizedName, "quantity" -> fluid.amount)) + } override def onMessage(message: Message): Unit = { super.onMessage(message) diff --git a/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala b/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala index 30cafb313..2ae52b0e4 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala @@ -1,5 +1,6 @@ package li.cil.oc.server.component.traits +import li.cil.oc.Settings import li.cil.oc.api.machine.Arguments import li.cil.oc.api.machine.Callback import li.cil.oc.api.machine.Context @@ -54,7 +55,7 @@ trait InventoryTransfer extends traits.WorldAware with traits.SideRestricted { result(Unit, reason) case _ => val moved = FluidUtils.transferBetweenFluidHandlersAt(sourcePos, sourceSide.getOpposite, sinkPos, sinkSide.getOpposite, count, sourceTank) - if (moved > 0) context.pause(moved / 1000 * 0.25) // Allow up to 4 buckets per second. + if (moved > 0) context.pause(moved / Settings.get.transposerFluidTransferRate) // Allow up to 16 buckets per second. result(moved > 0, moved) } } diff --git a/src/main/scala/li/cil/oc/server/machine/Machine.scala b/src/main/scala/li/cil/oc/server/machine/Machine.scala index 3bc3c81bb..2b187c1ff 100644 --- a/src/main/scala/li/cil/oc/server/machine/Machine.scala +++ b/src/main/scala/li/cil/oc/server/machine/Machine.scala @@ -780,7 +780,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach catch { case t: Throwable => OpenComputers.log.error( - s"""Unexpected error loading a state of computer at (${host.xPosition}, ${host.yPosition}, ${host.zPosition}). """ + + s"""Unexpected error loading a state of computer at ${machinePosition}. """ + s"""State: ${state.headOption.fold("no state")(_.toString)}. Unless you're upgrading/downgrading across a major version, please report this! Thank you.""", t) close() } @@ -862,7 +862,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach catch { case t: Throwable => OpenComputers.log.error( - s"""Unexpected error saving a state of computer at (${host.xPosition}, ${host.yPosition}, ${host.zPosition}). """ + + s"""Unexpected error saving a state of computer at ${machinePosition}. """ + s"""State: ${state.headOption.fold("no state")(_.toString)}. Unless you're upgrading/downgrading across a major version, please report this! Thank you.""", t) } }) @@ -1039,6 +1039,9 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach // Keep track of time spent executing the computer. cpuTotal += System.nanoTime() - cpuStart } + + /** Helper method for printing the machine position in error messages and debug statements. */ + private def machinePosition = s"(${host.xPosition}, ${host.yPosition}, ${host.zPosition}, ${host.world().provider.dimensionId})" } object Machine extends MachineAPI { diff --git a/src/main/scala/li/cil/oc/server/machine/luac/NativeLuaArchitecture.scala b/src/main/scala/li/cil/oc/server/machine/luac/NativeLuaArchitecture.scala index f87d313d1..ec110a64e 100644 --- a/src/main/scala/li/cil/oc/server/machine/luac/NativeLuaArchitecture.scala +++ b/src/main/scala/li/cil/oc/server/machine/luac/NativeLuaArchitecture.scala @@ -376,7 +376,7 @@ abstract class NativeLuaArchitecture(val machine: api.machine.Machine) extends A try lua.gc(LuaState.GcAction.COLLECT, 0) catch { case t: Throwable => - OpenComputers.log.warn(s"Error cleaning up loaded computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}). This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.") + OpenComputers.log.warn(s"Error cleaning up loaded computer @ ${machinePosition}. This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.") machine.crash("error in garbage collector, most likely __gc method timed out") } } catch { @@ -414,19 +414,22 @@ abstract class NativeLuaArchitecture(val machine: api.machine.Machine) extends A try lua.gc(LuaState.GcAction.COLLECT, 0) catch { case t: Throwable => - OpenComputers.log.warn(s"Error cleaning up loaded computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}). This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.") + OpenComputers.log.warn(s"Error cleaning up loaded computer @ ${machinePosition}. This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.") machine.crash("error in garbage collector, most likely __gc method timed out") } } catch { case e: LuaRuntimeException => - OpenComputers.log.warn(s"Could not persist computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}).\n${e.toString}" + (if (e.getLuaStackTrace.isEmpty) "" else "\tat " + e.getLuaStackTrace.mkString("\n\tat "))) + OpenComputers.log.warn(s"Could not persist computer @ ${machinePosition}.\n${e.toString}" + (if (e.getLuaStackTrace.isEmpty) "" else "\tat " + e.getLuaStackTrace.mkString("\n\tat "))) nbt.removeTag("state") case e: LuaGcMetamethodException => - OpenComputers.log.warn(s"Could not persist computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}).\n${e.toString}") + OpenComputers.log.warn(s"Could not persist computer @ ${machinePosition}.\n${e.toString}") nbt.removeTag("state") } // Limit memory again. recomputeMemory(machine.host.internalComponents) } + + /** Helper method for printing the machine position in error messages and debug statements. */ + private def machinePosition = s"(${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}, ${machine.host.world().provider.dimensionId})" }