From dc83623ac13cb2c1f314805ea1d92f6f7b70d365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Thu, 27 Nov 2014 19:07:16 +0100 Subject: [PATCH] Added `geolyzer.store` to save item stack representations of blocks in database components. Closes #654. Expect this to not work for all blocks in existence. In particular blocks that have custom drop logic (e.g. to spawn stacks with NBT tags) will fail to be stored correctly. I'm afraid there's just no way to handle all cases introduced by all the mods out there. So this is good enough. --- .../li/cil/oc/api/event/GeolyzerEvent.java | 1 + .../li/cil/oc/server/component/Geolyzer.scala | 37 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java b/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java index 60b8dd5f4..92269f7eb 100644 --- a/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java +++ b/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java @@ -74,6 +74,7 @@ public abstract class GeolyzerEvent extends Event { * The side of the geolyzer on which the block to scan is located. */ public final ForgeDirection side; + /** * The retrieved data for the block being scanned. */ 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 13a3c4863..5dc708c2f 100644 --- a/src/main/scala/li/cil/oc/server/component/Geolyzer.scala +++ b/src/main/scala/li/cil/oc/server/component/Geolyzer.scala @@ -11,7 +11,12 @@ import li.cil.oc.api.machine.Callback import li.cil.oc.api.machine.Context import li.cil.oc.api.network.Visibility import li.cil.oc.api.prefab +import li.cil.oc.util.BlockPosition +import li.cil.oc.util.DatabaseAccess import li.cil.oc.util.ExtendedArguments._ +import li.cil.oc.util.ExtendedWorld._ +import net.minecraft.item.Item +import net.minecraft.item.ItemStack import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.util.ForgeDirection @@ -45,7 +50,7 @@ class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment { @Callback(doc = """function(side:number[,options:table]):table -- Get some information on a directly adjacent block.""") def analyze(computer: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) { val side = args.checkSide(0, ForgeDirection.VALID_DIRECTIONS: _*) - val localSide = host match { + val globalSide = host match { case rotatable: Rotatable => rotatable.toGlobal(side) case _ => side } @@ -54,10 +59,38 @@ class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment { if (!node.tryChangeBuffer(-Settings.get.geolyzerScanCost)) return result(Unit, "not enough energy") - val event = new Analyze(host, options, localSide) + val event = new Analyze(host, options, globalSide) MinecraftForge.EVENT_BUS.post(event) if (event.isCanceled) result(Unit, "scan was canceled") else result(event.data) } else result(Unit, "not enabled in config") + + @Callback(doc = """function(side:number, dbAddress:string, dbSlot:number):boolean -- Store an item stack representation of the block on the specified side in a database component.""") + def store(computer: Context, args: Arguments): Array[AnyRef] = { + val side = args.checkSide(0, ForgeDirection.VALID_DIRECTIONS: _*) + val globalSide = host match { + case rotatable: Rotatable => rotatable.toGlobal(side) + case _ => side + } + + if (!node.tryChangeBuffer(-Settings.get.geolyzerScanCost)) + return result(Unit, "not enough energy") + + val blockPos = BlockPosition(host).offset(globalSide) + val block = host.world.getBlock(blockPos) + val item = Item.getItemFromBlock(block) + if (item == null) result(Unit, "block has no registered item representation") + else { + val metadata = host.world.getBlockMetadata(blockPos) + val damage = block.damageDropped(metadata) + val stack = new ItemStack(item, 1, damage) + DatabaseAccess.withDatabase(node, args.checkString(1), database => { + val toSlot = args.checkSlot(database.data, 2) + val nonEmpty = database.data.getStackInSlot(toSlot) != null + database.data.setInventorySlotContents(toSlot, stack) + result(nonEmpty) + }) + } + } }