convert to userdata

This commit is contained in:
Xander 2017-04-19 19:18:51 +08:00
parent 37363127e8
commit 1273968142
2 changed files with 157 additions and 11 deletions

View File

@ -0,0 +1,136 @@
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<Object,Object> emptyMap = new HashMap<Object,Object>();
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) {
NBTBase nbttagcompound = stack.serializeNBT();
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<Integer,Object> map = new TreeMap<Integer,Object>();
for (int i=0; i<this.array.length; i++){
map.put(i, this.array[i] != null ? this.array[i] : emptyMap);
}
return new Object[] { map };
}
public String toString(){
return "{ItemStack Array}";
}
}

View File

@ -4,10 +4,12 @@ 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
import li.cil.oc.api.prefab.ItemStackArrayValue
import li.cil.oc.server.component.result
import li.cil.oc.util.DatabaseAccess
import li.cil.oc.util.{BlockPosition, DatabaseAccess, InventoryUtils}
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.InventoryUtils
import net.minecraft.block.Block
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumFacing
import net.minecraftforge.items.IItemHandler
@ -76,27 +78,35 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ
}
else result(Unit, "not enabled in config")
@Callback(doc = """function(side:number):table -- Get a description of all stacks in the inventory on the specified side of the device.""")
@Callback(doc = """function(side:number):userdata -- Get a description of all stacks in the inventory on the specified side of the device.""")
def getAllStacks(context: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) {
val facing = checkSideForAction(args, 0)
withInventory(facing, inventory => {
var stacks = new Array[AnyRef](inventory.getSizeInventory)
for(i <- 0 to inventory.getSizeInventory - 1){
val stacks = new Array[ItemStack](inventory.getSlots)
for(i <- 0 until inventory.getSlots){
stacks(i) = inventory.getStackInSlot(i)
if (stacks(i) == null) {
stacks(i) = scala.collection.mutable.Map.empty[AnyRef, AnyRef]
}
}
result(stacks)
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] = {
def getInventoryName(context: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) {
val facing = checkSideForAction(args, 0)
withInventory(facing, inventory => result(inventory.getName()))
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.getRegistryName)
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] = {