From 352aaefbc56689801f5f4dcd6a1a0a9941bb1bf0 Mon Sep 17 00:00:00 2001 From: payonel Date: Sun, 11 Mar 2018 12:07:53 -0700 Subject: [PATCH] Merge pull request #2075 from thiakil/WorldInventoryAnalytics-updates-pr World Inventory Analytics Improvements closes #2771 --- .../oc/api/prefab/ItemStackArrayValue.java | 137 ++++++++++++++++++ .../traits/WorldInventoryAnalytics.scala | 35 ++++- .../oc/server/machine/luac/UserdataAPI.scala | 5 +- .../oc/server/machine/luaj/UserdataAPI.scala | 5 +- 4 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java diff --git a/src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java b/src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java new file mode 100644 index 0000000000..b842ae2a26 --- /dev/null +++ b/src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java @@ -0,0 +1,137 @@ +package li.cil.oc.api.prefab; + +import li.cil.oc.api.machine.Arguments; +import li.cil.oc.api.machine.Callback; +import li.cil.oc.api.machine.Context; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import java.util.HashMap; +import java.util.TreeMap; + +public class ItemStackArrayValue extends AbstractValue { + + private ItemStack[] array = null; + private int iteratorIndex; + + private static final byte TAGLIST_ID = (new NBTTagList()).getId(); + private static final byte COMPOUND_ID = (new NBTTagCompound()).getId(); + private static final String ARRAY_KEY = "Array"; + private static final String INDEX_KEY = "Index"; + + private static final HashMap emptyMap = new HashMap(); + + public ItemStackArrayValue(ItemStack[] arr){ + if (arr != null){ + this.array = new ItemStack[arr.length]; + for (int i=0; i< arr.length; i++){ + this.array[i] = arr[i] != null ? arr[i].copy() : null; + } + } + this.iteratorIndex = 0; + } + + public ItemStackArrayValue(){ + this(null); + } + + @Override + public Object[] call(Context context, Arguments arguments) { + if (this.array == null) + return null; + if (this.iteratorIndex >= this.array.length) + return null; + int index = this.iteratorIndex++; + if (this.array[index] == null)//TODO 1.11 change to ItemStack.EMPTY? + return new Object[]{ emptyMap }; + return new Object[]{ this.array[index] != null ? this.array[index] : emptyMap }; + } + + @Override + public Object apply(Context context, Arguments arguments) { + if (arguments.count() == 0 || this.array == null) + return null; + if (arguments.isInteger(0)){//index access + int luaIndex = arguments.checkInteger(0); + if (luaIndex > this.array.length || luaIndex < 1){ + return null; + } + return this.array[luaIndex-1]; + } + if (arguments.isString(0)){ + String arg = arguments.checkString(0); + if (arg.equals("n")){ + return this.array.length; + } + } + return null; + } + + @Override + public void load(NBTTagCompound nbt) { + if (nbt.hasKey(ARRAY_KEY, TAGLIST_ID)){ + NBTTagList tagList = nbt.getTagList(ARRAY_KEY,COMPOUND_ID); + this.array = new ItemStack[tagList.tagCount()]; + for (int i = 0; i < tagList.tagCount(); ++i){ + NBTTagCompound el = tagList.getCompoundTagAt(i); + if (el.hasNoTags()) + this.array[i] = null;//TODO 1.11 change to ItemStack.EMPTY? + else + this.array[i] = ItemStack.loadItemStackFromNBT(el); + } + } else { + this.array = null; + } + this.iteratorIndex = nbt.getInteger(INDEX_KEY); + } + + @Override + public void save(NBTTagCompound nbt) { + + NBTTagCompound nullnbt = new NBTTagCompound(); + + if (this.array != null) { + NBTTagList nbttaglist = new NBTTagList(); + for (ItemStack stack : this.array) { + if (stack != null) { + NBTTagCompound nbttagcompound = new NBTTagCompound(); + stack.writeToNBT(nbttagcompound); + nbttaglist.appendTag(nbttagcompound); + } else { + nbttaglist.appendTag(nullnbt); + } + } + + nbt.setTag(ARRAY_KEY, nbttaglist); + } + + nbt.setInteger(INDEX_KEY, iteratorIndex); + } + + @Callback(doc="function():nil -- Reset the iterator index so that the next call will return the first element.") + public Object[] reset(Context context, Arguments arguments) throws Exception { + this.iteratorIndex = 0; + return null; + } + + @Callback(doc="function():number -- Returns the number of elements in the this.array.") + public Object[] count(Context context, Arguments arguments) throws Exception { + return new Object[] { this.array != null ? this.array.length : 0 }; + } + + @Callback(doc="function():table -- Returns ALL the stack in the this.array. Memory intensive.") + public Object[] getAll(Context context, Arguments arguments) throws Exception { + TreeMap map = new TreeMap(); + for (int i=0; i { + val stacks = new Array[ItemStack](inventory.getSizeInventory) + for(i <- 0 until inventory.getSizeInventory){ + stacks(i) = inventory.getStackInSlot(i) + } + result(new ItemStackArrayValue(stacks)) + }) + } + else result(Unit, "not enabled in config") + + @Callback(doc = """function(side:number):string -- Get the the name of the inventory on the specified side of the device.""") + def getInventoryName(context: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) { + val facing = checkSideForAction(args, 0) + def blockAt(position: BlockPosition): Option[Block] = position.world match { + case Some(world) if world.blockExists(position) => world.getBlock(position) match { + case block: Block => Some(block) + case _ => None + } + case _ => None + } + withInventory(facing, inventory => blockAt(position.offset(facing)) match { + case Some(block) => result(block.getUnlocalizedName) + case _ => result(Unit, "Unknown") + }) + } + else result(Unit, "not enabled in config") + @Callback(doc = """function(side:number, slot:number, dbAddress:string, dbSlot:number):boolean -- Store an item stack description in the specified slot of the database with the specified address.""") def store(context: Context, args: Arguments): Array[AnyRef] = { val facing = checkSideForAction(args, 0) diff --git a/src/main/scala/li/cil/oc/server/machine/luac/UserdataAPI.scala b/src/main/scala/li/cil/oc/server/machine/luac/UserdataAPI.scala index 168a19da1e..3d24fe65e0 100644 --- a/src/main/scala/li/cil/oc/server/machine/luac/UserdataAPI.scala +++ b/src/main/scala/li/cil/oc/server/machine/luac/UserdataAPI.scala @@ -8,6 +8,7 @@ import java.io.DataOutputStream import li.cil.oc.OpenComputers import li.cil.oc.api.Persistable import li.cil.oc.api.machine.Value +import li.cil.oc.server.driver.Registry import li.cil.oc.server.machine.ArgumentsImpl import li.cil.oc.util.ExtendedLuaState.extendLuaState import net.minecraft.nbt.CompressedStreamTools @@ -56,7 +57,7 @@ class UserdataAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) { lua.pushScalaFunction(lua => { val value = lua.toJavaObjectRaw(1).asInstanceOf[Value] val args = lua.toSimpleJavaObjects(2) - owner.invoke(() => Array(value.apply(machine, new ArgumentsImpl(args)))) + owner.invoke(() => Registry.convert(Array(value.apply(machine, new ArgumentsImpl(args))))) }) lua.setField(-2, "apply") @@ -73,7 +74,7 @@ class UserdataAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) { lua.pushScalaFunction(lua => { val value = lua.toJavaObjectRaw(1).asInstanceOf[Value] val args = lua.toSimpleJavaObjects(2) - owner.invoke(() => value.call(machine, new ArgumentsImpl(args))) + owner.invoke(() => Registry.convert(value.call(machine, new ArgumentsImpl(args)))) }) lua.setField(-2, "call") diff --git a/src/main/scala/li/cil/oc/server/machine/luaj/UserdataAPI.scala b/src/main/scala/li/cil/oc/server/machine/luaj/UserdataAPI.scala index 6ada183b28..336fc4eea5 100644 --- a/src/main/scala/li/cil/oc/server/machine/luaj/UserdataAPI.scala +++ b/src/main/scala/li/cil/oc/server/machine/luaj/UserdataAPI.scala @@ -2,6 +2,7 @@ package li.cil.oc.server.machine.luaj import li.cil.oc.OpenComputers import li.cil.oc.api.machine.Value +import li.cil.oc.server.driver.Registry import li.cil.oc.server.machine.ArgumentsImpl import li.cil.oc.util.ScalaClosure._ import li.cil.repack.org.luaj.vm2.LuaValue @@ -16,7 +17,7 @@ class UserdataAPI(owner: LuaJLuaArchitecture) extends LuaJAPI(owner) { userdata.set("apply", (args: Varargs) => { val value = args.checkuserdata(1, classOf[Value]).asInstanceOf[Value] val params = toSimpleJavaObjects(args, 2) - owner.invoke(() => Array(value.apply(machine, new ArgumentsImpl(params)))) + owner.invoke(() => Registry.convert(Array(value.apply(machine, new ArgumentsImpl(params))))) }) userdata.set("unapply", (args: Varargs) => { @@ -31,7 +32,7 @@ class UserdataAPI(owner: LuaJLuaArchitecture) extends LuaJAPI(owner) { userdata.set("call", (args: Varargs) => { val value = args.checkuserdata(1, classOf[Value]).asInstanceOf[Value] val params = toSimpleJavaObjects(args, 2) - owner.invoke(() => value.call(machine, new ArgumentsImpl(params))) + owner.invoke(() => Registry.convert(value.call(machine, new ArgumentsImpl(params)))) }) userdata.set("dispose", (args: Varargs) => {